語音識別——根據聲波能量、VAD 和 頻譜分析實時輸出文字

SenseVoiceSmall網絡結構圖 

ASR(語音識別)是將音頻信息轉化為文字的技術。在實時語音識別中,一個關鍵問題是:如何決定將采集的音頻數據輸入大模型的最佳時機?固定時間間隔顯然不夠靈活,太短可能導致頻繁調用模型,太長則會延遲文字輸出。有沒有更智能的方式?答案是肯定的。

一種常見的解決方案是使用 webrtcvad 庫中的 Vad(VAD_MODE) 方法。它通過分析音頻波動來判斷是否有人說話,從而決定是否觸發語音識別。然而,我在實際測試中發現,這種方法在某些場景下不夠靈敏,尤其是在白噪音較大或較小的環境中,難以做到真正的自適應。

為了解決這一問題,我嘗試了一種更綜合的驗證方式:結合 聲波能量VAD頻譜分析,通過多重驗證來判斷音頻中是否包含語音活動。這種方法不僅能更精準地捕捉語音信號,還能有效過濾背景噪音,確保實時輸出的準確性。

在模型選擇上,我推薦使用 SenseVoiceSmall。這款模型在實時語音識別任務中表現優秀,既能保持高準確率,又能兼顧效率。openai推出的IWhisper也可以試試其效果,我主要識別的語言是中文,暫時還沒試過這個模型。此外,值得一提的是,魔搭社區(ModelScope)提供了豐富的模型資源和詳細的調用代碼。如果你對語音識別感興趣,這里是一個值得探索的平臺。雖然它和 Hugging Face有些相似,但作為國產社區,它在本地化支持和模型適配上有著獨特的優勢,值得推薦。

SenseVoiceSmall性能如下:

