Audio

Week 1F


前言

本來 Chatbot 寫得很開心
有一天主管突然跑來跟我說

「欸欸,你要不要接個 ASR 上去」

於是再度開啟我的語音處理之路


簡介

聲音是一種縱波
一般而言麥克風上有振膜
用來紀錄聲波的振幅
連續的振幅可以形成一個聲音


Sample Rate

採樣率 Sample Rate

是在將聲音
類比訊號轉為數位訊號的過程中
出現的概念

用來表示聲音訊號的取樣頻率
例如 48K 代表一秒取樣 48,000 次


實際應用

現在的麥克風多能錄製到 40K 以上
一般電話多為 8K 左右
但是語音辨識通常 8K 或 16K 就夠了
因此需要做 Downsampling


語音特徵

語音辨識通常會有取特徵的動作
一般透過傅立葉轉換分析音頻
然後計算 FBankMFCC 之類的特徵
取完特徵就能更輕鬆的做機器學習任務


使用單位

語音處理通常使用 Frame 作為單位
常見的單位是 10 ms 作為一個 Frame
也有 20 ms 或 30 ms 的

因此對 16K 的聲音訊號而言
一個 10 ms 的 Frame 會有 160 個樣本點


資料型態

通常使用 Bit Depth 來描述樣本點的資料型態
通常為 16 Bit 也就是 2 Bytes 整數

把樣本直接存起來的檔案也可稱為
Pulse-Code Modulation, PCM

常見的 Wave 檔 (.wav)
就是加了 44 Byte Header 的 PCM


VAD

語音活性檢測 Voice Activity Detection, VAD
用來檢查現在有沒有人在講話
一般而言 VAD 的運算量比較小,而 ASR 運算量比較大
所以通常在 VAD 被觸發一段時間後才開始做 ASR
這樣可以節省計算資源


EPD

端點偵測 End-Point Detection, EPD
與 VAD 不同的地方在於
VAD 只針對某個 Frame 是否為人聲
而 EPD 通常觀察一段連續的 VAD 狀態
用來決定是否啟動語音辨識


ASR

Automatic Speech Recognition
也稱為 Speech-To-Text, STT

傳統 ASR 通常由
聲學模型 Acoustic Model, AM
語言模型 Language Model, LM
所組成


聲學模型

AM 主要的目的是辨識聲音訊號的音節
就好比在辨識我們講話的注音
其結果可能像是「ㄋㄧˊ ㄏㄠˇ ㄚ」


語言模型

LM 則用來看這些音節的順序
可能構成哪些合理的句子
以「ㄋㄧˊ ㄏㄠˇ ㄚ」為例
LM 就會算出「你好啊」的機率比較高
而不是「泥豪阿」


KWS

關鍵詞偵測 Keyword Spotting, KWS
是一種形式比較單純的語音辨識
只辨識特定的關鍵字,來避免語音誤動
像是 Hey Siri 與 OK Google 就是 KWS


Whisper

講了這麼多
其實 Whisper 也不是這種傳統做法
而是直接用 Transformers 訓練一個
Encoder-Decoder 模型


實做環節


安裝錄音套件

透過 PyAudio 套件錄音
Linux 上需要安裝以下套件

sudo apt install portaudio19-dev python3-pyaudio

從麥克風錄音

import pyaudio recorder = pyaudio.PyAudio() stream = recorder.open( format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=160, ) # 10ms = 1 Frame, 5s = 5000ms = 500 Frames frames = [stream.read(160) for _ in range(500)]

存成音檔

透過 Python 內建的 wave 套件存成音檔

import wave with wave.open("output.wav", "wb") as wf: wf.setnchannels(1) wf.setsampwidth(2) # 16 Bits = 2 Bytes wf.setframerate(16000) wf.writeframes(b"".join(frames))

VAD 實做

透過 webrtcvad 套件可以輕鬆達成
每次輸入必須是一個完整的 Frame

import webrtcvad vad = webrtcvad.Vad() vad.set_mode(1) sample_rate = 16000 frame = b"\x00\x00" * 160 # 2 Bit x 1 Frame print(vad.is_speech(frame, sample_rate))

ASR 實做

透過 Faster Whisper 輕鬆調用 ASR 模型

from faster_whisper import WhisperModel model = WhisperModel( "large-v2", device="cuda", compute_type="int8_float16", # 8-Bit Quantization ) segments, info = model.transcribe("audio.mp3") print(f"Language: {info.language}") print(f"Lang Prob: {info.language_probability}") for seg in segments: print(f"[{seg.start:.2f}s -> {seg.end}s] {seg.text}")

實做 EPD

一般而言會需要一個 VAD Buffer
長度大概 80 到 120 個 Frames
當這個 Buffer 假設有 80% 都是觸發狀態
代表發現聲音的開始端點


聲音 Buffer

在進入 ASR 之前
通常會有一個 5 秒的 Buffer 用來存聲音訊號
在 EPD 觸發之後,把這個 Buffer 送入 ASR
避免在 EPD 之前有漏字的狀況


EPD 狀態變換

進入 ASR 階段後持續計算 VAD Buffer
如果 Buffer 只剩 20% 是觸發狀態就結束 ASR
所以會有三個狀態:未觸發 > 觸發 > 完成


Demo

完整程式碼放在 GitHub


Other


ChatGPT & Mathjax

ChatGPT 解釋 Mathjax
成功的例子 | 失敗的例子

ChatGPT 的 Mathjax 真的強
Example 1 | Example 2


VSCode Math Plugin

使用 Markdown+Math 插件
可以在 VSCode 裡面渲染 Mathjax 語法
目的是將數學公式放入 Slides 所以需要設定小括號

{ "mdmath.delimiters": "brackets" }

Qubby AI

Qubby AI

蠻歡樂的應用
有山道猴子的 AI 虛擬形象

Select a repo