whisper.cpp en tiempo real con tiny
This commit is contained in:
@ -12,6 +12,8 @@ defmodule Recognition_VAD.Application do
|
||||
{DNSCluster, query: Application.get_env(:recognition_VAD, :dns_cluster_query) || :ignore},
|
||||
{Phoenix.PubSub, name: Recognition_VAD.PubSub},
|
||||
Recognition_VAD.AudioProcessor,
|
||||
Recognition_VAD.WhisperStreamer,
|
||||
|
||||
# Start the Finch HTTP client for sending emails
|
||||
{Finch, name: Recognition_VAD.Finch},
|
||||
# Start a worker by calling: Recognition_VAD.Worker.start_link(arg)
|
||||
|
46
recognition_VAD/lib/recognition_VAD/whisper.ex
Normal file
46
recognition_VAD/lib/recognition_VAD/whisper.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule Recognition_VAD.Whisper do
|
||||
@default_model "ggml-tiny.bin"
|
||||
@script_path "/home/aime-pc2/i_m/whisper.cpp/transcribe.sh"
|
||||
require Logger
|
||||
|
||||
def transcribe(path, model \\ @default_model) do
|
||||
path_to_run = convert_path_to_wsl(path)
|
||||
|
||||
args = [@script_path, path_to_run, model]
|
||||
|
||||
case System.cmd("wsl", args, stderr_to_stdout: true) do
|
||||
{output, 0} ->
|
||||
text = extract_transcription(output)
|
||||
Logger.info("📝 Transcripción: #{text}")
|
||||
{:ok, text}
|
||||
|
||||
{error_output, _} ->
|
||||
Logger.error("❌ Error al transcribir con whisper: #{error_output}")
|
||||
{:error, error_output}
|
||||
end
|
||||
end
|
||||
|
||||
defp convert_path_to_wsl(path) do
|
||||
if String.starts_with?(path, "C:/") do
|
||||
path
|
||||
|> String.replace_prefix("C:/", "/mnt/c/")
|
||||
|> String.replace("\\", "/")
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
defp extract_transcription(output) do
|
||||
output
|
||||
|> String.split("\n")
|
||||
|> Enum.filter(fn line ->
|
||||
line =~ ~r/[\p{L}\p{N}]/u and
|
||||
not String.starts_with?(line, "whisper_") and
|
||||
not String.starts_with?(line, "system_info") and
|
||||
not String.starts_with?(line, "main: ") and
|
||||
not String.starts_with?(line, "whisper_print_timings:")
|
||||
end)
|
||||
|> Enum.join(" ")
|
||||
|> String.trim()
|
||||
end
|
||||
end
|
56
recognition_VAD/lib/recognition_VAD/whisper_streamer.ex
Normal file
56
recognition_VAD/lib/recognition_VAD/whisper_streamer.ex
Normal file
@ -0,0 +1,56 @@
|
||||
defmodule Recognition_VAD.WhisperStreamer do
|
||||
use GenServer
|
||||
require Logger
|
||||
|
||||
@transcribe_interval 2000 # cada 2 segundos
|
||||
@max_chunks 100 # máximo a mantener en memoria
|
||||
|
||||
def start_link(_opts) do
|
||||
GenServer.start_link(__MODULE__, %{chunks: [], sample_rate: 48000}, name: __MODULE__)
|
||||
end
|
||||
|
||||
def push_chunk(chunk, sample_rate) do
|
||||
GenServer.cast(__MODULE__, {:chunk, chunk, sample_rate})
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(state) do
|
||||
schedule_transcription()
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast({:chunk, binary, sr}, %{chunks: chunks} = state) do
|
||||
new_chunks = [binary | chunks] |> Enum.take(@max_chunks)
|
||||
{:noreply, %{state | chunks: new_chunks, sample_rate: sr}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:transcribe_timer, %{chunks: []} = state) do
|
||||
# Si no hay audio, solo reprogramamos
|
||||
schedule_transcription()
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:transcribe_timer, %{chunks: chunks, sample_rate: sr} = state) do
|
||||
Task.start(fn ->
|
||||
path = "C:/Users/rolan/i_m/voice_recognition/recognition_VAD/tmp/realtime_#{System.system_time(:millisecond)}.wav"
|
||||
:ok = Recognition_VAD.WavWriter.write_pcm_chunks_to_wav(Enum.reverse(chunks), sr, path)
|
||||
|
||||
case Recognition_VAD.Whisper.transcribe(path) do
|
||||
{:ok, text} when byte_size(text) > 0 ->
|
||||
Phoenix.PubSub.broadcast(Recognition_VAD.PubSub, "audio_output", {:realtime, %{"text" => text}})
|
||||
|
||||
_ ->
|
||||
Logger.debug("⏱ Nada para transcribir o error")
|
||||
end
|
||||
end)
|
||||
|
||||
schedule_transcription()
|
||||
{:noreply, %{state | chunks: []}}
|
||||
end
|
||||
|
||||
defp schedule_transcription do
|
||||
Process.send_after(self(), :transcribe_timer, @transcribe_interval)
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user