import pyaudio
import webrtcvad
import numpy as np
from pypinyin import pinyin, Style  # 如果后續需要用,可按需使用
import refrom funasr import AutoModel
from funasr.utils.postprocess_utils import rich_transcription_postprocess
from modelscope.pipelines import pipeline# 參數配置
AUDIO_RATE = 16000       # 采樣率(支持8000, 16000, 32000或48000)
CHUNK_SIZE = 480         # 每塊大小(30ms,保證為10/20/30ms的倍數)
VAD_MODE = 1             # VAD 模式(0-3,數值越小越保守)# 初始化 VAD
vad = webrtcvad.Vad(VAD_MODE)# 初始化 ASR 模型
sound_rec_model = AutoModel(model=r"D:\Downloads\SenseVoiceSmall",trust_remote_code=True,remote_code="./model.py",vad_model="fsmn-vad",vad_kwargs={"max_single_segment_time": 30000},device="cuda:0",use_itn=True,disable_update = True,disable_pbar = True,disable_log = True)# 初始化說話人驗證模型(如果需要后續使用)
# sv_pipeline = pipeline(
#     task='speaker-verification',
#     model=r'D:\Downloads\speech_campplus_sv_zh-cn_3dspeaker_16k'
# )def calibrate(stream, calibration_seconds=2, chunk_duration_ms=30):"""校準背景噪音:錄制指定時長的音頻,計算平均幅值與標準差,從而設置自適應閾值參數:calibration_seconds: 校準時間(秒)chunk_duration_ms: 每塊時長(毫秒)返回:amplitude_threshold: 設定的音頻幅值閾值"""print("開始校準背景噪音,請保持安靜...")amplitudes = []num_frames = int(calibration_seconds * (1000 / chunk_duration_ms))for _ in range(num_frames):audio_chunk = stream.read(CHUNK_SIZE, exception_on_overflow=False)audio_data = np.frombuffer(audio_chunk, dtype=np.int16)amplitudes.append(np.abs(audio_data).mean())mean_noise = np.mean(amplitudes)std_noise = np.std(amplitudes)amplitude_threshold = mean_noise + 2 * std_noiseprint(f"校準完成:噪音均值={mean_noise:.2f},標準差={std_noise:.2f},設置閾值={amplitude_threshold:.2f}")return amplitude_thresholdclass SpeechDetector:"""SpeechDetector 負責處理音頻塊,結合能量預處理、VAD 和頻譜分析進行語音檢測,并在檢測到語音結束后調用 ASR 模型進行轉寫,返回識別結果文本。"""def __init__(self, amplitude_threshold):self.amplitude_threshold = amplitude_threshold# 音頻緩沖區,用于存儲當前語音段的音頻數據self.speech_buffer = bytearray()# 連續幀狀態,用于平滑判斷語音是否開始/結束self.speech_state = False          # True:正在錄入語音;False:非語音狀態self.consecutive_speech = 0        # 連續語音幀計數self.consecutive_silence = 0       # 連續靜音幀計數self.required_speech_frames = 2    # 連續語音幀達到此值后確認進入語音狀態(例如 2 幀大約 60ms)self.required_silence_frames = 15  # 連續靜音幀達到此值后確認語音結束(例如 15 幀大約 450ms)self.long_silence_frames = 67    # 連續靜音幀達到此值后確認語音結束(例如 34 幀大約 1s)def analyze_spectrum(self, audio_chunk):"""通過頻譜分析檢測語音特性:1. 對音頻塊應用漢寧窗后計算 FFT2. 統計局部峰值數量(峰值必須超過均值的1.5倍)3. 當峰值數量大于等于3時,認為該塊具有語音特征"""audio_data = np.frombuffer(audio_chunk, dtype=np.int16)if len(audio_data) == 0:return False# 應用漢寧窗減少 FFT 泄露window = np.hanning(len(audio_data))windowed_data = audio_data * window# 計算 FFT 并取正頻率部分spectrum = np.abs(np.fft.rfft(windowed_data))spectral_mean = np.mean(spectrum)peak_count = 0for i in range(1, len(spectrum) - 1):if (spectrum[i] > spectrum[i - 1] and spectrum[i] > spectrum[i + 1] and spectrum[i] > spectral_mean * 1.5):peak_count += 1return peak_count >= 3def is_speech(self, audio_chunk):"""判斷當前音頻塊是否包含語音:1. 先通過能量閾值預過濾低幅值數據2. 再結合 VAD 檢測與頻譜分析判斷"""threshold = self.amplitude_threshold if self.amplitude_threshold is not None else 11540.82audio_data = np.frombuffer(audio_chunk, dtype=np.int16)amplitude = np.abs(audio_data).mean()if amplitude < threshold:return Falsevad_result = vad.is_speech(audio_chunk, AUDIO_RATE)spectral_result = self.analyze_spectrum(audio_chunk)return vad_result and spectral_resultdef process_chunk(self, audio_chunk):"""處理每個音頻塊,并在識別到語音結束后返回文本結果。工作流程:- 若檢測到語音:* 增加連續語音幀計數(consecutive_speech),清零靜音幀計數* 若達到語音起始幀閾值,則進入語音狀態* 處于語音狀態時,將當前音頻塊追加到緩沖區- 若檢測為靜音:* 累計靜音幀數,同時清零語音計數* 若處于語音狀態且靜音幀達到設定閾值,認為當前語音段結束,則調用 ASR 模型進行識別,并返

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77033.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77033.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77033.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI大模型如何重塑科研范式:從“假說驅動”到“數據涌現”

??個人主頁??:慌ZHANG-CSDN博客 ????期待您的關注 ???? 一、引言:科研進入“模型共研”時代 傳統科研范式通常以“假設→實驗→驗證→理論”的方式推進,這一經典路徑建立在人類的認知能力與邏輯推理基礎上。然而,隨著數據規模的爆炸式增長與知識系統的高度復雜…

使用Python寫入JSON、XML和YAML數據到Excel文件

