80 lines
2.3 KiB
Elixir
80 lines
2.3 KiB
Elixir
defmodule RiverConnectWeb.AudioChannel do
|
|
use RiverConnectWeb, :channel
|
|
alias RiverConnect.Audio
|
|
|
|
@impl true
|
|
def join("audio:lobby", _payload, socket) do
|
|
{:ok, socket}
|
|
end
|
|
|
|
@impl true
|
|
def handle_in("audio_start", %{"id" => id}, socket) do
|
|
# Ensure upload directory exists
|
|
upload_path = Application.app_dir(:river_connect, "priv/static/uploads")
|
|
File.mkdir_p!(upload_path)
|
|
|
|
user_id = socket.assigns[:user_id] || "guest"
|
|
|
|
# Create DB record immediately with "recording" status
|
|
{:ok, message} =
|
|
Audio.create_message(%{
|
|
user_id: user_id,
|
|
file_path: "/uploads/#{id}.webm",
|
|
status: "recording"
|
|
})
|
|
|
|
# Store temporary file path and message_id in socket assigns
|
|
temp_file_path = Path.join(upload_path, "#{id}.webm")
|
|
|
|
# Broadcast start and new message to other listeners
|
|
broadcast_from!(socket, "audio_start", %{id: id})
|
|
broadcast!(socket, "audio_message_created", %{message: message})
|
|
|
|
{:noreply,
|
|
assign(socket, :current_recording, %{id: id, path: temp_file_path, message_id: message.id})}
|
|
end
|
|
|
|
@impl true
|
|
def handle_in("audio_chunk", {:binary, payload}, socket) do
|
|
case socket.assigns[:current_recording] do
|
|
%{path: path} ->
|
|
# Append binary chunk to file
|
|
File.write!(path, payload, [:append])
|
|
# Broadcast chunk to other listeners for live playback
|
|
broadcast_from!(socket, "audio_chunk", %{data: Base.encode64(payload)})
|
|
{:noreply, socket}
|
|
|
|
_ ->
|
|
{:noreply, socket}
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def handle_in("audio_end", %{"duration_ms" => duration_ms}, socket) do
|
|
case socket.assigns[:current_recording] do
|
|
%{message_id: message_id} ->
|
|
message = Audio.get_message!(message_id)
|
|
|
|
# Update DB record to "processing" status
|
|
{:ok, message} =
|
|
Audio.update_message(message, %{
|
|
duration_ms: duration_ms,
|
|
status: "processing"
|
|
})
|
|
|
|
# Queue Oban job for processing
|
|
%{id: message.id}
|
|
|> RiverConnect.Workers.ProcessRecording.new()
|
|
|> Oban.insert!()
|
|
|
|
# Notify UI that message status changed
|
|
broadcast!(socket, "audio_message_ready", %{id: message.id})
|
|
|
|
{:noreply, assign(socket, :current_recording, nil)}
|
|
|
|
_ ->
|
|
{:noreply, socket}
|
|
end
|
|
end
|
|
end
|