@@ -40,19 +40,83 @@ pub struct StreamingAsrModels {
4040 pub tokens : String ,
4141}
4242
43- /// 流式引擎配置(ADR-012 F3-1:rule3 可配置)。
44- #[ derive( Debug , Clone , Copy ) ]
43+ /// 流式引擎配置(ADR-012 F3-1:rule3 可配置;v0.20.1 REQ-265:rule1/2 一并入档——
44+ /// 默认值即原常量,零行为变更;档案化来源:`asr-params.json`(可选,经
45+ /// ENTROPY_ASR_PARAMS_JSON 指定)+ 遗留 env ENTROPY_ASR_RULE3_SECS 覆盖)。
46+ #[ derive( Debug , Clone , PartialEq ) ]
4547pub struct StreamingAsrConfig {
46- /// rule3 最长句强制断句(秒;默认 8s——5s 过短致句中硬切,20s 过长)
48+ /// 端点 rule1:尾静音断句秒数(默认 2.4——sherpa-onnx 惯例)。
49+ pub rule1_min_trailing_silence : f32 ,
50+ /// 端点 rule2:短停顿断句秒数(默认 1.2)。
51+ pub rule2_min_trailing_silence : f32 ,
52+ /// rule3 最长句强制断句(秒;默认 8s——5s 过短致句中硬切,20s 过长)。
4753 pub rule3_min_utterance_secs : f32 ,
4854}
4955
5056impl Default for StreamingAsrConfig {
5157 fn default ( ) -> Self {
52- Self { rule3_min_utterance_secs : 8.0 }
58+ Self {
59+ rule1_min_trailing_silence : 2.4 ,
60+ rule2_min_trailing_silence : 1.2 ,
61+ rule3_min_utterance_secs : 8.0 ,
62+ }
63+ }
64+ }
65+
66+ impl StreamingAsrConfig {
67+ /// 从 asr-params.json(可选)加载:缺失/损坏 → 默认 + 提示(不阻断启动,
68+ /// 同 audio-preproc.json 先例);字段可缺省。
69+ ///
70+ /// @ai-context: JSON 形态 `{"rule1S": 2.4, "rule2S": 1.2, "rule3S": 8.0}`——
71+ /// 字段名沿用 harness 参数注入面的短名,标定结论可直接落档。
72+ pub fn load_from_file ( path : & std:: path:: Path ) -> Self {
73+ let mut cfg = Self :: default ( ) ;
74+ if let Ok ( raw) = std:: fs:: read_to_string ( path) {
75+ match serde_json:: from_str :: < AsrParamsFile > ( & raw ) {
76+ Ok ( f) => {
77+ if let Some ( v) = f. rule1_s {
78+ cfg. rule1_min_trailing_silence = v;
79+ }
80+ if let Some ( v) = f. rule2_s {
81+ cfg. rule2_min_trailing_silence = v;
82+ }
83+ if let Some ( v) = f. rule3_s {
84+ cfg. rule3_min_utterance_secs = v;
85+ }
86+ }
87+ Err ( e) => eprintln ! ( "[AsrParams] asr-params.json 解析失败,使用默认: {}" , e) ,
88+ }
89+ }
90+ cfg
91+ }
92+
93+ /// 档案 + 遗留 env 覆盖(生产装配入口:文件优先、env 最高优先级保持旧行为)。
94+ pub fn from_env ( ) -> Self {
95+ let mut cfg = Self :: default ( ) ;
96+ if let Ok ( p) = std:: env:: var ( "ENTROPY_ASR_PARAMS_JSON" ) {
97+ cfg = Self :: load_from_file ( std:: path:: Path :: new ( & p) ) ;
98+ }
99+ if let Ok ( v) = std:: env:: var ( "ENTROPY_ASR_RULE3_SECS" ) {
100+ if let Ok ( s) = v. parse :: < f32 > ( ) {
101+ cfg. rule3_min_utterance_secs = s;
102+ }
103+ }
104+ cfg
53105 }
54106}
55107
108+ /// asr-params.json 的 serde 形态(字段可缺省)。
109+ #[ derive( Debug , Clone , serde:: Deserialize ) ]
110+ #[ serde( rename_all = "camelCase" ) ]
111+ struct AsrParamsFile {
112+ #[ serde( default ) ]
113+ rule1_s : Option < f32 > ,
114+ #[ serde( default ) ]
115+ rule2_s : Option < f32 > ,
116+ #[ serde( default ) ]
117+ rule3_s : Option < f32 > ,
118+ }
119+
56120/// 流式 ASR 事件(文本事件,时间戳由编排层标注)。
57121#[ derive( Debug , Clone , PartialEq ) ]
58122pub enum StreamingAsrEvent {
@@ -127,10 +191,10 @@ impl StreamingAsrEngine {
127191 // 带 graph 的流,断言 abort(exit 0xffffffff,用户真机日志实证 Decode:101);
128192 // 无热词时同样兼容(beam 搜索对普通流无副作用,识别质量相当或更优)。
129193 recognizer_config. decoding_method = Some ( "modified_beam_search" . into ( ) ) ;
130- // 端点规则:尾静音 2.4s / 1.2s 断句(sherpa-onnx 默认),
131- // rule3 强制断句 = 可配置(ADR-012 F3-1:默认 8s,env 可覆盖 )
132- recognizer_config. rule1_min_trailing_silence = 2.4 ;
133- recognizer_config. rule2_min_trailing_silence = 1.2 ;
194+ // 端点规则:rule1/2/3 来自配置(默认 2.4/1.2/8.0 即原常量,零行为变更;
195+ // 档案/覆盖来源见 StreamingAsrConfig::from_env/load_from_file )
196+ recognizer_config. rule1_min_trailing_silence = config . rule1_min_trailing_silence ;
197+ recognizer_config. rule2_min_trailing_silence = config . rule2_min_trailing_silence ;
134198 recognizer_config. rule3_min_utterance_length = config. rule3_min_utterance_secs ;
135199
136200 let recognizer = OnlineRecognizer :: create ( & recognizer_config)
0 commit comments