字幕工具:基于faster-whisper的完整實(shí)現(xiàn))
1. 為什么要做本地 AI 字幕工具做視頻內(nèi)容創(chuàng)作或者課程整理的朋友大概率都遇到過這樣的場(chǎng)景手上有幾十段訪談錄音、網(wǎng)課錄像或者會(huì)議紀(jì)要需要把它們轉(zhuǎn)成帶時(shí)間軸的字幕文件方便后續(xù)剪輯、校對(duì)或者做二次分發(fā)。最初我的做法是找在線工具一個(gè)文件一個(gè)文件上傳轉(zhuǎn)完再手動(dòng)下載。遇到長(zhǎng)視頻還要掐著時(shí)間分段處理一邊擔(dān)心平臺(tái)限額一邊擔(dān)心上傳的素材會(huì)不會(huì)被留存。后來?yè)Q成本地 AI 方案之后這些問題基本都消失了。本文要分享的就是一套完全運(yùn)行在本地電腦上的批量音視頻轉(zhuǎn)文字工具核心功能圍繞三點(diǎn)展開批量處理把整個(gè)文件夾里的音頻、視頻一次性交給程序。長(zhǎng)音頻自動(dòng)切分不需要手工剪斷文件程序會(huì)按靜音點(diǎn)或其他策略自動(dòng)分段轉(zhuǎn)寫。斷點(diǎn)續(xù)跑轉(zhuǎn)寫到一半斷電、報(bào)錯(cuò)或手動(dòng)停止下次啟動(dòng)自動(dòng)跳過已完成內(nèi)容。整套方案基于開源語(yǔ)音識(shí)別模型實(shí)現(xiàn)不需要 GPU 也能跑重點(diǎn)在于工程化封裝把模型調(diào)用、音頻切分、SRT 字幕生成、任務(wù)進(jìn)度記錄這幾件事整合到一起。讀完本文你不僅會(huì)得到一個(gè)能直接運(yùn)行的腳本還能理解它背后的設(shè)計(jì)思路方便后續(xù)按自己的需求改造。2. 技術(shù)方案與核心概念2.1 音頻轉(zhuǎn)文字的常見路徑目前主流的語(yǔ)音識(shí)別開源方案有 Whisper、faster-whisper、FunASR、Kaldi 等。其中 Whisper 和 faster-whisper 是社區(qū)使用最廣泛的兩類。Whisper 是 OpenAI 開源的語(yǔ)音識(shí)別模型支持多語(yǔ)言、帶時(shí)間戳輸出可以直接生成類似 SRT 的段落信息。faster-whisper 是 Whisper 模型的加速推理版本底層使用 CTranslate2 做模型推理在 CPU 上的速度比原版快不少內(nèi)存占用也更低。對(duì)于本地批量處理來說faster-whisper 是更務(wù)實(shí)的選擇。音頻切分方面一般有兩種思路固定時(shí)長(zhǎng)切分按 30 秒、60 秒一個(gè)片段切分實(shí)現(xiàn)簡(jiǎn)單但可能切斷句子導(dǎo)致字幕語(yǔ)義不完整。靜音檢測(cè)切分通過分析音頻能量找到相對(duì)安靜的位置作為切分點(diǎn)能較好地保留完整句子邊界。本文采用靜音檢測(cè)為主、固定時(shí)長(zhǎng)兜底的方式兼顧轉(zhuǎn)寫質(zhì)量和流程穩(wěn)定性。2.2 SRT 字幕格式SRT 是通用性最強(qiáng)的字幕格式之一幾乎所有播放器和剪輯軟件都支持。一個(gè) SRT 文件的結(jié)構(gòu)大致如下1 00:00:01,000 -- 00:00:05,000 大家好今天我們來聊一聊字幕工具的實(shí)現(xiàn)。 2 00:00:06,500 -- 00:00:10,200 首先需要準(zhǔn)備 Python 環(huán)境和語(yǔ)音識(shí)別模型。其中數(shù)字是字幕序號(hào)第二行是時(shí)間軸第三行開始是字幕文本。時(shí)間軸格式必須嚴(yán)格遵循“小時(shí):分鐘:秒,毫秒”毫秒部分用逗號(hào)分隔。2.3 什么是續(xù)跑所謂續(xù)跑是指在批量處理過程中記錄每個(gè)文件、每個(gè)切片的狀態(tài)。當(dāng)程序異常退出或人為中斷時(shí)已經(jīng)處理完成的部分不需要重新轉(zhuǎn)寫。實(shí)現(xiàn)續(xù)跑的關(guān)鍵在于任務(wù)狀態(tài)持久化本文采用 JSON 文件記錄任務(wù)清單和完成狀態(tài)每次啟動(dòng)時(shí)先讀取狀態(tài)文件再?zèng)Q定哪些任務(wù)需要執(zhí)行。3. 環(huán)境準(zhǔn)備與項(xiàng)目結(jié)構(gòu)3.1 運(yùn)行環(huán)境和依賴建議使用 Python 3.9 及以上版本。操作系統(tǒng)方面Windows、macOS、Linux 均可但 ffmpeg 的安裝方式略有差異。需要安裝的 Python 庫(kù)如下pip install faster-whisper pydub numpyffmpeg 是音頻解碼和切分的關(guān)鍵工具faster-whisper 解碼音頻時(shí)依賴它。Windows 用戶可以從 ffmpeg 官網(wǎng)下載可執(zhí)行文件然后把 bin 目錄加入系統(tǒng) PATH。macOS 用戶可以用 Homebrew 安裝brew install ffmpegUbuntu/Debian 用戶執(zhí)行sudo apt update sudo apt install ffmpeg安裝完成后可以在終端執(zhí)行ffmpeg -version驗(yàn)證是否生效。3.2 模型選擇說明faster-whisper 支持多種尺寸的模型包括 tiny、base、small、medium、large-v3 等。模型越大識(shí)別準(zhǔn)確率越高但推理速度越慢內(nèi)存占用也越高。如果只是處理清晰的中文訪談或課程small或medium是比較合適的選擇。如果對(duì)準(zhǔn)確率要求高且機(jī)器配置足夠可以嘗試large-v3。模型首次運(yùn)行時(shí)需要聯(lián)網(wǎng)下載下載完成后會(huì)緩存在本地后續(xù)使用不需要再次下載。3.3 項(xiàng)目文件結(jié)構(gòu)為了讓代碼結(jié)構(gòu)清晰建議按下面的目錄組織項(xiàng)目audio2srt/ ├── main.py # 主入口任務(wù)調(diào)度 ├── config.py # 配置參數(shù) ├── audio_splitter.py # 音頻切分模塊 ├── transcribe.py # 轉(zhuǎn)寫模塊 ├── srt_generator.py # SRT 字幕生成模塊 ├── task_manager.py # 任務(wù)狀態(tài)管理續(xù)跑核心 ├── input/ # 存放待處理的音視頻 ├── output/ # 輸出的 SRT 字幕文件 └── progress/ # 任務(wù)狀態(tài)記錄本文后續(xù)的代碼均按該結(jié)構(gòu)編寫實(shí)際操作時(shí)可以根據(jù)自己的項(xiàng)目習(xí)慣調(diào)整。4. 核心模塊設(shè)計(jì)與代碼實(shí)現(xiàn)4.1 配置文件先創(chuàng)建一個(gè)config.py把常用的參數(shù)集中管理方便修改。# 文件路徑config.py import os BASE_DIR os.path.dirname(os.path.abspath(__file__)) INPUT_DIR os.path.join(BASE_DIR, input) OUTPUT_DIR os.path.join(BASE_DIR, output) PROGRESS_DIR os.path.join(BASE_DIR, progress) # 支持的音視頻格式 SUPPORTED_EXTS {.mp3, .wav, .m4a, .flac, .mp4, .mkv, .avi, .mov, .webm} # Whisper 模型參數(shù) MODEL_SIZE small DEVICE cpu COMPUTE_TYPE int8 # 音頻切分參數(shù) MIN_SILENCE_DURATION 500 # 最小靜音時(shí)長(zhǎng)毫秒 SILENCE_THRESHOLD -40 # 靜音判定閾值dBFS MAX_SEGMENT_DURATION 30 # 單段最大時(shí)長(zhǎng)秒 KEEP_TRAILING_SILENCE True # 是否保留段尾靜音 # 轉(zhuǎn)寫參數(shù) LANGUAGE zh BEAM_SIZE 5 VAD_FILTER True # 是否啟用語(yǔ)音活動(dòng)檢測(cè)過濾靜音段 # 輸出參數(shù) OUTPUT_FORMAT srt這里需要說明幾個(gè)關(guān)鍵參數(shù)SILENCE_THRESHOLD靜音判定閾值單位是 dBFS值越小表示要求越安靜才判定為靜音。一般-35到-45之間效果不錯(cuò)可以根據(jù)實(shí)際錄音環(huán)境調(diào)整。MAX_SEGMENT_DURATION切分后單段音頻的最大時(shí)長(zhǎng)避免某一段過長(zhǎng)導(dǎo)致模型推理壓力過大。VAD_FILTER啟用后可以自動(dòng)過濾掉沒有人聲的純靜音片段對(duì)訪談?lì)愐纛l特別有用。4.2 音頻切分模塊音頻切分模塊的作用是把長(zhǎng)音頻按照靜音位置切成多個(gè)小片段并返回每個(gè)片段在原音頻中的起始時(shí)間。這里用 pydub 來做靜音檢測(cè)和切分。# 文件路徑audio_splitter.py from pydub import AudioSegment from pydub.silence import detect_silence, split_on_silence import config def find_split_points(audio_segment): 找出音頻中的靜音區(qū)間確定切分點(diǎn)。 返回切分點(diǎn)的時(shí)間位置列表單位為毫秒。 silence_ranges detect_silence( audio_segment, min_silence_lenconfig.MIN_SILENCE_DURATION, silence_threshconfig.SILENCE_THRESHOLD, ) split_points [] current_position 0 for start, end in silence_ranges: # 如果當(dāng)前段已經(jīng)達(dá)到最大時(shí)長(zhǎng)則在此靜音處切分 if start - current_position config.MAX_SEGMENT_DURATION * 1000: split_points.append((start end) // 2) current_position (start end) // 2 return split_points def split_audio(input_path): 切分音頻文件返回片段列表。 每個(gè)片段是一個(gè) dict包含 start_time、end_time 和音頻對(duì)象。 audio AudioSegment.from_file(input_path) split_points find_split_points(audio) segments [] last_point 0 for point in split_points: segment audio[last_point:point] segments.append({ start_time: last_point, end_time: point, audio: segment, }) last_point point # 最后一段 if last_point len(audio): segments.append({ start_time: last_point, end_time: len(audio), audio: audio[last_point:], }) return segments這個(gè)實(shí)現(xiàn)的核心邏輯是先檢測(cè)所有達(dá)到最小靜音時(shí)長(zhǎng)的區(qū)間然后只選取那些“距離上一個(gè)切分點(diǎn)已經(jīng)超過最大單段時(shí)長(zhǎng)”的靜音位置作為切分點(diǎn)。這樣做的好處是既不會(huì)把句子切得七零八落也不會(huì)讓單段音頻過長(zhǎng)。4.3 轉(zhuǎn)寫模塊轉(zhuǎn)寫模塊封裝了 faster-whisper 的調(diào)用邏輯。為了讓批次處理更高效這里采用分段轉(zhuǎn)寫的方式將每個(gè)切分好的音頻片段導(dǎo)出為臨時(shí) WAV 文件再交給 faster-whisper 轉(zhuǎn)寫并記錄該片段相對(duì)原文件的偏移量。# 文件路徑transcribe.py import tempfile import os from faster_whisper import WhisperModel import config class Transcriber: def __init__(self): self.model WhisperModel( config.MODEL_SIZE, deviceconfig.DEVICE, compute_typeconfig.COMPUTE_TYPE, ) def transcribe_segment(self, audio_segment, start_time_ms): 轉(zhuǎn)寫單個(gè)音頻片段。 audio_segment: pydub AudioSegment 對(duì)象 start_time_ms: 該片段在原音頻中的起始時(shí)間毫秒 返回字幕片段列表時(shí)間軸為原音頻絕對(duì)時(shí)間。 # 將 pydub 音頻導(dǎo)出為臨時(shí) WAV 文件 with tempfile.NamedTemporaryFile(suffix.wav, deleteFalse) as tmp_file: tmp_path tmp_file.name audio_segment.export(tmp_path, formatwav) try: segments, info self.model.transcribe( tmp_path, languageconfig.LANGUAGE, beam_sizeconfig.BEAM_SIZE, vad_filterconfig.VAD_FILTER, ) subtitle_segments [] for seg in segments: subtitle_segments.append({ start: start_time_ms seg.start * 1000, end: start_time_ms seg.end * 1000, text: seg.text.strip(), }) return subtitle_segments finally: os.remove(tmp_path)這里有一個(gè)容易被忽略的細(xì)節(jié)轉(zhuǎn)寫返回的seg.start和seg.end是相對(duì)當(dāng)前 WAV 文件的秒數(shù)。如果直接把這個(gè)時(shí)間寫入最終字幕時(shí)間軸會(huì)錯(cuò)亂。所以必須加上start_time_ms偏移量轉(zhuǎn)成原音頻的絕對(duì)時(shí)間。4.4 SRT 文件生成模塊SRT 生成模塊把時(shí)間戳轉(zhuǎn)換成標(biāo)準(zhǔn)格式并寫入文件。# 文件路徑srt_generator.py def ms_to_srt_time(ms): 將毫秒時(shí)間轉(zhuǎn)換為 SRT 時(shí)間軸格式HH:MM:SS,mmm hours ms // 3600000 minutes (ms % 3600000) // 60000 seconds (ms % 60000) // 1000 milliseconds ms % 1000 return f{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d} def write_srt(subtitle_segments, output_path): 將字幕片段列表寫入 SRT 文件。 subtitle_segments 需要按 start 時(shí)間升序排列。 subtitle_segments.sort(keylambda x: x[start]) with open(output_path, w, encodingutf-8) as f: for idx, seg in enumerate(subtitle_segments, start1): start_time ms_to_srt_time(seg[start]) end_time ms_to_srt_time(seg[end]) f.write(f{idx}\n) f.write(f{start_time} -- {end_time}\n) f.write(f{seg[text]}\n\n)4.5 任務(wù)狀態(tài)管理模塊續(xù)跑功能的實(shí)現(xiàn)依賴這個(gè)模塊。設(shè)計(jì)思路是程序處理前先生成一個(gè)待處理任務(wù)列表寫入任務(wù)文件每完成一個(gè)文件就把完成狀態(tài)寫入文件。下次啟動(dòng)時(shí)加載任務(wù)文件跳過節(jié)已完成的任務(wù)。# 文件路徑task_manager.py import json import os def load_progress(progress_path): 加載任務(wù)進(jìn)度文件。 如果文件不存在返回空字典。 if not os.path.exists(progress_path): return {} with open(progress_path, r, encodingutf-8) as f: return json.load(f) def save_progress(progress_path, progress_data): 保存任務(wù)進(jìn)度到 JSON 文件。 with open(progress_path, w, encodingutf-8) as f: json.dump(progress_data, f, ensure_asciiFalse, indent2) def build_task_list(input_dir, supported_exts): 掃描輸入目錄生成待處理文件列表。 返回按文件名排序的列表保證處理順序穩(wěn)定。 task_list [] for root, dirs, files in os.walk(input_dir): for file in files: ext os.path.splitext(file)[1].lower() if ext in supported_exts: task_list.append(os.path.join(root, file)) return sorted(task_list) def is_task_completed(progress_data, file_path): 判斷某個(gè)文件是否已經(jīng)處理完成。 return progress_data.get(file_path) completed4.6 主程序主程序負(fù)責(zé)把上面的模塊串聯(lián)起來。核心邏輯是加載任務(wù)列表。讀取進(jìn)度文件過濾已完成任務(wù)。逐個(gè)處理未完成任務(wù)處理成功后更新進(jìn)度文件。所有任務(wù)完成后輸出匯總信息。# 文件路徑main.py import os import sys import time import config from audio_splitter import split_audio from transcribe import Transcriber from srt_generator import write_srt, ms_to_srt_time from task_manager import load_progress, save_progress, build_task_list, is_task_completed def process_file(transcriber, input_path, output_path): 處理單個(gè)音視頻文件生成 SRT 字幕文件。 print(f[處理] {input_path}) # 1. 按靜音切分音頻 segments split_audio(input_path) print(f[切分] 共切分為 {len(segments)} 段) # 2. 逐段轉(zhuǎn)寫 all_subtitles [] total_duration_ms sum(seg[end_time] - seg[start_time] for seg in segments) for idx, seg in enumerate(segments, start1): seg_duration seg[end_time] - seg[start_time] print(f[轉(zhuǎn)寫] 第 {idx}/{len(segments)} 段時(shí)長(zhǎng) {seg_duration / 1000:.1f}s) start_time time.time() subtitles transcriber.transcribe_segment(seg[audio], seg[start_time]) elapsed time.time() - start_time print(f 已用 {elapsed:.1f}s識(shí)別 {len(subtitles)} 條字幕) all_subtitles.extend(subtitles) # 3. 生成 SRT 文件 write_srt(all_subtitles, output_path) print(f[完成] 字幕已保存至 {output_path}) def main(): os.makedirs(config.OUTPUT_DIR, exist_okTrue) os.makedirs(config.PROGRESS_DIR, exist_okTrue) progress_path os.path.join(config.PROGRESS_DIR, task_progress.json) progress_data load_progress(progress_path) task_list build_task_list(config.INPUT_DIR, config.SUPPORTED_EXTS) pending_tasks [t for t in task_list if not is_task_completed(progress_data, t)] if not pending_tasks: print(沒有待處理的任務(wù)全部已完成。) return print(f待處理任務(wù)數(shù){len(pending_tasks)}) transcriber Transcriber() for task_path in pending_tasks: try: rel_path os.path.relpath(task_path, config.INPUT_DIR) base_name os.path.splitext(rel_path)[0] output_path os.path.join(config.OUTPUT_DIR, base_name .srt) os.makedirs(os.path.dirname(output_path), exist_okTrue) process_file(transcriber, task_path, output_path) # 更新任務(wù)狀態(tài) progress_data[task_path] completed save_progress(progress_path, progress_data) except Exception as e: print(f[錯(cuò)誤] 處理 {task_path} 時(shí)發(fā)生異常{e}) print(跳過該文件繼續(xù)處理下一個(gè)任務(wù)。) print(所有任務(wù)處理完成。) if __name__ __main__: main()這個(gè)主程序已經(jīng)具備完整的批量處理和續(xù)跑能力。程序每處理完一個(gè)文件就會(huì)立刻把狀態(tài)寫入 JSON 文件。即使中途崩潰已完成文件的進(jìn)度也不會(huì)丟失。5. 完整運(yùn)行演示5.1 準(zhǔn)備測(cè)試文件在input目錄下放入兩到三個(gè)音視頻文件比如input/ ├── 課程01.mp4 ├── 訪談02.m4a └── 會(huì)議記錄03.mp35.2 運(yùn)行程序在項(xiàng)目根目錄執(zhí)行python main.py首次運(yùn)行會(huì)下載模型網(wǎng)絡(luò)較慢時(shí)可能需要等待一段時(shí)間。模型下載完成后程序會(huì)自動(dòng)開始處理。5.3 預(yù)期輸出正常情況下控制臺(tái)輸出類似這樣待處理任務(wù)數(shù)3 [處理] /path/to/input/課程01.mp4 [切分] 共切分為 12 段 [轉(zhuǎn)寫] 第 1/12 段時(shí)長(zhǎng) 28.3s 已用 15.2s識(shí)別 6 條字幕 [轉(zhuǎn)寫] 第 2/12 段時(shí)長(zhǎng) 30.0s 已用 17.8s識(shí)別 5 條字幕 ... [完成] 字幕已保存至 /path/to/output/課程01.srt全部完成后output目錄下會(huì)生成對(duì)應(yīng)的 SRT 文件output/ ├── 課程01.srt ├── 訪談02.srt └── 會(huì)議記錄03.srt5.4 續(xù)跑驗(yàn)證可以手動(dòng)中斷程序來驗(yàn)證續(xù)跑功能。只要程序在處理完完整文件后才更新進(jìn)度那么中斷后再次運(yùn)行已經(jīng)完成的任務(wù)會(huì)自動(dòng)跳過只會(huì)處理剩余文件。比如上面的示例中如果課程01.srt已經(jīng)生成而訪談02.m4a處理到一半被中斷重新運(yùn)行程序后控制臺(tái)會(huì)顯示待處理任務(wù)數(shù)2 [處理] /path/to/input/訪談02.m4a ...課程01.mp4不會(huì)再被重復(fù)處理這就是續(xù)跑帶來的效率提升。6. 常見問題與排查思路6.1 常見錯(cuò)誤對(duì)照表問題現(xiàn)象常見原因解決思路導(dǎo)入 pydub 時(shí)提示找不到 ffmpegffmpeg 未安裝或未加入系統(tǒng) PATH安裝 ffmpeg執(zhí)行ffmpeg -version檢查轉(zhuǎn)寫速度很慢模型過大或 CPU 性能不足改用 small/base 模型或開啟 int8 量化字幕時(shí)間軸錯(cuò)亂轉(zhuǎn)寫時(shí)間未加偏移量檢查transcribe_segment中是否加上start_time_ms識(shí)別內(nèi)容為空音頻音量太低或語(yǔ)言參數(shù)不對(duì)增大音量檢查L(zhǎng)ANGUAGE參數(shù)打開 VAD 過濾檢測(cè)靜音失敗沒有切分點(diǎn)靜音閾值設(shè)置不合理調(diào)高SILENCE_THRESHOLD到 -30 或 -25程序報(bào)錯(cuò)提示磁盤空間不足臨時(shí) WAV 文件堆積檢查臨時(shí)文件目錄確認(rèn)代碼中已刪除臨時(shí)文件6.2 音頻切分效果不佳怎么辦切分效果與錄音環(huán)境密切相關(guān)。如果錄音中存在明顯的環(huán)境噪聲靜音檢測(cè)可能失效導(dǎo)致切分點(diǎn)過少或過密。遇到這種情況可以先做一個(gè)簡(jiǎn)單的降噪預(yù)處理from pydub import AudioSegment from pydub.effects import normalize audio AudioSegment.from_file(input_path) audio normalize(audio)normalize會(huì)把音頻的峰值音量歸一化能讓后續(xù)的靜音檢測(cè)更穩(wěn)定。6.3 內(nèi)存占用過高怎么辦如果一次處理時(shí)長(zhǎng)很長(zhǎng)的音頻pydub 會(huì)把整個(gè)音頻加載到內(nèi)存中導(dǎo)致內(nèi)存占用飆升。對(duì)于超過 1 小時(shí)的音頻建議先用 ffmpeg 按固定時(shí)間窗口切割成若干中間文件再逐個(gè)調(diào)用AudioSegment.from_file加載。這個(gè)策略雖然多做了一步文件操作但內(nèi)存消耗會(huì)穩(wěn)定很多。7. 最佳實(shí)踐與工程建議7.1 合理設(shè)計(jì)任務(wù)狀態(tài)更新時(shí)機(jī)續(xù)跑不是簡(jiǎn)單地加一個(gè) try-except 就能實(shí)現(xiàn)。真正的關(guān)鍵點(diǎn)是任務(wù)狀態(tài)必須在“整個(gè)文件的字幕文件成功寫入磁盤之后”更新而不是在轉(zhuǎn)寫開始時(shí)更新。這樣即使轉(zhuǎn)寫中途崩潰下次啟動(dòng)也能重新處理不會(huì)生成殘缺的字幕文件。7.2 輸出文件命名規(guī)范建議輸出 SRT 文件時(shí)保持與源文件相同的相對(duì)路徑這樣既避免重名覆蓋又方便管理。對(duì)于不同語(yǔ)言的翻譯需求可以在文件名后追加語(yǔ)言后綴例如課程01.zh.srt、課程01.en.srt。7.3 日志與可觀測(cè)性批量處理任務(wù)往往耗時(shí)較長(zhǎng)如果缺少日志很難定位問題。建議在關(guān)鍵節(jié)點(diǎn)加入日志輸出并寫入獨(dú)立的日志文件。Python 的logging模塊可以很方便地實(shí)現(xiàn)控制臺(tái)和文件雙輸出。7.4 隱私與安全在本地運(yùn)行 AI 模型的優(yōu)勢(shì)之一是不需要把數(shù)據(jù)上傳到第三方服務(wù)。如果你的素材涉及隱私信息或商業(yè)機(jī)密本地推理是更安全的選擇。需要注意模型文件本身是公開的輸入內(nèi)容不會(huì)離開本機(jī)這一點(diǎn)在向團(tuán)隊(duì)推廣時(shí)可以重點(diǎn)說明。7.5 模型選擇與成本控制如果只是輕量使用base和small模型已經(jīng)能覆蓋大部分中文場(chǎng)景。medium和large-v3雖然在復(fù)雜口音、背景噪聲場(chǎng)景下表現(xiàn)更好但推理時(shí)間會(huì)成倍增加。建議先用少量樣本測(cè)試不同模型的效果和耗時(shí)再正式批量運(yùn)行。8. 擴(kuò)展方向當(dāng)前版本的工具已經(jīng)具備完整的“批量處理、長(zhǎng)音頻切分、續(xù)跑”三大能力。如果想進(jìn)一步實(shí)用化可以考慮下面幾個(gè)方向多格式輸出在 SRT 之外同時(shí)輸出 VTT、純文本 TXT 或帶說話人標(biāo)簽的 JSON。說話人分離接入 pyannote 等說話人分離模型讓字幕區(qū)分“人物 A / 人物 B”。并行加速在 CPU 多核環(huán)境下可以同時(shí)對(duì)多個(gè)文件啟動(dòng)轉(zhuǎn)寫進(jìn)程進(jìn)一步縮短總耗時(shí)。定時(shí)任務(wù)把腳本封裝成可執(zhí)行文件配合系統(tǒng)自帶定時(shí)任務(wù)在夜間自動(dòng)處理素材。字幕翻譯對(duì)轉(zhuǎn)寫文本調(diào)用本地翻譯模型實(shí)現(xiàn)字幕自動(dòng)翻譯方便做雙語(yǔ)字幕。本文給出的代碼完全可以在本地直接運(yùn)行。核心價(jià)值在于把“音頻切分、模型轉(zhuǎn)寫、字幕生成、狀態(tài)管理”這四個(gè)環(huán)節(jié)拆成獨(dú)立模塊每一塊都可以按你的實(shí)際場(chǎng)景替換或增強(qiáng)。如果你在做批量字幕處理時(shí)還有其他問題歡迎在評(píng)論區(qū)交流我會(huì)根據(jù)實(shí)際問題繼續(xù)補(bǔ)充更深入的實(shí)踐方案。