緣起:
接續這篇,其實那一篇的都算是鋪陳,我重點是想要寫我用
faster-whisper 來幫我處理對話存文字的部份,這裡遇到最多麻煩。
在我把 Jellyfin 搞定後,我的腦子後來又開始想說,現在已經很習慣用 AI
功具來幫我學習了,能不能也用在這些課程上呢?請它幫我抓重點、做筆記之類的。直接要
AI 幫我分析整部影片感覺很不實際,像是 claude project 上傳文件的部份,你一個
500 多 MB 的檔案傳上去就要花不少時間,而且那 project 空間也是有限的。
我自己思考後,認為用語音識別影片的內容後,存成文字檔,再丢給 AI
處理,會是個比較好的做法,所以就請 claude 教我怎麼用程式來達成這需求。
Faster-Whisper:
使用 Python,開個 Python venv 專案,然後用 pip 載 faster
whisper
pip install faster-whisper
然後跟 claude 講需求,請它幫我寫一個 python 程式
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批次把教學影片轉成逐字稿(.srt 時間軸字幕 + .txt 帶時間戳純文字)
用法:
pip install faster-whisper
python transcribe.py "D:/課程影片" # 或 Linux/mac: python3 transcribe.py ~/影片
產出的檔案會放在每支影片旁邊,同名不同副檔名。
已經有 .srt 的影片會自動跳過,所以中途關掉再跑一次不會重來。
"""
import sys
import pathlib
from faster_whisper import WhisperModel
# ---------- 可調參數 ----------
MODEL_SIZE = "large-v3" # 中文建議 large-v3;機器太慢就改 "medium"(快 2-3 倍,準確度略降)
LANGUAGE = "zh"
COMPUTE_TYPE = "float16" # CPU 用 int8。若有 NVIDIA 顯卡改 device="cuda", compute_type="float16"
DEVICE = "cuda"
CPU_THREADS = 0 # 0 = 自動用全部核心
# ★ 把你課程裡常出現的英文術語、套件名、人名列在這裡,用逗號分隔。
# 這是提升中英夾雜辨識率最有效的一招,務必按你的課程內容改。
GLOSSARY = "API, function, component, debug, deploy, database, server, framework"
# 這句 prompt 會引導模型輸出繁體中文,並提示會夾雜英文術語
INITIAL_PROMPT = (
f"以下是繁體中文的教學課程錄影,講者會夾雜英文技術名詞,"
f"例如 {GLOSSARY}。請以繁體中文輸出,英文術語保留英文原文。"
)
EXTS = {".mp4", ".mkv", ".mov", ".avi", ".flv", ".ts", ".webm",
".m4a", ".mp3", ".wav", ".aac", ".opus"}
# --------------------------------
def srt_time(sec: float) -> str:
h = int(sec // 3600)
m = int(sec % 3600 // 60)
s = sec % 60
return f"{h:02d}:{m:02d}:{s:06.3f}".replace(".", ",")
def mmss(sec: float) -> str:
return f"{int(sec) // 60:02d}:{int(sec) % 60:02d}"
def transcribe_compat(model, path, opts):
"""有些參數只有新版 faster-whisper 支援,不支援就自動拿掉重試。"""
opts = dict(opts)
while True:
try:
return model.transcribe(str(path), **opts)
except TypeError as err:
for key in ("multilingual", "hotwords"):
if key in opts and key in str(err):
print(f" (這版 faster-whisper 不支援 {key},已略過)")
opts.pop(key)
break
else:
raise
def main():
root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".").expanduser()
videos = sorted(p for p in root.rglob("*")
if p.suffix.lower() in EXTS and not p.name.startswith("."))
if not videos:
print(f"在 {root} 找不到影片/音檔")
return
todo = [v for v in videos if not v.with_suffix(".srt").exists()]
print(f"共 {len(videos)} 個檔案,待處理 {len(todo)} 個\n")
if not todo:
return
print(f"載入模型 {MODEL_SIZE}(第一次會下載約 1.5GB,之後就有快取)...")
model = WhisperModel(MODEL_SIZE, device=DEVICE,
compute_type=COMPUTE_TYPE, cpu_threads=CPU_THREADS)
print("模型就緒\n")
for n, v in enumerate(todo, 1):
print(f"[{n}/{len(todo)}] {v.name}", flush=True)
try:
segments, info = transcribe_compat(model, v, dict(
language=LANGUAGE,
initial_prompt=INITIAL_PROMPT,
hotwords=GLOSSARY, # 每個 30 秒視窗都會看到術語表,不只開頭那段
multilingual=True, # 逐段偵測語言,中英夾雜時英文比較不會被翻成中文
beam_size=5,
vad_filter=True, # 切掉靜音,減少幻聽式亂編
vad_parameters=dict(min_silence_duration_ms=500),
condition_on_previous_text=False, # 避免一句錯就整段跟著歪掉
))
srt_lines, txt_lines = [], []
for i, seg in enumerate(segments, 1):
text = seg.text.strip()
if not text:
continue
srt_lines.append(
f"{i}\n{srt_time(seg.start)} --> {srt_time(seg.end)}\n{text}\n")
txt_lines.append(f"[{mmss(seg.start)}] {text}")
print(f" {mmss(seg.start)} {text[:36]}", flush=True)
v.with_suffix(".srt").write_text("\n".join(srt_lines), encoding="utf-8")
v.with_suffix(".txt").write_text("\n".join(txt_lines), encoding="utf-8")
print(f" -> 完成 {v.with_suffix('.txt').name}\n", flush=True)
except Exception as e:
print(f" !! 失敗:{e}\n", flush=True)
if __name__ == "__main__":
main()
嘿嘿,超方便的,有哪些可以自己修改的地方,claude
也有幫我標出來。我把它存成 main.py,只要執行
python3 ./main.py "<目標資料夾>"
它就會處理資料夾下的影音檔,識別完文字後存成同名稱的
txt 檔跟 rst 檔,那個 rst 檔可以給 Jellyfin 用,只要同檔名的 rst
檔跟影片處在同一目錄,在播放放影片時 Jellyfin 會自動讀取它。
問題:
這程式可以純 cpu 跑,但超慢,如果要處理那 200
多部影片的話,會做到天荒地老,所以一定要用
cuda,只是我改完後,執行程式,它會報錯,在 Windows 上執行會說
cudblas64_12.dll not found,在 Linux 上的話是
libcublas.so.12 not found。
???? 三小,那台跑 windows
的筆電我不是很確定,但我那台跑 Arch Linux 的電腦確定是有載 cuda
啊,怎麼會找不到?我一開始把問題丢給 claude,它說可以用 pip 載
pip install nvidia-cublas-cu12 "nvidia-cudnn-cu12==9.*"
原來能用 pip 直接載 python lib 之外的 lib 啊 ~~ 啊幹,這也不是重點,重點是我載完後再跑,它還是報同樣的錯,不管是在 Windows 還是在 Linux 上都是。
(嘆氣),Claude 難得無法幫我解決問題,我只能回到老方法了,用 google search。我發現一個 github issue,有人提到它新增一個 soft link,
沒有留言:
張貼留言