defmodule WhisperWeb.AudioChannel do @moduledoc """ Phoenix Channel que gestiona la recepción de audio en tiempo real desde el cliente. El audio se envía en chunks binarios y se acumula en un buffer temporal (`AudioBuffer`). Al recibir el evento `"stop_audio"`, todos los chunks se combinan y se guardan como un único archivo WAV final. """ use Phoenix.Channel require Logger alias Phoenix.PubSub def join("audio:lobby", _payload, socket) do ref = socket_id(socket) Logger.info("Cliente conectado al canal audio:lobby") {:ok, socket} end def handle_in("audio_chunk", {:binary, raw_binary}, socket) do <> = raw_binary <> = rest %{"sample_rate" => rate} = Jason.decode!(header) ref = socket_id(socket) Logger.info("Chunk recibido: #{byte_size(audio)} bytes, sample_rate: #{rate}") AudioBuffer.append(ref, {rate, audio}) {:ok, path} = AudioSaver.save_chunk_as_wav(ref, audio, rate, "part") chunk_number = Whisper.Counter.next(ref) # AudioFilesList.add_file(path) Task.start(fn -> transcription = Whisper.SendToModel.realtime(path) Logger.info("Real-time:\n#{transcription}") chunk_id = "chunk_#{chunk_number}" # <--- un ID común message = %{"chunks" => [%{"text" => transcription, "id" => chunk_id}]} Phoenix.PubSub.broadcast(Whisper.PubSub, "transcription", {:transcription_tiny, Jason.encode!(message)}) transcription_large = Whisper.SendToModel.large(path) Logger.info("✅ Transcripción completa:\n#{transcription_large}") message_large = %{"chunks" => [%{"text" => transcription_large, "id" => chunk_id}]} Phoenix.PubSub.broadcast(Whisper.PubSub, "transcription", {:transcription_large, Jason.encode!(message_large)}) File.rm!(path) end) {:noreply, socket} end def handle_in("stop_audio", _payload, socket) do Logger.info("🛑 Grabación detenida por cliente") # ref = socket_id(socket) # chunks = AudioBuffer.get_and_clear(ref) # if chunks != [] do # [{rate, _} | _] = chunks # full_audio = Enum.map(chunks, fn {_, bin} -> bin end) |> IO.iodata_to_binary() # {:ok, path} = AudioSaver.save_chunk_as_wav(ref, full_audio, rate, "final") # Task.start(fn -> # transcription = Whisper.SendToModel.large(path) # Logger.info("✅ Transcripción completa:\n#{transcription}") # message = %{"chunks" => [%{"text" => transcription}]} # Phoenix.PubSub.broadcast(Whisper.PubSub, "transcription", {:transcription_m, Jason.encode!(message)}) # # File.rm!(path) # end) # end {:noreply, socket} end defp socket_id(socket), do: socket.transport_pid |> :erlang.pid_to_list() |> List.to_string() end