pub struct Vad { /* private fields */ }Expand description
ストリーミング VAD。1 インスタンスが ONNX Session を 1 つ持つ(共有しない)。
任意長の &[f32] を Vad::process に流すと、内部で frame (16k=512) 単位に束ねて
silero 推論し、セグメント状態機械を回して確定したイベントを返す。
Implementations§
Source§impl Vad
impl Vad
Sourcepub fn new(config: VadConfig) -> Result<Vad, VadError>
pub fn new(config: VadConfig) -> Result<Vad, VadError>
埋め込みモデルをロードして VAD を構築する。
Examples found in repository?
13fn main() {
14 // 決定的入力: 440Hz サイン振幅 0.5。
15 let n = 16000usize;
16 let mut samples = Vec::with_capacity(n);
17 for i in 0..n {
18 let v = 0.5f32 * (2.0f32 * std::f32::consts::PI * 440.0 * (i as f32) / 16000.0).sin();
19 samples.push(v);
20 }
21
22 let mut vad = Vad::new(VadConfig::default()).expect("model load");
23 // 一括投入。内部で 512 窓に束ねて推論し、生確率を取り出す。
24 vad.process(&samples);
25 let probs = vad.last_frame_probabilities();
26
27 for p in probs.iter().take(10) {
28 println!("{p:.6}");
29 }
30}Sourcepub fn process(&mut self, samples: &[f32]) -> Vec<VadEvent>
pub fn process(&mut self, samples: &[f32]) -> Vec<VadEvent>
任意長の f32 サンプルを処理し、確定した VadEvent を返す。
内部で frame_size 単位に束ね、満たないサンプルは次回まで保持する。サンプル位置は 呼び出しをまたいで連続する(累積)。
Examples found in repository?
13fn main() {
14 // 決定的入力: 440Hz サイン振幅 0.5。
15 let n = 16000usize;
16 let mut samples = Vec::with_capacity(n);
17 for i in 0..n {
18 let v = 0.5f32 * (2.0f32 * std::f32::consts::PI * 440.0 * (i as f32) / 16000.0).sin();
19 samples.push(v);
20 }
21
22 let mut vad = Vad::new(VadConfig::default()).expect("model load");
23 // 一括投入。内部で 512 窓に束ねて推論し、生確率を取り出す。
24 vad.process(&samples);
25 let probs = vad.last_frame_probabilities();
26
27 for p in probs.iter().take(10) {
28 println!("{p:.6}");
29 }
30}Sourcepub fn process_pcm(
&mut self,
samples: &[f32],
input_sample_rate: u32,
input_channels: u16,
) -> Vec<VadEvent>
pub fn process_pcm( &mut self, samples: &[f32], input_sample_rate: u32, input_channels: u16, ) -> Vec<VadEvent>
録音チャンクをそのまま渡せる自己完結の入口。任意フォーマット(input_sample_rate /
input_channels の interleaved f32)を内部で mono 化・VAD レートへリサンプルしてから
Vad::process と同じ経路にかける。
各言語バインディングが録音チャンク(例 48k/stereo)を変換せずそのまま流せるようにする
のが狙い。samples は interleaved で、長さは input_channels の倍数を想定する
(端数フレームは次回まで内部に持ち越すので、任意の位置で分割して渡してよい)。
入力が既に VAD レート(VadConfig::sample_rate)の mono なら、mono 化もリサンプル
もせず Vad::process へそのまま渡す(追加コストなし)。それ以外は各チャンネルの
平均で mono 化し、rubato でリサンプルする。リサンプラは呼び出しをまたいで状態を持つ
ので、連続ストリームでも継ぎ目は出ない。
返す VadEvent の at_sample は VAD 内部レート(config().sample_rate=16000
か 8000)のサンプル基準で、入力サンプル基準ではない(リサンプル後の内部位置の累積)。
Vad::process と揃えてあるので両者を混ぜても位置は連続する。秒に直すなら
at_sample as f64 / config().sample_rate as f64、入力サンプル位置の目安が要るなら
at_sample * input_sample_rate / config().sample_rate で近似できる。
リサンプラの構築や実行に失敗した場合(極端なレート比など)は、その呼び出し分を捨てて
空のイベント列を返す(取り込みを panic で止めない。Vad::process が推論失敗を無音に
倒すのと同じ方針)。
Sourcepub fn last_frame_probabilities(&self) -> &[f32]
pub fn last_frame_probabilities(&self) -> &[f32]
直近 Vad::process で計算した各フレームの生発話確率を返す。
セグメントイベントとは独立した第二の出力。
Examples found in repository?
13fn main() {
14 // 決定的入力: 440Hz サイン振幅 0.5。
15 let n = 16000usize;
16 let mut samples = Vec::with_capacity(n);
17 for i in 0..n {
18 let v = 0.5f32 * (2.0f32 * std::f32::consts::PI * 440.0 * (i as f32) / 16000.0).sin();
19 samples.push(v);
20 }
21
22 let mut vad = Vad::new(VadConfig::default()).expect("model load");
23 // 一括投入。内部で 512 窓に束ねて推論し、生確率を取り出す。
24 vad.process(&samples);
25 let probs = vad.last_frame_probabilities();
26
27 for p in probs.iter().take(10) {
28 println!("{p:.6}");
29 }
30}