9个版本
新版本 0.2.5 | 2024年8月22日 |
---|---|
0.2.4 | 2024年8月20日 |
0.2.3 | 2024年5月23日 |
0.2.2 | 2023年8月1日 |
0.1.2 | 2023年7月22日 |
#98 在 音频 中排名
430 每月下载量
在 2 crates 中使用
175KB
841 行
Mel Spec
Mel Spec是一个Rust语言的实现,它将Mel谱图与whisper.cpp、pytorch和librosa的参考实现结果对齐,适用于流式音频。
使用方法
要使用库的主要功能
use mel_spec::prelude::*
与librosa相匹配的Mel滤波器组
与librosa和whisper GGML模型嵌入的滤波器在1.0e-7范围内相同的Mel滤波器组。
let file_path = "./testdata/mel_filters.npz";
let f = File::open(file_path).unwrap();
let mut npz = NpzReader::new(f).unwrap();
let filters: Array2<f32> = npz.by_index(0).unwrap();
let want: Array2<f64> = filters.mapv(|x| f64::from(x));
let sampling_rate = 16000.0;
let fft_size = 400;
let n_mels = 80;
let f_min = None;
let f_max = None;
let hkt = false;
let norm = true;
let got = mel(sampling_rate, fft_size, n_mels, f_min, f_max, hkt, norm);
assert_eq!(got.shape(), vec![80, 201]);
for i in 0..80 {
assert_nearby!(got.row(i), want.row(i), 1.0e-7);
}
使用短时傅里叶变换进行谱图
与pytorch和whisper.cpp相匹配的 overlap-and-save STFT。
该实现适用于处理流式音频,并在返回FFT结果之前积累正确数量的数据。
let fft_size = 8;
let hop_size = 4;
let mut spectrogram = Spectrogram::new(fft_size, hop_size);
// Add PCM audio samples
let frames: Vec<f32> = vec![1.0, 2.0, 3.0];
if let Some(fft_frame) = spectrogram.add(&frames) {
// use fft result
}
STFT谱图到Mel谱图
MelSpectrogram将预计算的滤波器组应用于FFT结果。结果与whisper.cpp和whisper.py相同
let fft_size = 400;
let sampling_rate = 16000.0;
let n_mels = 80;
let mut mel = MelSpectrogram::new(fft_size, sampling_rate, n_mels);
// Example input data for the FFT
let fft_input = Array1::from(vec![Complex::new(1.0, 0.0); fft_size]);
// Add the FFT data to the MelSpectrogram
let mel_spec = stage.add(fft_input);
从音频创建Mel谱图。
该库包含基本的音频辅助工具和一个用于处理PCM音频并创建可以发送到whisper.cpp的Mel谱图的管道。
它还具有使用边缘检测(可能是一种新颖的方法)进行语音活动检测的功能,以实时识别词/语音边界。
// load the whisper jfk sample
let file_path = "../testdata/jfk_f32le.wav";
let file = File::open(&file_path).unwrap();
let data = parse_wav(file).unwrap();
let samples = deinterleave_vecs_f32(&data.data, 1);
let fft_size = 400;
let hop_size = 160;
let n_mels = 80;
let sampling_rate = 16000.0;
let mel_settings = MelConfig::new(fft_size, hop_size, n_mels, sampling_rate);
let vad_settings = DetectionSettings::new(1.0, 10, 5, 0, 100);
let config = PipelineConfig::new(mel_settings, Some(vad_settings));
let mut pl = Pipeline::new(config);
let handles = pl.start();
// chunk size can be anything, 88 is random
for chunk in samples[0].chunks(88) {
let _ = pl.send_pcm(chunk);
}
pl.close_ingress();
while let Ok((_, mel_spectrogram)) = pl.rx().recv() {
// do something with spectrogram
}
保存Mel谱图到文件
Mel谱图可以保存为Tga格式 - 一种由OSX和Windows支持的未压缩图像格式。
由于这些图像直接编码了量化的Mel谱图数据,因此它们代表了音频数据的“照片负片”,whisper.cpp可以在无需直接音频输入的情况下开发和打印。
tga
文件在库的大部分测试中代替实际音频使用。这些文件在语音到文本方面是无损的,它们编码了模型在原始音频视图中所能获取的所有信息,并将产生相同的结果。
请注意,时域中的频谱图必须具有偶数列,否则Whisper将会产生幻觉。如果使用核心方法,库会处理这个问题。
let file_path = "../testdata/jfk_full_speech_chunk0_golden.tga";
let dequantized_mel = load_tga_8bit(file_path).unwrap();
// dequantized_mel can be sent straight to whisper.cpp
❯ ffmpeg -hide_banner -loglevel error -i ~/Downloads/JFKWHA-001-AU_WR.mp3 -f f32le -ar 16000 -acodec pcm_f32le -ac 1 pipe:1 | ./target/debug/tga_whisper -t ../../doc/cutsec_46997.tga
...
whisper_init_state: Core ML model loaded
Got 1
the quest for peace.
和平的追求。
语音活动检测
我想到使用Sobel算子来完成这个任务,因为在梅尔频谱图中,语音的梯度是清晰的。
总体思路是在频谱图中勾勒结构,然后找到适合切割的垂直间隙 - 以便在近乎实时地将新的频谱图传递给模型。
更多详细信息请参阅主仓库中的README。
依赖关系
~13MB
~217K SLoC