本地語音識別 Whisper NAS 部署:faster-whisper 轉寫教程

在 NAS 本地部署 Whisper 語音識別的實用教程:使用 faster-whisper 轉寫音視頻,選擇 tiny/base/small/medium 模型,輸出 TXT/SRT,配置 VAD 過濾、CPU/GPU compute_type,並處理批量轉寫與隱私邊界。

把 Whisper 部署到 NAS,最適合的場景不是追求“實時會議字幕”,而是把家庭錄像、訪談、課程錄音、播客和會議文件放進一個私有目錄後,按需或批量生成文字稿和 SRT 字幕。

對大多數 NAS,推薦從 faster-whisper 開始。它使用 CTranslate2 推理引擎,能使用 CPU 或 CUDA GPU,並支持量化、VAD 靜音過濾和詞級時間戳。先用小模型跑通流程,再按準確率和等待時間決定是否升級模型。

先說結論

NAS 本地語音識別的最穩妥路線是:

1
2
3
4
5
6
准备输入 / 输出目录
-> 安装 ffmpeg 与 faster-whisper
-> 用短音频跑 small 或 base
-> 检查 TXT 和 SRT
-> 开启 VAD 过滤
-> 再做批量任务、GPU 加速或 Docker 封装

沒有獨顯的 NAS 也能轉寫,但應把它當成離線任務。若要頻繁轉寫長視頻、多人錄音或追求更快響應,GPU 的作用通常比單純增加硬盤容量更明顯。

模型怎麼選

Whisper 有不同大小的模型。模型越大,通常越能處理口音、噪聲和複雜語境,但推理更慢、內存需求也更高。

模型 NAS 上的建議 適合場景
tiny / base 測試流程、低功耗 NAS 清晰短音頻、快速預覽
small 多數家庭 NAS 的起點 普通中文會議、課程、視頻字幕
medium CPU NAS 通常較慢;有 GPU 再嘗試 噪聲較多、專業術語較多的音頻
large-v3 / turbo 更適合顯存充足的 GPU 主機 高質量離線轉寫、長音頻批處理

不要只以模型名判斷效果。錄音清晰度、說話人重疊、背景音樂、麥克風距離和專有名詞,往往比從 small 升到更大模型更影響最終文字稿。

目錄規劃:輸入、輸出和模型緩存分開

以 Linux NAS 爲例:

1
2
3
mkdir -p ~/asr/inbox
mkdir -p ~/asr/out
mkdir -p ~/asr/models

建議約定:

1
2
3
~/asr/inbox/   放 MP3、M4A、WAV、MP4 等输入文件
~/asr/out/     放 TXT、SRT、JSON 等结果
~/asr/models/  放下载的模型缓存

批量任務最怕輸入、輸出和模型緩存混在同一個目錄裏。分開後,備份、清理和權限控制都更簡單。

安裝環境

在 Debian/Ubuntu 類 NAS 或 Linux 容器內,先安裝基礎工具:

1
2
sudo apt update
sudo apt install -y python3 python3-venv ffmpeg

創建獨立虛擬環境:

1
2
3
4
python3 -m venv ~/asr/.venv
source ~/asr/.venv/bin/activate
pip install --upgrade pip
pip install faster-whisper

ffmpeg 用來讀取常見音視頻格式。沒有它時,MP4、M4A 或某些編碼格式可能無法正常轉碼或讀取。

最小轉寫腳本

~/asr/transcribe.py 寫入下面代碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pathlib import Path
from faster_whisper import WhisperModel

input_file = Path("/home/USER/asr/inbox/sample.mp3")
output_dir = Path("/home/USER/asr/out")
output_dir.mkdir(parents=True, exist_ok=True)

model = WhisperModel(
    "small",
    device="cpu",
    compute_type="int8",
    download_root="/home/USER/asr/models",
)

segments, info = model.transcribe(
    str(input_file),
    language="zh",
    vad_filter=True,
    word_timestamps=True,
)

segments = list(segments)

lines = []
for segment in segments:
    text = segment.text.strip()
    lines.append(text)
    print(f"[{segment.start:.2f} -> {segment.end:.2f}] {text}")

(output_dir / f"{input_file.stem}.txt").write_text(
    "\n".join(lines), encoding="utf-8"
)

把代碼中的 /home/USER 改成你的實際 Linux 用戶目錄,然後運行:

1
2
source ~/asr/.venv/bin/activate
python ~/asr/transcribe.py

第一次運行時,faster-whisper 會下載對應模型。模型下載成功後會保存在你指定的 download_root,以後不需要重複下載。

CPU NAS 推薦參數

沒有 GPU 時,優先控制模型大小和計算精度:

1
2
3
4
5
6
model = WhisperModel(
    "small",
    device="cpu",
    compute_type="int8",
    download_root="/home/USER/asr/models",
)

int8 通常適合作爲 CPU 推理的起點。若 NAS 同時還承擔文件同步、照片索引、下載或媒體服務,建議:

  • 先從 basesmall 開始;
  • 避免同時跑多個轉寫任務;
  • 長視頻安排在低峯時段;
  • 觀察系統內存、CPU 溫度和 swap;
  • 不要在同一時段讓 NAS 大量轉碼、校驗和轉寫同時進行。

CPU NAS 的目標應是“穩定完成”,而不是實時追趕音頻播放進度。

有 NVIDIA GPU 時怎麼配置

NAS 或 Linux 主機有可用 NVIDIA GPU 時,可嘗試:

