# 转录最佳实践 --- ## 零、环境准备 ### 0.1 安装依赖 ```bash pip install funasr pip install modelscope # 模型下载 ``` ### 0.2 模型下载 首次运行会自动下载模型到 `~/.cache/modelscope/`(约 2GB): | 模型 | 大小 | 用途 | |------|------|------| | paraformer-zh | 953MB | 语音识别(带时间戳) | | punc_ct | 1.1GB | 标点预测 | | fsmn-vad | 4MB | 语音活动检测 | **手动预下载**(可选,避免首次运行等待): ```python from funasr import AutoModel # 运行一次即可触发下载 model = AutoModel( model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc", ) print("模型下载完成") ``` ### 0.3 验证安装 ```python from funasr import AutoModel model = AutoModel(model="paraformer-zh", disable_update=True) result = model.generate(input="test.wav") print(result) # 应该输出转录结果 ``` --- ## 一、技术选型 ### FunASR Paraformer 阿里开源,中文识别最优,支持字符级时间戳。 ### ⚠️ 关键发现(2026-01-15) | 方案 | 问题 | |------|------| | FunASR 全视频 | 长视频时间戳漂移(~10s/3分钟)→ 剪辑不准 | | **FunASR 30s分段** | ✅ 无漂移 + 精确时间戳 | **结论**:口播剪辑用 **FunASR 30s 分段转录** --- ## 二、音频预处理 ### 2.1 从视频提取音频 ```bash ffmpeg -i video.mp4 \ -vn \ # 不要视频 -acodec pcm_s16le \ # 16-bit PCM -ar 16000 \ # 16kHz 采样率 -ac 1 \ # 单声道 output.wav ``` ### 2.2 参数说明 | 参数 | 值 | 原因 | |------|-----|------| | 采样率 | 16000 Hz | FunASR 模型训练采样率 | | 声道 | 单声道 | 语音识别不需要立体声 | | 格式 | WAV | 无损,兼容性好 | | 位深 | 16-bit | 足够,文件更小 | --- ## 三、FunASR 使用 ### 3.1 ⭐ 推荐:30s 分段转录(口播剪辑用这个) ```python from funasr import AutoModel import subprocess import os video = "video.mp4" segment_len = 30 # 30秒一段 duration = 217.97 # 视频时长(用 ffprobe 获取) model = AutoModel(model="paraformer-zh", disable_update=True) all_chars = [] num_segments = int(duration // segment_len) + 1 for i in range(num_segments): start = i * segment_len dur = min(segment_len, duration - start) wav = f'/tmp/seg_{i}.wav' # 提取音频段 subprocess.run(['ffmpeg', '-y', '-i', video, '-ss', str(start), '-t', str(dur), '-vn', '-acodec', 'pcm_s16le', '-ar', '16000', '-ac', '1', wav], capture_output=True) # FunASR 转录(字符级时间戳) result = model.generate(input=wav, return_raw_text=True, timestamp_granularity="character") for item in result: if 'timestamp' in item and 'text' in item: text = item['text'].replace(' ', '') for char, ts in zip(text, item['timestamp']): all_chars.append({ 'char': char, 'start': round(start + ts[0] / 1000, 2), # 加偏移! 'end': round(start + ts[1] / 1000, 2) }) os.remove(wav) ``` **关键点**: - 30s 分段避免时间戳漂移 - `timestamp_granularity="character"` 获取字符级时间戳 - 每段结果要 **加上段起始偏移** ### 3.2 基础用法(短视频可用) ```python from funasr import AutoModel model = AutoModel( model="paraformer-zh", # 中文模型 vad_model="fsmn-vad", # 语音活动检测 punc_model="ct-punc", # 标点预测 ) result = model.generate( input="audio.wav", batch_size_s=300, # 批处理时长(秒) ) ``` ### 3.2 输出格式 ```json [{ "key": "audio", "text": "大家好,我是陈峰。", "timestamp": [ [880, 1120], // 第1个字的时间范围 (ms) [1120, 1360], // 第2个字 ... ] }] ``` ### 3.3 模型说明 | 模型 | 用途 | |------|------| | `paraformer-zh` | 中文语音识别主模型 | | `fsmn-vad` | 检测哪里有人说话 | | `ct-punc` | 自动添加标点符号 | --- ## 四、输出格式设计 ### 4.1 详细 JSON 格式 ```json { "audio_file": "/path/to/audio.wav", "full_text": "完整转录文本...", "duration_ms": 935455, "segments": [ { "char": "大", "start_ms": 880, "end_ms": 1120 }, ... ], "raw_result": { /* FunASR 原始输出 */ } } ``` ### 4.2 可读 TXT 格式 ``` ====================================== 视频转录结果 - video.mp4 ====================================== 总时长: 15:35 (15分35秒) 字符数: 2006 ====================================== 完整文本 ====================================== 大家好,我是陈峰。一直有同学问我... ====================================== 带时间戳的句子记录 ====================================== [00:01 - 00:02] 大家好,我是陈峰。 [00:05 - 00:17] 一直有同学问我能不能做一期企业级PPT模板的教程? ``` --- ## 五、常见问题 ### Q0: 调用方式错误(2026-01-13) **错误**:尝试用命令行 `funasr --input video.mp4` 调用 **正确**:只能用 Python API ```python # ❌ 错误 - 没有 funasr CLI subprocess.run(['funasr', '--input', 'video.mp4']) # ✅ 正确 - 用 Python API from funasr import AutoModel model = AutoModel(model="paraformer-zh", ...) result = model.generate(input="video.mp4") ``` ### Q0.5: 模型选错没有时间戳(2026-01-13) **错误**:用 `SenseVoiceSmall` 模型,只输出文本没有时间戳 **正确**:必须用 `paraformer-zh` 才有字符级时间戳 ```python # ❌ 错误 - 没有时间戳 model = AutoModel(model="iic/SenseVoiceSmall", ...) # ✅ 正确 - 有时间戳 model = AutoModel( model="paraformer-zh", # 这个才有时间戳! vad_model="fsmn-vad", punc_model="ct-punc", ) ``` ### Q1: 模型下载慢 首次运行会下载 ~1GB 模型到 `~/.cache/modelscope/` **解决**: - 使用国内镜像 - 或手动下载后放到缓存目录 ### Q2: 时间戳和文字对不上 **原因**:标点符号没有时间戳,需要特殊处理 **解决**: ```python # 去掉标点后再对齐 import re text_no_punc = re.sub(r'[,。!?、;:]', '', text) ``` ### Q2.5: 时间戳数量少于字符数(2026-01-13) **现象**:纯字符数828,时间戳数763,末尾67个字符没有时间戳 **原因**:FunASR 对视频末尾部分可能丢失时间戳 **解决**: ```python # 访问时间戳要兜底 if idx < len(timestamps): ts = timestamps[idx] else: ts = timestamps[-1] # 用最后一个时间戳兜底 ``` ### Q2.6: 正则表达式漏掉英文标点(2026-01-13) **现象**:搜索文本时位置偏移,因为 clean_text 里还有英文标点 **原因**:正则只移除中文标点,没处理英文 `,` `.` 等 **解决**: ```python # ❌ 错误 - 只有中文标点 clean = re.sub(r'[,。!?、;:]', '', text) # ✅ 正确 - 包含英文标点 clean = re.sub(r'[,。?!、:;""''()《》【】\s\.,!?;:\'"()]', '', text) ``` ### Q3: 长视频处理慢 **解决**: - 增大 `batch_size_s` 参数 - 使用 GPU 加速(需要 PyTorch CUDA) ### Q4: 识别准确率低 **可能原因**: - 背景噪音太大 - 说话人口音重 - 音频采样率不对 **解决**: - 预处理降噪 - 确保 16kHz 采样率 --- ## 六、性能参考 | 指标 | 值 | |------|-----| | RTF (Real-Time Factor) | ~0.16 | | 含义 | 1秒音频只需0.16秒处理 | | 15分钟视频 | 约2.5分钟处理完 | *测试环境:M1 Mac,CPU 推理*