【直播切片工作台】第26章:字幕断句与导出

简介: 第26章详解字幕断句与导出:将ASR分句智能切分为≤12字的视频字幕行,支持标点断句、西文/数字词不拆、Unicode级精准计数,并通过词级时间戳或比例分配实现高保真时间对齐,纯函数实现,可测试、可复用。(239字)

第26章:字幕断句与导出

本章分析 internal/pkg/asr/split_utterance.go 与 subtitle_txt.go:把 ASR 分句加工成「适合视频字幕」的短行——按标点断句、超长均分(英文词与数字词不拆)、词级时间对齐或比例分配兜底。这是一个算法密度很高的小模块,读它可以学到「产品规则如何翻译成纯函数」。

流程

一句话从 ASR 到字幕行的旅程:SplitUtteranceForCaptions(u Utterance) []TimedSegment 输入一条分句(可能长达几十字),输出若干字幕行(每行 ≤ 12 字,MaxCaptionRunes 常量)。处理分四步:

  1. 标点断句:splitByPunctuation 按断句标点(。!?;等,isBreakPunctRune 判定)切成子句;
  2. 边缘标点清理:trimCaptionEdgePunct 剥掉行首行尾的空白与断句标点(含省略号 …/... 的特判)——注释明示产品规则:「成片每行会剥离首尾断句标点,保证行首行尾均非标点」;
  3. 超长均分:子句仍超 12 字则 splitBalancedPreferIntact 均分,但英文词与数字词(captionAtom 的 keepIntact 标记)整段不拆——「Beautiful」不能被劈成「Beauti」+「ful」,「2024」不能变「20」+「24」;
  4. 时间分配:优先 assignTimesWithWords——用词级时间戳按各行的字符覆盖区间精确切时间;无词数据时退化 assignTimesProportional 按字符数比例线性插值。

字幕导出(subtitle_txt.go)则在段落层把全文拼成带说话人标记的纯文本 TXT(供素材页下载,第 21 章的 DownloadASRSubtitle)。

实现

算法实现的三处巧思:

  • captionAtom 三元组:{text, keepIntact, runes} 把「原子不可拆」的语义建模成数据——英文词/数字词整段成一个 atom(keepIntact=true),中文每字一个 atom。均分算法面对的是同构的原子序列,不用特判文种。
  • SplitHostPort 式的 rune 操作:全部字符串处理按 []rune(unicode/utf8),中文、emoji、英文混排的字数统计按 Unicode 码点——与 model 包的 VideoProjectTitleMaxRunes 同一套计数观(第 11 章),中英文混合不出「字节计费」事故。
  • 两级时间分配:词级对齐是理想路径(ASR 开了 show_utterances 必有 words),比例分配是兜底(老数据或上游降级)——精度能力逐级降级而不失败。

设计上该模块是纯函数集合:输入 Utterance 输出切片,无 IO、无状态,split_utterance_test.go 用表驱动测试覆盖中文长句、英文句、数字、无词数据、全标点等边界——算法正确性靠穷举用例保证。

字幕行长度 12 字的选择:竖屏短视频(9:16)单行可视宽度约 12~16 字,12 字是安全上限;这与剪映草稿字幕轨的默认样式参数(第 41 章 CaptionsStep)配合,成片无需人工调字幕。

📌 设计决策

  • 断句规则在 Go 侧实现而非交给剪映:剪映自动字幕不可控,Go 侧纯函数可测试、可迭代、跨项目复用(字幕 TXT 导出也用同一套)。
  • keepIntact 保护西文词:中文可任意断(读者可容忍),西文断词不可读——一行规则避免大量返工。
  • 词级时间优先、比例兜底:精确度取决于上游能力但不被其绑架。

代码示例

断句主流程(四步管线):

// internal/pkg/asr/split_utterance.go(节选)
// MaxCaptionRunes 单条字幕最大字数(按 Unicode rune 计,含标点与英文字母)。
const MaxCaptionRunes = 12

// SplitUtteranceForCaptions 将一句 ASR 按标点断句,超长则均分
//(英文词与数字词不拆),并切分时间。
func SplitUtteranceForCaptions(u Utterance) []TimedSegment {
   
    text := strings.TrimSpace(u.Text)
    if text == "" {
   
        return nil
    }
    var lines []string
    for _, clause := range splitByPunctuation(text) {
   
        clause = trimCaptionEdgePunct(clause) // 行首行尾非标点
        if clause == "" {
   
            continue
        }
        for _, line := range splitBalancedPreferIntact(clause, MaxCaptionRunes) {
   
            line = trimCaptionEdgePunct(line)
            if line == "" {
   
                continue
            }
            lines = append(lines, line)
        }
    }
    if segs, ok := assignTimesWithWords(u, lines); ok {
    // 词级时间对齐
        return segs
    }
    return assignTimesProportional(u, lines) // 比例插值兜底
}

边缘标点清理(含省略号特判):

// trimCaptionEdgePunct 去掉首尾空白与断句标点(含 … / ...),
// 使成片行首行尾非标点。
func trimCaptionEdgePunct(s string) string {
   
    runes := []rune(strings.TrimSpace(s))
    for len(runes) > 0 {
   
        if len(runes) >= 3 && runes[0] == '.' &&
            runes[1] == '.' && runes[2] == '.' {
   
            runes = runes[3:]
            continue
        }
        if runes[0] == '…' || isBreakPunctRune(runes[0]) {
   
            runes = runes[1:]
            continue
        }
        break
    }
    // 尾部同理省略……
    return string(runes)
}

小结

  • 字幕断句 = 标点切分 → 边缘清理 → 12 字均分(西文词不拆)→ 词级/比例两级时间分配。
  • 纯函数 + 表驱动测试,算法规则全部产品语义化(行首非标点、西文不断词)。
  • 12 字上限与竖屏字幕样式、剪映轨参数三方对齐。

思考题

  1. 均分算法遇到「一个英文词就超 12 字」(如超长 URL 朗读文本)会怎样?该加什么兜底?
  2. 词级时间对齐在多行共享一个词的时间窗时如何避免行间重叠?找出 assignTimesWithWords 的处理方式。

项目信息

  • GitHub仓库:Chyona/live-mixer
相关文章
|
5天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
2111 13
|
云安全 安全 网络安全
|
5天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
911 1
|
18天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
3062 49
|
11天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2108 2
|
5天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
|
10天前
|
人工智能 JSON Linux
【保姆级】ComfyUI部署教程(下载+安装+配置+工作流,2026最新)
ComfyUI 是一款开源节点式AI生成工具,支持图像、视频、音频及3D内容创作。通过拖拽连线组合模型加载、提示词、采样等节点,构建可复用、易修改的工作流,兼容SD1.5、SDXL、Flux、Qwen Image等主流模型。
|
4天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)

热门文章

最新文章