在當今數據驅動的技術生態中&#xff0c;JSON、XML和YAML作為主流結構化數據格式&#xff0c;因其層次化表達能力和跨平臺兼容性&#xff0c;已成為系統間數據交換的通用載體。然而&#xff0c;當需要將這類半結構化數據轉化為具備直觀可視化、動態計算和協作共享特性的載體時&…

面試題:Eureka和Nocas的區別

Eureka 與 Nacos 核心區別對比 一、功能定位與核心能力 ?維度??Eureka??Nacos??核心功能?專注服務注冊與發現&#xff0c;無配置管理功能?:ml-citation{ref“1,3” data“citationList”}集成服務注冊、發現、配置管理、動態DNS等?:ml-citation{ref“1,3” data“c…

2025年4月15日 百度一面 面經

目錄 1. 代理相關 從靜態代理到動態代理 2. cglib可以代理被final修飾的類嗎,為什么 3. JVM 體系結構 4. 垃圾回收算法 5. 什么是注解 如何使用 底層原理 6. synchronized和reentrantlock 7. 講一下你項目中 redis的分布式鎖 與java自帶的鎖有啥區別 8. post 請求和 ge…

AI改變生活

AI改變生活 人工智能&#xff08;AI&#xff09;在我們生活中的應用越來越廣泛&#xff0c;深刻地改變了我們的工作和生活方式。以下是一些AI實際應用的實例&#xff0c;以及它們如何影響我們的日常生活。 1. 智能助手 智能助手如Siri、Alexa和Google Assistant等&#xff0…

信奧賽之c++基礎(取模運算與數位分離)

?? 數字拆解大冒險——取模運算與數位分離魔法課 ?? 第一章:糖果分裝術——取模運算 ?? 分糖果游戲 7顆糖每人分3顆: 每人得到:7 / 3 = 2顆剩余糖果:7 % 3 = 1顆(%就是取模符號) 就像把糖果裝袋后剩下的零散糖粒!?? 取模運算說明書 算式比喻結果10 % 310顆糖分…

揭秘大數據 | 21、軟件定義計算

老夫先將這個小系列的前兩篇內容鏈接奉上&#xff0c;方便感興趣的朋友一氣讀之。 揭秘大數據 | 19、軟件定義的世界-CSDN博客 揭秘大數據 | 20、軟件定義數據中心-CSDN博客 今天&#xff0c;書接上文&#xff0c;開聊軟件定義計算的那些事兒&#xff01; 虛擬化是軟件定義…

FPGA-DDS技術的波形發生器

1.實驗目的 1.1掌握直接數字頻率合成&#xff08;DDS&#xff09;的基本原理及其實現方法。 1.2在DE2-115 FPGA開發板上設計一個可調頻率的正弦波和方波發生器&#xff0c;頻率范圍10Hz~5MHz&#xff0c;最小分辨率小于1kHz。 1.3使用Quartus II進行仿真&#xff0c;并通過S…

LeetCode[541]反轉字符串Ⅱ

思路&#xff1a; 題目給我們加了幾個規則&#xff0c;剩余長度小于2k&#xff0c;大于等于k就反轉k個&#xff0c;小于k就全部反轉&#xff0c;我們按照這個邏輯來就行。 第一就是大于等于k就反轉k個&#xff0c;我們for循環肯定是i2k了&#xff0c;接下來就是判斷是否大于等于…

實現定長的內存池

池化技術 所謂的池化技術&#xff0c;就是程序預先向系統申請過量的資源&#xff0c;然后自己管理起來&#xff0c;以備不時之需。這個操作的價值就是&#xff0c;如果申請與釋放資源的開銷較大&#xff0c;提前申請資源并在使用后并不釋放而是重復利用&#xff0c;能夠提高程序…

路由器原理與配置技術詳解

一、路由基礎原理 1.1 路由器的核心功能 網絡層設備&#xff1a;工作在OSI參考模型第三層&#xff0c;實現不同網絡間的互聯互通智能路徑選擇&#xff1a;基于路由表為數據包選擇最優傳輸路徑協議轉換&#xff1a;處理不同網絡接口間的協議差異&#xff08;如以太網與PPP&…