1
2
3
4
5
6
model = WhisperModel(
    "small",
    device="cuda",
    compute_type="float16",
    download_root="/home/USER/asr/models",
)

顯存緊張時可以嘗試:

1
2
3
4
5
6
model = WhisperModel(
    "small",
    device="cuda",
    compute_type="int8_float16",
    download_root="/home/USER/asr/models",
)

實際可用的 compute_type 取決於 CTranslate2、CUDA、驅動和 GPU。先用短音頻驗證,再處理長文件。若放進 Docker,還需要先確認容器能看到 GPU;容器內 nvidia-smi 都不可用時,轉寫程序也不會獲得 CUDA 加速。

爲什麼建議開啓 VAD 過濾

VAD(語音活動檢測)會跳過明顯無語音的片段。對會議錄像、長暫停、背景音樂或錄音頭尾空白較多的文件,通常有兩點好處:

  • 減少無意義的推理時間;
  • 降低靜音段被識別成無關文字的概率。

在 faster-whisper 中啓用:

1
2
3
4
segments, info = model.transcribe(
    "input.mp3",
    vad_filter=True,
)

但 VAD 不是“絕不出錯”的開關。說話聲音很輕、音樂與人聲混雜、電話錄音斷續時,應抽樣檢查 VAD 是否誤切掉了有效內容。

生成 SRT 字幕

Whisper 的每個 segment 都帶有起止時間。可以在上述腳本基礎上輸出簡單 SRT:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def srt_time(seconds: float) -> str:
    milliseconds = round(seconds * 1000)
    hours, milliseconds = divmod(milliseconds, 3_600_000)
    minutes, milliseconds = divmod(milliseconds, 60_000)
    seconds, milliseconds = divmod(milliseconds, 1000)
    return f"{hours:02}:{minutes:02}:{seconds:02},{milliseconds:03}"

blocks = []
for index, segment in enumerate(segments, start=1):
    blocks.append(
        f"{index}\n"
        f"{srt_time(segment.start)} --> {srt_time(segment.end)}\n"
        f"{segment.text.strip()}\n"
    )

(output_dir / f"{input_file.stem}.srt").write_text(
    "\n".join(blocks), encoding="utf-8"
)

如果要做逐詞高亮或更精細剪輯,可以讀取 word_timestamps=True 後的詞級時間戳。但詞級結果也需要人工抽查,尤其是中英混說、人名、地名和縮寫。

批量轉寫不要一口氣併發跑滿

批量文件建議按隊列串行或低併發處理:

1
2
3
for file in ~/asr/inbox/*; do
  python ~/asr/transcribe.py "$file"
done

實際腳本中應補上擴展名過濾、成功/失敗記錄和跳過已完成文件的邏輯。最重要的是:先處理 5 個樣本,確認輸出目錄、語言、模型和字幕時間軸都正確,再啓動整批任務。

NAS 上盲目併發多個 large-v3 轉寫任務,很容易讓內存、GPU 顯存或散熱成爲瓶頸。轉寫服務如果還要和相冊、備份、下載器共用資源,更應限制隊列。

Docker 怎麼用才穩

許多 NAS 更適合用 Container Manager 或 Docker 管理服務。建議先在宿主機或普通 Linux 容器裏跑通 Python 版本,再封裝容器。容器化時至少要做到:

  • 將輸入目錄只讀掛載;
  • 將輸出目錄單獨可寫掛載;
  • 將模型緩存目錄持久化掛載;
  • 固定 faster-whisper、CTranslate2 和 Python 版本;
  • 若使用 GPU,先驗證容器運行時和設備透傳。

不要把整個 NAS 的共享目錄以讀寫方式掛入轉寫容器。語音識別任務只需要讀取音視頻和寫入文字結果,權限越小,誤操作影響越小。

準確率與隱私邊界

本地部署的優勢是音頻不必上傳到第三方服務,但這不代表輸出天然準確。Whisper 可能聽錯人名、專業術語、數字和靜音段,也可能在噪聲或長空白時出現不可靠文本。

以下內容應人工複覈:

  • 醫療、法律、財務和安全記錄;
  • 對外發布的字幕;
  • 訪談引用和會議決議;
  • 人名、金額、日期、電話號碼和產品型號。

保留原始音頻,並把文字稿視爲初稿,是比“轉寫後立刻刪除原文件”更穩妥的流程。

一套適合 NAS 的默認配置

如果你沒有獨顯:

1
2
3
4
5
model: base 或 small
device: cpu
compute_type: int8
vad_filter: true
并发: 1

如果你有可用 NVIDIA GPU:

1
2
3
4
5
model: small 起步,按效果再试 medium
device: cuda
compute_type: float16 或 int8_float16
vad_filter: true
并发: 从 1 开始压测

先用同一段 10 到 30 分鐘的真實錄音比較耗時、漏字、錯字和字幕時間軸,再決定是否升級模型。不要只用幾秒鐘的清晰樣本來判斷 NAS 是否適合長期轉寫。

總結

Whisper NAS 部署可以從 faster-whisper 開始:小模型、低併發、VAD 過濾、輸入輸出目錄分離。CPU NAS 能承擔低頻離線轉寫;有正確 CUDA 環境的 GPU NAS 才更適合大量視頻和更大模型。

真正決定體驗的不是“Whisper 能不能裝上”,而是你的音頻質量、模型大小、實際轉寫隊列和 NAS 還承擔了多少其他服務。先跑通一段真實音頻,再擴大規模。

參考:

记录并分享
使用 Hugo 建立
主題 StackJimmy 設計