把小说转成多角色有声书,真正的技术坑其实在文本解析而非 TTS 合成
最典型的例子就是这种夹杂说话人的结构:"I told you," she said, "and you did not listen." 如果你采用最基础的 Naive 切割法(即识别引号内容),这句话会被强行拆成两条独立的对话,甚至因为中间的 she said 干扰,导致前后两段话被分给了两个不同的配音角色,听感极其诡异。更糟糕的是,很多小说存在长段的对话流,完全没有说话人标记,全靠上下文推断。一旦场景中出现第三个角色插话,基于简单逻辑的解析链条会瞬间崩掉,导致角色声音完全错位。
在实战中,我总结了三套比较有效的处理方案,建议在架构设计时就考虑进去。
首先,建议放弃纯正则方案,引入动词词典。不要试图写一个能兼容所有情况的巨大正则表达式,那样维护成本极高且极易漏掉边缘case。更稳妥的做法是建立一个包含 said / asked / whispered / muttered 及其各种变体的词典。针对 "..." 或 , "..." 这两种常见的对话顺序模式进行显式处理。通过词典匹配说话动词,再反向锁定引号内的文本归属,这种方法的准确率远高于死磕正则。
其次,必须引入指代消解(Coreference Resolution)。这是很多初学者最容易忽略的一环。即使你成功解析出了 "she said",如果你的系统不知道这个 "she" 在当前场景中具体指代谁,那么你依然无法为这段话分配正确的音色。在文学作品中,角色指代极其复杂,如果不做指代消解,虽然每句话都有声音,但声音分配错误。这种角色跳变的违和感,比单调的机器朗读更让听众难以接受。
最后,角色映射必须在全局维度锁定。这是一个极其隐蔽的坑:你绝对不能采用纯流式的处理架构。如果你的系统是边读边解析,可能会出现这种情况——在第 14 章因为置信度降低,导致主角的声音突然变了。为了避免这种灾难,必须采用“全书扫描 → 分配 → 冻结 → 渲染”的离线工作流。
一个经过验证的稳健实操工作流应该是这样的:
1. 全文预解析:扫描全书,统计所有出现的角色及其出现频次。
2. 权重分配:给高频出现的关键角色分配特定音色,低频或不明确的角色统一交给旁白。
3. 持久化存储:将这个角色与音色的 Mapping 表进行持久化存储,确保全书唯一。
4. 顺序渲染:根据已经冻结的映射表,逐章进行音频渲染。
当然,目前的通用解法依然存在死角。比如第一人称叙述(叙述者本身就是角色)、书信体小说,或者单章内频繁切换视角的复杂文本。这些场景目前很难通过纯算法完美解决,在商业级产品中,最靠谱的方案依然是在自动化流程之后,增加一个手动覆盖(Manual Override)的修正界面,允许人工干预错误的角色指派。