Leetcode 3518. Smallest Palindromic Rearrangement II

Leetcode 3518. Smallest Palindromic Rearrangement II 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;Leetcode 3518. Smallest Palindromic Rearrangement II 1. 解題思路 這一題是題目Leetcode 3517. Smallest Palindromic Rearrangement I的升級版本&#xff0c;其主要的…

大模型——Crawl4AI 中的數據提取策略

大模型——Crawl4AI 中的數據提取策略 在本章中,將詳細介紹在 Crawl4AI 中可用的數據提取策略。這些策略包括: LLMExtractionStrategy:用于詳細內容提取。JsonCssExtractionStrategy:使用 CSS 選擇器進行結構化數據檢索。CosineStrategy:基于余弦相似性進行有效的語義分段…

職坐標解碼互聯網行業轉型發展新動能

當前&#xff0c;互聯網行業正以前所未有的速度重塑全球產業格局。工信部最新數據顯示&#xff0c;我國互聯網企業營收連續三年保持雙位數增長&#xff0c;其中百強企業在人工智能、物聯網等領域的投入強度同比提升40%&#xff0c;展現出強勁的技術引領力。與此同時&#xff0c…

linux多線(進)程編程——(4)進程間的傳音術(命名管道)

前言&#xff08;前情回顧&#xff09; 進程君&#xff08;父進程&#xff09;在開發出匿名管道這門傳音術后&#xff0c;解決了和自己孩子&#xff08;子進程&#xff09;間的溝通問題&#xff0c;父子關系趨于融洽。和孩子溝通后&#xff0c;進程君發現&#xff0c;自己脫離…

在IDEA里面建立maven項目(便于java web使用)

具體步驟&#xff1a; 第一次有的電腦你再創建項目的時候右下角會提醒你彈窗&#xff1a;讓你下載沒有的東西 一定要下載&#xff01;&#xff01;可能會很慢 運行結果&#xff1a; 因為他是默認的8080端口所以在運行的時候輸入的url如下圖&#xff1a; 新建了一個controller代…

【13】數據結構之樹結構篇章

目錄標題 樹Tree樹的定義樹的基本概念樹的存儲結構雙親表示法孩子表示法孩子兄弟表示法 二叉樹二叉樹與度不超過&#xff12;的普通樹的不同之處二叉樹的基本形態二叉樹的分類二叉樹的性質 二叉樹的順序存儲二叉樹的鏈式存儲二叉樹的鏈式存儲的結點結構樹的遍歷先序遍歷中序遍歷…

雷達生命探測儀,地震救援的生命探測先鋒|鼎躍安全

在地震、山體滑坡、坍塌建筑等突發災害中&#xff0c;會嚴重摧毀建筑物&#xff0c;造成倒塌和人員被困&#xff1b;在瓦礫堆、混凝土板層中&#xff0c;受困人員的生命安全常常面臨嚴峻威脅。傳統救援手段通常存在響應時間長、監測精度有限等不足。 救援現場往往環境復雜&…

512天,倔強生長:一位技術創作者的獨白

親愛的讀者與同行者&#xff1a; 我是倔強的石頭_&#xff0c;今天是我在CSDN成為創作者的第512天。當系統提示我寫下這篇紀念日文章時&#xff0c;我恍惚間想起了2023年11月19日的那個夜晚——指尖敲下《開端——》的標題&#xff0c;忐忑又堅定地按下了“發布”鍵。那時的我…

數據結構*集合框架順序表-ArrayList

集合框架 常見的集合框架 什么是順序表 順序表是一種線性表數據結構&#xff0c;它借助一組連續的存儲單元來依次存儲線性表中的數據元素。一般情況下采用數組存儲。 在數組上完成數據的增刪查改。 自定義簡易版的順序表 代碼展示&#xff1a; public interface IArray…