@@ -3096,6 +3096,42 @@ mod tests {
30963096 ) ;
30973097 }
30983098
3099+ #[ test]
3100+ fn local_qwen_timeout_floors_at_global_timeout_for_short_audio ( ) {
3101+ // 5s 录音:5 × 0.6 = 3, +10 = 13, max(15) = 15。短录音保留 15s 兜底。
3102+ assert_eq ! (
3103+ local_qwen_transcribe_timeout( 5.0 ) ,
3104+ std:: time:: Duration :: from_secs( COORDINATOR_GLOBAL_TIMEOUT_SECS )
3105+ ) ;
3106+ }
3107+
3108+ #[ test]
3109+ fn local_qwen_timeout_scales_with_audio_duration ( ) {
3110+ // 60s 录音:60 × 0.6 = 36, +10 = 46s。覆盖 RTF ≈ 0.5 的边界。
3111+ assert_eq ! (
3112+ local_qwen_transcribe_timeout( 60.0 ) ,
3113+ std:: time:: Duration :: from_secs( 46 )
3114+ ) ;
3115+ }
3116+
3117+ #[ test]
3118+ fn local_qwen_timeout_ceils_partial_seconds ( ) {
3119+ // 10.1s 录音:10.1 × 0.6 = 6.06, ceil = 7, +10 = 17, max(15) = 17。
3120+ assert_eq ! (
3121+ local_qwen_transcribe_timeout( 10.1 ) ,
3122+ std:: time:: Duration :: from_secs( 17 )
3123+ ) ;
3124+ }
3125+
3126+ #[ test]
3127+ fn local_qwen_timeout_handles_zero_duration ( ) {
3128+ // 0 时长(空 buffer 边界):0 × 0.6 = 0, +10 = 10, max(15) = 15。
3129+ assert_eq ! (
3130+ local_qwen_transcribe_timeout( 0.0 ) ,
3131+ std:: time:: Duration :: from_secs( COORDINATOR_GLOBAL_TIMEOUT_SECS )
3132+ ) ;
3133+ }
3134+
30993135 #[ cfg( target_os = "windows" ) ]
31003136 #[ test]
31013137 fn foundry_release_uses_foundry_keep_loaded_preference ( ) {
@@ -3597,6 +3633,17 @@ fn foundry_audio_transcribe_timeout_duration() -> std::time::Duration {
35973633 std:: time:: Duration :: from_secs ( COORDINATOR_GLOBAL_TIMEOUT_SECS )
35983634}
35993635
3636+ /// 本地 Qwen3-ASR 的动态转写超时。固定 15 秒在长录音(≥ 30s)+ 慢机器
3637+ /// (RTF ≈ 0.3–0.5)上必然超时把整段内容丢掉。改用 max(15, ceil(audio_s
3638+ /// × 0.6) + 10):基础保留 15s 兜住短录音;长录音按音频长度的 0.6 倍 +
3639+ /// 10s 余量,覆盖 RTF ≤ 0.5 的机器。
3640+ fn local_qwen_transcribe_timeout ( audio_secs : f64 ) -> std:: time:: Duration {
3641+ let secs = ( ( audio_secs * 0.6 ) . ceil ( ) as u64 )
3642+ . saturating_add ( 10 )
3643+ . max ( COORDINATOR_GLOBAL_TIMEOUT_SECS ) ;
3644+ std:: time:: Duration :: from_secs ( secs)
3645+ }
3646+
36003647/// 检查 begin_session 的 await 间隙是否被 cancel_session 打断。
36013648/// 必须在持有 state lock 的瞬间读,结果一拿就过期,所以用 helper 名字提醒只在
36023649/// 「准备做下一步副作用前」用。
0 commit comments