refactor(asr): 抽出共享 pcm_duration_ms
(pcm.len()/2)*1000/16000 这段时长换算原本在 foundry/sherpa_runtime/ sherpa_provider/whisper/mimo 五处各自重复(带魔法数 2/16000)。收口到新 模块 asr/pcm.rs(pcm_duration_ms + pcm_duration_ms_from_bytes),各处改为 薄封装调用,参考 wav::encode_wav_16k_mono 的共享先例。行为不变。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
72f9ced533
commit
db51e95fde
7 files changed
+45
-6
No files matched your search
@@ -148,7 +148,7 @@ impl crate::recorder::AudioConsumer for FoundryLocalWhisperAsr {
|
||||
}
|
||||
|
||||
fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
(pcm.len() as u64 / 2) * 1000 / 16_000
|
||||
crate::asr::pcm::pcm_duration_ms(pcm)
|
||||
}
|
||||
|
||||
fn pcm_to_wav(pcm: &[u8]) -> Vec<u8> {
|
||||
|
||||
@@ -222,11 +222,11 @@ impl crate::recorder::AudioConsumer for SherpaOnnxAsr {
|
||||
}
|
||||
|
||||
fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
pcm_duration_ms_from_bytes(pcm.len() as u64)
|
||||
crate::asr::pcm::pcm_duration_ms(pcm)
|
||||
}
|
||||
|
||||
fn pcm_duration_ms_from_bytes(bytes: u64) -> u64 {
|
||||
(bytes / 2) * 1000 / 16_000
|
||||
crate::asr::pcm::pcm_duration_ms_from_bytes(bytes)
|
||||
}
|
||||
|
||||
fn trim_transcript_text(text: &str) -> String {
|
||||
|
||||
@@ -485,7 +485,7 @@ fn accumulate_dir_size(dir: &Path, bytes: &mut u64) {
|
||||
}
|
||||
|
||||
fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
(pcm.len() as u64 / 2) * 1000 / 16_000
|
||||
crate::asr::pcm::pcm_duration_ms(pcm)
|
||||
}
|
||||
|
||||
enum LoadedModel {
|
||||
|
||||
@@ -178,7 +178,7 @@ pub fn extract_mimo_text(json: &Value) -> String {
|
||||
}
|
||||
|
||||
fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
(pcm.len() as u64 / PCM_BYTES_PER_SAMPLE as u64) * 1000 / PCM_SAMPLE_RATE_HZ
|
||||
super::pcm::pcm_duration_ms(pcm)
|
||||
}
|
||||
|
||||
fn split_pcm_by_duration(pcm: &[u8], max_chunk_duration_ms: u64) -> Vec<&[u8]> {
|
||||
|
||||
@@ -9,6 +9,7 @@ pub mod bailian;
|
||||
mod frame;
|
||||
pub mod local;
|
||||
pub mod mimo;
|
||||
pub mod pcm;
|
||||
pub mod volcengine;
|
||||
pub mod wav;
|
||||
pub mod whisper;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//! 共享 PCM 时长计算。
|
||||
//!
|
||||
//! 录音统一是 16 kHz / 单声道 / 16-bit 小端 PCM,时长换算 `(字节数 / 2) * 1000 / 16000`
|
||||
//! 原本散落在各 ASR provider 里重复(foundry / sherpa / whisper / mimo),这里收口成
|
||||
//! 唯一实现,各处改为薄封装调用(参考 `wav::encode_wav_16k_mono` 的共享先例)。
|
||||
|
||||
/// 每个采样的字节数(16-bit → 2 字节)。
|
||||
const PCM_BYTES_PER_SAMPLE: u64 = 2;
|
||||
/// 采样率(16 kHz)。
|
||||
const PCM_SAMPLE_RATE_HZ: u64 = 16_000;
|
||||
|
||||
/// 由原始字节数计算 16 kHz / 单声道 / 16-bit PCM 的时长(毫秒)。
|
||||
pub fn pcm_duration_ms_from_bytes(bytes: u64) -> u64 {
|
||||
(bytes / PCM_BYTES_PER_SAMPLE) * 1000 / PCM_SAMPLE_RATE_HZ
|
||||
}
|
||||
|
||||
/// 由 PCM 字节切片计算 16 kHz / 单声道 / 16-bit PCM 的时长(毫秒)。
|
||||
pub fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
pcm_duration_ms_from_bytes(pcm.len() as u64)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn one_second_of_16k_i16_pcm_is_1000ms() {
|
||||
// 16000 采样 × 2 字节 = 32000 字节 = 1 秒
|
||||
assert_eq!(pcm_duration_ms(&vec![0u8; 32_000]), 1000);
|
||||
assert_eq!(pcm_duration_ms_from_bytes(32_000), 1000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn odd_trailing_byte_is_floored() {
|
||||
// 末尾半个采样向下取整,与历史行为一致
|
||||
assert_eq!(pcm_duration_ms(&vec![0u8; 33]), pcm_duration_ms(&vec![0u8; 32]));
|
||||
}
|
||||
}
|
||||
@@ -285,7 +285,7 @@ fn extract_confident_text(json: &serde_json::Value) -> String {
|
||||
}
|
||||
|
||||
fn pcm_duration_ms(pcm: &[u8]) -> u64 {
|
||||
(pcm.len() as u64 / PCM_BYTES_PER_SAMPLE as u64) * 1000 / PCM_SAMPLE_RATE_HZ
|
||||
super::pcm::pcm_duration_ms(pcm)
|
||||
}
|
||||
|
||||
fn split_pcm_by_duration(pcm: &[u8], max_chunk_duration_ms: Option<u64>) -> Vec<&[u8]> {
|
||||
|
||||
Reference in new issue
Block a user