@@ -5,12 +5,17 @@ use std::time::Duration;
55use anyhow:: { Context , Result , bail} ;
66use clap:: { Parser , ValueEnum } ;
77use cpal:: traits:: { DeviceTrait , HostTrait , StreamTrait } ;
8+ use openai_api_rs:: realtime:: types:: {
9+ AzureSemanticVadConfig , EndOfUtteranceDetectionConfig , EndOfUtteranceDetectionModel ,
10+ EndOfUtteranceThresholdLevel , TurnDetection ,
11+ } ;
812use rodio:: DeviceSinkBuilder ;
913use tokio:: select;
1014use tokio:: sync:: mpsc:: { channel, unbounded_channel} ;
1115
1216use context_switch:: services:: {
1317 AristechTranscribe , AzureTranscribe , ElevenLabsTranscribe , GoogleTranscribe ,
18+ MicrosoftVoiceLiveTranscribe ,
1419} ;
1520use context_switch:: { AudioConsumer , InputModality , OutputModality } ;
1621use context_switch_core:: language:: Languages ;
@@ -44,6 +49,8 @@ enum Provider {
4449 Google ,
4550 #[ value( name = "aristech" ) ]
4651 Aristech ,
52+ #[ value( name = "voice-live" ) ]
53+ VoiceLive ,
4754}
4855
4956#[ tokio:: main]
@@ -343,5 +350,51 @@ async fn start_conversation(
343350 } ;
344351 AristechTranscribe . conversation ( params, conversation) . await
345352 }
353+ Provider :: VoiceLive => {
354+ if diarization {
355+ bail ! ( "--diarization is only supported for the azure provider" ) ;
356+ }
357+ if region. is_some ( ) {
358+ bail ! ( "--region is only supported for the google provider" ) ;
359+ }
360+
361+ let language = Some (
362+ languages
363+ . single ( )
364+ . context ( "Voice Live provider supports exactly one --language value" ) ?
365+ . clone ( ) ,
366+ ) ;
367+ let vad_languages = language. clone ( ) . map ( |lang| vec ! [ lang] ) ;
368+
369+ let params = microsoft_voice_live:: Params {
370+ api_key : env:: var ( "MICROSOFT_VOICE_LIVE_API_KEY" )
371+ . expect ( "MICROSOFT_VOICE_LIVE_API_KEY undefined" ) ,
372+ endpoint : env:: var ( "MICROSOFT_VOICE_LIVE_ENDPOINT" )
373+ . expect ( "MICROSOFT_VOICE_LIVE_ENDPOINT undefined (must be wss://...)" ) ,
374+ model : model. map ( str:: to_owned) . unwrap_or_else ( || {
375+ env:: var ( "MICROSOFT_VOICE_LIVE_MODEL" ) . unwrap_or_else ( |_| "gpt-4.1" . to_owned ( ) )
376+ } ) ,
377+ api_version : env:: var ( "MICROSOFT_VOICE_LIVE_API_VERSION" ) . ok ( ) ,
378+ transcription_model : env:: var ( "MICROSOFT_VOICE_LIVE_TRANSCRIPTION_MODEL" )
379+ . unwrap_or_else ( |_| "azure-speech" . to_owned ( ) ) ,
380+ language,
381+ noise_reduction : None ,
382+ turn_detection : Some ( TurnDetection :: AzureSemanticVadMultilingual (
383+ AzureSemanticVadConfig {
384+ end_of_utterance_detection : Some ( EndOfUtteranceDetectionConfig {
385+ model : EndOfUtteranceDetectionModel :: SmartEndOfTurnDetection ,
386+ threshold_level : Some ( EndOfUtteranceThresholdLevel :: Low ) ,
387+ timeout_ms : Some ( 5000 ) ,
388+ } ) ,
389+ // remove_filler_words: Some(true),
390+ languages : vad_languages,
391+ ..Default :: default ( )
392+ } ,
393+ ) ) ,
394+ } ;
395+ MicrosoftVoiceLiveTranscribe
396+ . conversation ( params, conversation)
397+ . await
398+ }
346399 }
347400}
0 commit comments