mirror of
https://github.com/ClaperCo/Claper.git
synced 2026-09-01 19:49:11 +02:00
Refactor code
This commit is contained in:
@@ -60,7 +60,9 @@ defmodule Claper.Transcriptions.MistralRealtimeClient do
|
||||
|
||||
@impl true
|
||||
def handle_info(:send_session_update, state) do
|
||||
session_config = %{"audio_format" => %{"encoding" => "pcm_s16le", "sample_rate" => 16000}}
|
||||
session_config = %{
|
||||
"audio_format" => %{"encoding" => "pcm_s16le", "sample_rate" => 16_000}
|
||||
}
|
||||
|
||||
message = Jason.encode!(%{"type" => "session.update", "session" => session_config})
|
||||
{:reply, {:text, message}, state}
|
||||
@@ -74,47 +76,8 @@ defmodule Claper.Transcriptions.MistralRealtimeClient do
|
||||
@impl true
|
||||
def handle_frame({:text, msg}, state) do
|
||||
case Jason.decode(msg) do
|
||||
{:ok, %{"type" => "session.created"} = event} ->
|
||||
Logger.info("MistralRealtimeClient: session created")
|
||||
send(state.callback_pid, {:mistral_event, :session_created, event})
|
||||
{:ok, %{state | session_ready: true}}
|
||||
|
||||
{:ok, %{"type" => "session.updated"}} ->
|
||||
Logger.info("MistralRealtimeClient: session updated, ready for audio")
|
||||
{:ok, state}
|
||||
|
||||
{:ok, %{"type" => "transcription.text.delta", "text" => text}} ->
|
||||
send(state.callback_pid, {:mistral_event, :text_delta, text})
|
||||
{:ok, state}
|
||||
|
||||
{:ok, %{"type" => "transcription.segment", "text" => text}} ->
|
||||
send(state.callback_pid, {:mistral_event, :segment, text})
|
||||
{:ok, state}
|
||||
|
||||
{:ok, %{"type" => "transcription.done"} = event} ->
|
||||
text = Map.get(event, "text", "")
|
||||
send(state.callback_pid, {:mistral_event, :done, text})
|
||||
{:ok, state}
|
||||
|
||||
{:ok, %{"type" => "transcription.language"} = event} ->
|
||||
lang = Map.get(event, "audioLanguage") || Map.get(event, "language")
|
||||
|
||||
Logger.info("MistralRealtimeClient: detected language #{lang}")
|
||||
send(state.callback_pid, {:mistral_event, :language, lang})
|
||||
{:ok, state}
|
||||
|
||||
{:ok, %{"type" => "error"} = event} ->
|
||||
error_msg = get_in(event, ["error", "message"]) || "unknown error"
|
||||
Logger.error("MistralRealtimeClient: error - #{error_msg}")
|
||||
send(state.callback_pid, {:mistral_event, :error, error_msg})
|
||||
{:ok, state}
|
||||
|
||||
{:ok, event} ->
|
||||
Logger.info(
|
||||
"MistralRealtimeClient: unhandled event type #{inspect(event["type"])} payload=#{inspect(event)}"
|
||||
)
|
||||
|
||||
{:ok, state}
|
||||
handle_event(event, state)
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error("MistralRealtimeClient: failed to parse: #{inspect(reason)}")
|
||||
@@ -134,6 +97,56 @@ defmodule Claper.Transcriptions.MistralRealtimeClient do
|
||||
{:reconnect, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "session.created"} = event, state) do
|
||||
Logger.info("MistralRealtimeClient: session created")
|
||||
send(state.callback_pid, {:mistral_event, :session_created, event})
|
||||
{:ok, %{state | session_ready: true}}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "session.updated"}, state) do
|
||||
Logger.info("MistralRealtimeClient: session updated, ready for audio")
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "transcription.text.delta", "text" => text}, state) do
|
||||
send(state.callback_pid, {:mistral_event, :text_delta, text})
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "transcription.segment", "text" => text}, state) do
|
||||
send(state.callback_pid, {:mistral_event, :segment, text})
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "transcription.done"} = event, state) do
|
||||
text = Map.get(event, "text", "")
|
||||
send(state.callback_pid, {:mistral_event, :done, text})
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "transcription.language"} = event, state) do
|
||||
lang = Map.get(event, "audioLanguage") || Map.get(event, "language")
|
||||
|
||||
Logger.info("MistralRealtimeClient: detected language #{lang}")
|
||||
send(state.callback_pid, {:mistral_event, :language, lang})
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(%{"type" => "error"} = event, state) do
|
||||
error_msg = get_in(event, ["error", "message"]) || "unknown error"
|
||||
Logger.error("MistralRealtimeClient: error - #{error_msg}")
|
||||
send(state.callback_pid, {:mistral_event, :error, error_msg})
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp handle_event(event, state) do
|
||||
Logger.info(
|
||||
"MistralRealtimeClient: unhandled event type #{inspect(event["type"])} payload=#{inspect(event)}"
|
||||
)
|
||||
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
defp get_api_key do
|
||||
Claper.Settings.get_transcription_api_key()
|
||||
end
|
||||
|
||||
@@ -40,10 +40,7 @@ defmodule Claper.Transcriptions.TranscriptionWorker do
|
||||
|
||||
@impl true
|
||||
def init({event_uuid, presentation_file_id}) do
|
||||
unless Claper.Settings.transcription_globally_enabled?() do
|
||||
Logger.info("TranscriptionWorker: transcription globally disabled, not starting")
|
||||
{:stop, :transcription_disabled}
|
||||
else
|
||||
if Claper.Settings.transcription_globally_enabled?() do
|
||||
Logger.info("TranscriptionWorker started for event #{event_uuid}")
|
||||
|
||||
config_language =
|
||||
@@ -72,6 +69,9 @@ defmodule Claper.Transcriptions.TranscriptionWorker do
|
||||
Logger.error("Failed to connect to Mistral realtime API: #{inspect(reason)}")
|
||||
{:stop, reason}
|
||||
end
|
||||
else
|
||||
Logger.info("TranscriptionWorker: transcription globally disabled, not starting")
|
||||
{:stop, :transcription_disabled}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -106,11 +106,9 @@ defmodule ClaperWeb.AdminLive.EventLive do
|
||||
transcriptions = socket.assigns.transcriptions
|
||||
|
||||
content =
|
||||
transcriptions
|
||||
|> Enum.map(fn t ->
|
||||
Enum.map_join(transcriptions, "\n", fn t ->
|
||||
"[#{Calendar.strftime(t.inserted_at, "%Y-%m-%d %H:%M:%S")}] #{t.text}"
|
||||
end)
|
||||
|> Enum.join("\n")
|
||||
|
||||
{:noreply,
|
||||
push_event(socket, "download_csv", %{
|
||||
|
||||
@@ -26,91 +26,95 @@ defmodule ClaperWeb.EventLive.Manage do
|
||||
|> put_flash(:error, gettext("Event doesn't exist"))
|
||||
|> redirect(to: "/")}
|
||||
else
|
||||
if connected?(socket) do
|
||||
Claper.Events.Event.subscribe(event.uuid)
|
||||
Presentations.subscribe(event.presentation_file.id)
|
||||
Events.subscribe_user_events(socket.assigns.current_user.id)
|
||||
end
|
||||
|
||||
posts = list_all_posts(socket, event.uuid)
|
||||
pinned_posts = list_pinned_posts(socket, event.uuid)
|
||||
questions = list_all_questions(socket, event.uuid)
|
||||
form_submits = list_form_submits(socket, event.presentation_file.id)
|
||||
|
||||
audio_token =
|
||||
Phoenix.Token.sign(ClaperWeb.Endpoint, "audio_token", %{
|
||||
user_id: socket.assigns.current_user.id,
|
||||
event_uuid: event.uuid
|
||||
})
|
||||
|
||||
transcription_config =
|
||||
Transcriptions.get_transcription_config(event.presentation_file.id)
|
||||
|
||||
transcription_globally_enabled = Claper.Settings.transcription_globally_enabled?()
|
||||
|
||||
# Auto-start transcription worker if config says enabled and globally enabled
|
||||
if connected?(socket) && transcription_globally_enabled && transcription_config &&
|
||||
transcription_config.enabled do
|
||||
unless Claper.Transcriptions.TranscriptionWorker.running?(event.uuid) do
|
||||
DynamicSupervisor.start_child(
|
||||
Claper.TranscriptionSupervisor,
|
||||
{Claper.Transcriptions.TranscriptionWorker, {event.uuid, event.presentation_file.id}}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:interaction_modal, false)
|
||||
|> assign(:settings_modal, false)
|
||||
|> assign(:attendees_nb, 0)
|
||||
|> assign(:event, event)
|
||||
|> assign(:sort_questions_by, "date")
|
||||
|> assign(:state, event.presentation_file.presentation_state)
|
||||
|> assign(:audio_token, audio_token)
|
||||
|> assign(:transcription_config, transcription_config)
|
||||
|> assign(:transcription_globally_enabled, transcription_globally_enabled)
|
||||
|> stream(:posts, posts)
|
||||
|> stream(:questions, questions)
|
||||
|> stream(:pinned_posts, pinned_posts)
|
||||
|> stream(:form_submits, form_submits)
|
||||
|> assign(:pinned_post_count, length(pinned_posts))
|
||||
|> assign(:question_count, length(questions))
|
||||
|> assign(:post_count, length(posts))
|
||||
|> assign(
|
||||
:total_interactions,
|
||||
Claper.Interactions.get_number_total_interactions(event.presentation_file.id)
|
||||
)
|
||||
|> assign(
|
||||
:form_submit_count,
|
||||
length(form_submits)
|
||||
)
|
||||
|> assign(:create, nil)
|
||||
|> assign(:list_tab, :posts)
|
||||
|> assign(:create_action, :new)
|
||||
|> assign(
|
||||
:missing_slide_thumbnails,
|
||||
Presentations.missing_slide_thumbnails?(event.presentation_file)
|
||||
)
|
||||
|> assign(:thumbnail_cache_bust, thumbnail_cache_bust())
|
||||
|> assign(:thumbnail_regeneration_in_progress, false)
|
||||
|> push_event("page-manage", %{
|
||||
current_page: event.presentation_file.presentation_state.position,
|
||||
timeout: 500
|
||||
})
|
||||
|> then(fn s ->
|
||||
if transcription_config && transcription_config.enabled do
|
||||
push_event(s, "transcription-state", %{enabled: true})
|
||||
else
|
||||
s
|
||||
end
|
||||
end)
|
||||
|> interactions_at_position(event.presentation_file.presentation_state.position)
|
||||
|
||||
{:ok, socket}
|
||||
mount_event(socket, event)
|
||||
end
|
||||
end
|
||||
|
||||
defp mount_event(socket, event) do
|
||||
if connected?(socket) do
|
||||
Claper.Events.Event.subscribe(event.uuid)
|
||||
Presentations.subscribe(event.presentation_file.id)
|
||||
Events.subscribe_user_events(socket.assigns.current_user.id)
|
||||
end
|
||||
|
||||
posts = list_all_posts(socket, event.uuid)
|
||||
pinned_posts = list_pinned_posts(socket, event.uuid)
|
||||
questions = list_all_questions(socket, event.uuid)
|
||||
form_submits = list_form_submits(socket, event.presentation_file.id)
|
||||
|
||||
audio_token =
|
||||
Phoenix.Token.sign(ClaperWeb.Endpoint, "audio_token", %{
|
||||
user_id: socket.assigns.current_user.id,
|
||||
event_uuid: event.uuid
|
||||
})
|
||||
|
||||
transcription_config =
|
||||
Transcriptions.get_transcription_config(event.presentation_file.id)
|
||||
|
||||
transcription_globally_enabled = Claper.Settings.transcription_globally_enabled?()
|
||||
|
||||
# Auto-start transcription worker if config says enabled and globally enabled
|
||||
if connected?(socket) && transcription_globally_enabled && transcription_config &&
|
||||
transcription_config.enabled do
|
||||
unless Claper.Transcriptions.TranscriptionWorker.running?(event.uuid) do
|
||||
DynamicSupervisor.start_child(
|
||||
Claper.TranscriptionSupervisor,
|
||||
{Claper.Transcriptions.TranscriptionWorker, {event.uuid, event.presentation_file.id}}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:interaction_modal, false)
|
||||
|> assign(:settings_modal, false)
|
||||
|> assign(:attendees_nb, 0)
|
||||
|> assign(:event, event)
|
||||
|> assign(:sort_questions_by, "date")
|
||||
|> assign(:state, event.presentation_file.presentation_state)
|
||||
|> assign(:audio_token, audio_token)
|
||||
|> assign(:transcription_config, transcription_config)
|
||||
|> assign(:transcription_globally_enabled, transcription_globally_enabled)
|
||||
|> stream(:posts, posts)
|
||||
|> stream(:questions, questions)
|
||||
|> stream(:pinned_posts, pinned_posts)
|
||||
|> stream(:form_submits, form_submits)
|
||||
|> assign(:pinned_post_count, length(pinned_posts))
|
||||
|> assign(:question_count, length(questions))
|
||||
|> assign(:post_count, length(posts))
|
||||
|> assign(
|
||||
:total_interactions,
|
||||
Claper.Interactions.get_number_total_interactions(event.presentation_file.id)
|
||||
)
|
||||
|> assign(
|
||||
:form_submit_count,
|
||||
length(form_submits)
|
||||
)
|
||||
|> assign(:create, nil)
|
||||
|> assign(:list_tab, :posts)
|
||||
|> assign(:create_action, :new)
|
||||
|> assign(
|
||||
:missing_slide_thumbnails,
|
||||
Presentations.missing_slide_thumbnails?(event.presentation_file)
|
||||
)
|
||||
|> assign(:thumbnail_cache_bust, thumbnail_cache_bust())
|
||||
|> assign(:thumbnail_regeneration_in_progress, false)
|
||||
|> push_event("page-manage", %{
|
||||
current_page: event.presentation_file.presentation_state.position,
|
||||
timeout: 500
|
||||
})
|
||||
|> then(fn s ->
|
||||
if transcription_config && transcription_config.enabled do
|
||||
push_event(s, "transcription-state", %{enabled: true})
|
||||
else
|
||||
s
|
||||
end
|
||||
end)
|
||||
|> interactions_at_position(event.presentation_file.presentation_state.position)
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
defp leader?(%{assigns: %{current_user: current_user}} = _socket, event) do
|
||||
Claper.Events.led_by?(current_user.email, event) || event.user.id == current_user.id
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ defmodule Claper.Transcriptions.MistralRealtimeClientTest do
|
||||
assert %{
|
||||
"type" => "session.update",
|
||||
"session" => %{
|
||||
"audio_format" => %{"encoding" => "pcm_s16le", "sample_rate" => 16000}
|
||||
"audio_format" => %{"encoding" => "pcm_s16le", "sample_rate" => 16_000}
|
||||
}
|
||||
} = Jason.decode!(message)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user