九组ASR配置的方言转写对比与融合实践

目录

方言字幕需要分别验证文本、时间和说话人

一段 128.847 秒的四川方言剧集音频,包含旁白、街边买蛋烘糕的对话、追逐和歌曲。对字幕或配音流水线来说,识别出文字只是第一步:漏掉整段对话、把时间标到错误位置、将同一个角色拆成多个 speaker,都会影响后续编辑。

本文比较九组 ASR 服务或配置,并讨论多源融合。它是一份针对该素材的工程案例,不是方言识别通用排行榜。本文修订时复核了对应工程的 Provider 和第 6 集 JSON 输出,没有重新调用收费 API,也没有据此宣称复现了原始听写实验。

先把比较对象和评判口径固定下来

测试 CLI 通过 Provider 接口调用服务,保留原始结果,再转换为统一分段结构:

from abc import ABC, abstractmethod

class ASRProvider(ABC):
    name: str = "base"
    input_type: str = "url"

    @abstractmethod
    def transcribe(self, audio_input: str, **kwargs) -> dict:
        ...

这只是接口,不是可直接运行的完整测试器。输入采样率、声道、音频预处理、服务地区、请求参数和后处理版本都应随运行记录保存。

对象 原评测记录的配置 复核时应注意
豆包 asr_spk_semantic preset 预设不是精确模型快照
Fish Audio 默认配置 默认模型可能变化
Gemini gemini-3.1-pro-preview 提示词和返回格式影响输出
OpenAI 原稿标为 gpt-4o-transcribe-diarize 原始 JSON 仅有全文,缺少本次调用参数,型号与格式需要请求日志确认
Qwen qwen3-asr-flash-filetrans 本次 JSON 没有 speaker 字段
腾讯云 16k_zh 说话人、情感及返回粒度由请求参数控制
讯飞 转写 API,speaker_number=0 保留具体接口版本与参数
Paraformer paraformer-v2 云服务 不等同于整套 FunASR 框架
FunASR paraformer-zh、fsmn-vad、ct-punc、cam++ 框架、模型和运行设备分别记录

Gemini 3.1 Pro 于 2026 年 2 月发布,不能把通用推理榜单成绩作为音频转写能力的证据。Google 模型说明

返回文件中没有某字段,不等于模型没有该能力。 例如 gpt-4o-transcribe-diarize 不是 Whisper;官方接口支持带说话人标签的 diarized_json,长音频还需按接口要求配置分块。工程当前 Provider 已选择 diarized_json,但这不能追溯证明旧结果使用了相同配置。因此本次 OpenAI 文件只能作为旧文本输出观察,不能据它否定模型的说话人分离能力。OpenAI 模型说明

人工标注是基准,模型一致只能作为线索

原评测由熟悉方言的人员结合画面听写关键词。完整、独立的逐字转写与带说话人时间标注尚未随文章交付,因此不报告 WER、CER 或 DER。没有现成标准文本不意味着不能计算这些指标,而是需要先建立并复核标注。

其他模型输出一致可以辅助定位疑点,不能直接当成真值。进一步评测应在查看各模型答案前固定标注规则,包括方言异体字、数字归一化、语气词、歌唱和重叠说话如何计分。

原稿还记录了其他集数的试验,但这些素材是有针对性地选择的漏段样本。它们适合排查缺陷,不能证明总体表现排名稳定。

原始输出显示了哪些问题

豆包:局部文本可用,长空白仍要独立处理

第 6 集结果包含 16 个 utterance、6 个 speaker ID。这些区间总时长为 40.840 秒,占完整音频 31.7%。这个比例是“输出区间时长 / 整段音频时长”,其中分母还包含静音与音乐,不能称为语音内容覆盖率。

最明显的相邻分段空白是 22.880 秒至 68.190 秒,约 45.31 秒。其他结果在其中包含买蛋烘糕的多轮对话。这是需要回听检查的漏识候选,而不是把所有无输出区间都自动认定为丢失语音。

豆包结果包含情感和声音性别标签,但它们也是模型预测。例如短句的声音性别标签会变化,不能据此确定角色身份。全局 singing_mand 标记也不能定位每一个歌唱片段。

Fish:补充了对话文本,不能直接照搬时间轴

Fish 输出中能找到“蛋烘糕”和“半托半托”等片段,补充了豆包空白区间内的文字。原听写记录同时指出,它把“知青返乡”转成“自己返乡”,并非完整文本都正确。

原评测逐句对照发现后段时间偏移,例如“谢谢你啊”的分段与豆包相差数秒。模型间不一致说明至少需要进一步核对,精确误差仍应以音频人工边界为基准。不能因为前 17 秒接近,就把后续时间全部视为可信。

Gemini:文本错误与角色标注要分开评估

保存的 Gemini JSON 有 30 段、3 个 speaker ID,其中“我知青返乡”被写成“我四处犯相”,“蛋烘糕”对应了不相关文本。这样的输出不宜直接作为字幕底稿。

原评测认为其角色划分较连贯,但“刚好分成 3 人”并不能证明 diarization 最准确。文件中最大结束时间为 146.500 秒,超过音频总长约 17.65 秒;使用它来映射其他模型的 speaker 之前,必须先修复时间定位并核对说话人。标签种类较多也不代表情感识别更准确。

其余服务:输出结构与识别质量各有问题

