File size: 1,765 Bytes
4553650
9f13621
3748deb
9f13621
 
 
 
 
 
 
 
bdffcf8
99149d9
60bcf8d
99149d9
 
 
3748deb
99149d9
96c379c
 
 
60bcf8d
 
 
 
 
 
3748deb
bdffcf8
dd55ec1
9f13621
a227b91
9f13621
 
dd55ec1
bae3e66
3748deb
 
bae3e66
9f13621
 
3748deb
bae3e66
3748deb
 
bae3e66
 
60bcf8d
 
9f13621
 
96d4a31
bdffcf8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
defmodule MedicalTranscription.Transcription do
  @moduledoc """
  Takes a path to an audio file and transcribes it to text.
  """

  # Ideas for future exploration:
  # - Instead of storing the long description vectors in a binary file on disk, we could store them within a vector DB
  #   (such as pgvector or Pinecone.io)
  # - A potential improvement would be to not code each chunk of transcribed audio separately, but to instead gather
  #   complete sentences based on punctuation. We may want to suggest codes for the entire audio as a single piece as
  #   well
  def stream_transcription_and_search(live_view_pid, audio_file_path) do
    # audio transcription + semantic search
    summary_text =
      audio_file_path
      |> stream_transcription()
      |> Enum.reduce("", fn {chunk, index}, acc ->
        send_result(chunk, index + 1, live_view_pid)

        acc <> chunk.text
      end)

    summary_chunk = %{
      text: summary_text,
      start_timestamp_seconds: nil,
      end_timestamp_seconds: nil
    }

    send_result(summary_chunk, 0, live_view_pid)
  end

  defp stream_transcription(audio_file_path) do
    MedicalTranscription.TranscriptionServing
    |> Nx.Serving.batched_run({:file, audio_file_path})
    |> Stream.with_index()
  end

  defp send_result(chunk, index, live_view_pid) do
    result = %{
      id: index,
      start_mark: format_timestamp(chunk.start_timestamp_seconds),
      end_mark: format_timestamp(chunk.end_timestamp_seconds),
      text: chunk.text
    }

    send(live_view_pid, {:transcription_row, result})
  end

  defp format_timestamp(seconds) when is_nil(seconds), do: nil

  defp format_timestamp(seconds) do
    seconds |> round() |> Time.from_seconds_after_midnight() |> Time.to_string()
  end
end