Module: RubyLLM::Protocols::Deepgram::StreamingTranscription
- Defined in:
- lib/ruby_llm/protocols/deepgram/streaming_transcription.rb
Overview
:nodoc: all
Instance Method Summary collapse
- #build_live_transcription(segments, metadata, model:, language:) ⇒ Object
- #process_transcription_result(event, segments) {|TranscriptionChunk.new(type: TranscriptionChunk::SEGMENT, delta:, segment:, raw: event)| ... } ⇒ Object
- #send_transcription_audio(socket, audio) ⇒ Object
- #stream_live_transcription(audio_file, model:, language:, speaker_names:, provider_options:, prompt:, &block) ⇒ Object
- #streaming_transcription_url(model:, language:, speaker_names:, provider_options:, prompt:) ⇒ Object
Instance Method Details
#build_live_transcription(segments, metadata, model:, language:) ⇒ Object
80 81 82 83 84 85 |
# File 'lib/ruby_llm/protocols/deepgram/streaming_transcription.rb', line 80 def build_live_transcription(segments, , model:, language:) RubyLLM::Transcription.new( text: segments.map { |segment| segment.fetch('text') }.join(' '), model:, language:, duration: ['duration'], segments:, words: segments.flat_map { |segment| segment['words'] || [] } ) end |
#process_transcription_result(event, segments) {|TranscriptionChunk.new(type: TranscriptionChunk::SEGMENT, delta:, segment:, raw: event)| ... } ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/ruby_llm/protocols/deepgram/streaming_transcription.rb', line 58 def process_transcription_result(event, segments) alternative = event.dig('channel', 'alternatives', 0) || {} text = alternative['transcript'].to_s return if text.empty? unless event['is_final'] yield TranscriptionChunk.new(type: TranscriptionChunk::PARTIAL, text:, raw: event) return end delta = segments.empty? ? text : " #{text}" segment = { 'text' => text, 'start' => event['start'], 'end' => event['start'].to_f + event['duration'].to_f, 'channel' => event.dig('channel_index', 0), 'words' => alternative['words'] }.compact segments << segment yield TranscriptionChunk.new(type: TranscriptionChunk::SEGMENT, delta:, segment:, raw: event) end |
#send_transcription_audio(socket, audio) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'lib/ruby_llm/protocols/deepgram/streaming_transcription.rb', line 49 def send_transcription_audio(socket, audio) offset = 0 while offset < audio.bytesize socket.send_binary(audio.byteslice(offset, 16_384)) offset += 16_384 end socket.send_text(JSON.generate(type: 'CloseStream')) end |
#stream_live_transcription(audio_file, model:, language:, speaker_names:, provider_options:, prompt:, &block) ⇒ Object
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 |
# File 'lib/ruby_llm/protocols/deepgram/streaming_transcription.rb', line 7 def stream_live_transcription(audio_file, model:, language:, speaker_names:, provider_options:, prompt:, &block) = Attachment.wrap(audio_file, config: @config) raise ArgumentError, 'Transcription requires exactly one audio file' unless .one? track_usage(:transcription) do url = streaming_transcription_url(model:, language:, speaker_names:, provider_options:, prompt:) segments = [] = nil @usage_tracker.start Transport::WebsocketConnection.open(url, headers: @provider.headers, config: @config) do |socket| write = ->(connection) { send_transcription_audio(connection, .first.content) } socket.(write:) do || event = JSON.parse() case event['type'] when 'Results' process_transcription_result(event, segments, &block) when 'Metadata' = event when 'Error' raise Error, event['description'] || event['message'] || 'Deepgram transcription failed' end end end raise Error, 'Deepgram transcription ended before its completion metadata' unless result = build_live_transcription(segments, , model:, language:) block.call(TranscriptionChunk.new(type: TranscriptionChunk::DONE, text: result.text, raw: )) result end end |
#streaming_transcription_url(model:, language:, speaker_names:, provider_options:, prompt:) ⇒ Object
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ruby_llm/protocols/deepgram/streaming_transcription.rb', line 38 def streaming_transcription_url(model:, language:, speaker_names:, provider_options:, prompt:) params = { model:, language:, smart_format: true, interim_results: true } params[:diarize_model] = DIARIZE_MODEL if speaker_names params[:keyterm] = Array(prompt) if prompt params.merge!() params = params.compact.flat_map { |key, value| Array(value).map { |item| [key, item] } } uri = URI.join("#{@provider.api_base.sub(%r{/+\z}, '')}/", "v1/listen?#{URI.encode_www_form(params)}") uri.scheme = uri.scheme == 'https' ? 'wss' : 'ws' uri.to_s end |