对象 保存结果中的观察 对流水线的意义
OpenAI 仅保存全文、logprobs 与 usage;有多处方言词替换 先查请求型号与返回格式,再补测结构化能力
Paraformer 21 个句段、2 个 speaker ID;部分字时间近似均匀排列 需要声学边界核验,不能仅从现象断言服务内部使用插值
FunASR 38 个句段、4 个 speaker ID;出现“蛋黄糕”等替换 可本地复现并调参,离线不代表零计算和运维成本
Qwen 23 个句段,有情感、语言和字时间;没有 speaker 字段 这份输出不能承担角色区分;服务能力需另核配置
讯飞 7 个句段,speaker 全为 0 整句较长,但已有字时间,仍可研究重新分句
腾讯云 35 个分段、4 个 speaker ID;部分对话和歌曲混在长段中 可作时间候选,不能免除边界与角色复核

这些是本次文件的结构事实,不是当前各服务全部能力的列表。尤其不要把 FunASR 框架、某个 Paraformer 模型及某厂商云接口混为同一个实验条件。

关键词对比必须使用同一分母

原稿对豆包用 3/3,对其他服务用 5 个词作分母,排除了豆包未覆盖的两项,不能公平比较。修订后将五个检查项都纳入分母,漏识同样记为未命中。

下表只统计保存全文中的字符串出现,不等于句子语义正确率。“半托半托 / 半坨半坨”按原稿认可的两种写法计入;“半头半头”不计入。若后续人工标注改变异体字政策,应统一重算所有结果。

检查项 豆包 Fish FunASR Gemini OpenAI Paraformer Qwen 讯飞 腾讯
知青返乡 ✓ — — — — — — ✓ —
蛋烘糕 — ✓ — — — — ✓ ✓ ✓
半托半托 / 半坨半坨 — ✓ — — — ✓ ✓ ✓ —
老汉儿 ✓ ✓ ✓ ✓ — ✓ — — —
职工抓到要遭处分 ✓ — — — — — — — —
命中项数 3/5 3/5 1/5 1/5 0/5 2/5 2/5 3/5 1/5

例如 Gemini 的“老汉儿”出现在错误句子中,仍会被字符串统计命中。这正说明关键词命中只能诊断特定词,不能替代完整 CER/WER。原稿据此给出的全局星级与“方言之王”评价不再保留。

多源融合先保留证据,再生成候选

融合要解决的不是选出一个全能模型,而是把文字、时间和角色分别建立可追踪来源。

先找到需要补查的区间

无输出区间可能是静音、音乐或漏识。下面的函数仅计算分段覆盖的补集,后续仍需 VAD、其他输出和音频复核:

def find_gaps(utterances, total_ms, min_gap_ms=500):
    if total_ms < 0 or min_gap_ms < 0:
        raise ValueError("durations must be nonnegative")
    intervals = []
    for u in utterances:
        start, end = u["start_ms"], u["end_ms"]
        if not 0 <= start <= end <= total_ms:
            raise ValueError("segment outside audio")
        intervals.append((start, end))
    gaps, prev_end = [], 0
    for start, end in sorted(intervals):
        if start - prev_end >= min_gap_ms:
            gaps.append((prev_end, start))
        prev_end = max(prev_end, end)
    if total_ms - prev_end >= min_gap_ms:
        gaps.append((prev_end, total_ms))
    return gaps

原示例漏掉了尾部空白,也没有排序和范围检查。修订后的计算不会将超出音频长度的时间直接混入融合。

文本 Diff 只提出候选,不产生时间证据

现有工程把豆包与 Fish 的全文提交给 LLM,寻找主要结果缺少的语句。第 6 集 Diff 文件保存了 10 个候选及文本字符位置。字符偏移不是毫秒时间戳;仍需用音频上下文、顺序与其他服务的时间候选进行对齐。

单纯用“语义相似”覆盖原文也可能把两个不同句子合并。每个候选应保留原始文本、来源、匹配依据及人工修订状态;置信不足时留待审核,不强制填进最近时间窗。

当前保存的融合文件包含 27 段:16 段来自豆包、10 段来自 Tencent + Fish、1 段来自 Fish。这与原稿所述“26 段,18 + 8”不一致;后者不能继续当作当前工程结果。

Forced Alignment 定位给定文本,不能恢复未知文本

当文本已经人工确认,但时间不可靠时,可以尝试强制对齐。它根据给定音频和文本估计声学边界,不负责发现所有漏词,也不能让错误文本自动变正确。若所有转写来源都漏掉某句话,应先回听或重新识别,不能凭空交给对齐器补全。

工程保存的 FA 文件有 26 句,其中 9 句的平均分数低于 0.1。该分数不能跨模型直接比较,也不是已经校准的正确概率;低分提示复核,不能保证其他句子都准确。重叠说话、方言、歌唱和背景音乐仍可能导致错位。

Gemini 角色映射、时间窗口匹配和 FA 都可以提供候选,但最终目标是同一套可复核字幕,而不是把每个模型在不同区间的最佳结果简单拼接后宣布整体最优。

从这个案例得到的选型方法

对这段素材,值得继续试验的是:以较可靠区间为起点,用其他来源定位漏段,单独修复时间与角色,并保留人工审核入口。是否值得四源融合,还要比较新增成本、延迟和复核工作量。

原稿的统一价格表没有保留可复核的计价来源、地区和完整耗时日志,不能用它宣称某组合“成本可忽略”。后续记录应区分上传、服务排队、推理、轮询和下载时间;本地模型另记设备、预热和资源成本。准确率提高多少、每分钟素材减少多少人工修订,比星级总分更能指导生产选型。

下一轮应使用事先固定、覆盖不同角色和噪声条件的样本,发布允许公开的转写基准、版本与配置,分别统计 CER、漏段、边界误差、DER 和人工修订时长。当前案例已经说明:字段齐全不等于结果准确,模型间一致不等于真值,融合结果也需要独立验收。

评论