效率工具

YouTube 视频章节检查:自动验证时间戳与顺序

发布视频前检查描述里的章节时间戳:按 YouTube 帮助中心的三条规则(第一个时间戳是 00:00、至少 3 个且按升序、每章至少 10 秒)逐条检查,再加上“最后一章不能太短、不能超出视频时长”。有问题时退出码为 1,可以放进发布清单或 CI。

BINBHO · 图文教程

发布视频前检查描述里的章节时间戳:按 YouTube 帮助中心的三条规则(第一个时间戳是 00:00、至少 3 个且按升序、每章至少 10 秒)逐条检查,再加上“最后一章不能太短、不能超出视频时长”。有问题时退出码为 1,可以放进发布清单或 CI。

先看清成品

本机用 pytest 跑了 5 个测试,全部通过。用两份示例描述运行:有问题的那份报了 2 个错误,退出码 1;合格的那份输出 OK,退出码 0。把视频时长设成 530 秒后,又检出“最后一章只有 5 秒”。没有上传到 YouTube 去看章节的实际显示效果。YouTube 是否显示章节还取决于频道是否开通了相关功能,以官方说明为准。

注意:YouTube Data API 本身免费,但有每日配额,各方法消耗多少以官方配额页为准,本文不列数字。只上传你有权发布的视频,遵守 YouTube 社区准则和 API 服务条款;不要共享频道账号或 OAuth 凭据,在 YouTube 无法访问的地区也不要用技术手段绕过。

做完之后你会得到什么?

成果 说明
chapters.py 支持 0:00、00:00、1:02:05 三种写法
规则 官方三条规则,外加时长检查和格式检查
输出 规范化后的章节列表和所有错误

需要准备哪些环境?

项目 要求 说明
Python 3.8 以上 只用标准库,测试要 pytest

文件结构

29-youtube-B-src/
├── chapters.py
├── test_chapters.py
├── desc_bad.txt
└── desc_good.txt

第 1 步:官方规则

YouTube 帮助中心 “Video Chapters” 页面写的是:

  • Make sure that the first timestamp you list starts with 00:00.
  • Your video should have at least three timestamps listed in ascending order.
  • The minimum length for video chapters is 10 seconds.

页面还提到:如果频道还不能使用章节功能,需要先申请开通 Advanced features;如果频道有未解除的警示,或者内容可能不适合部分观众,章节功能将不可用。

第 2 步:脚本

chapters.py:

"""检查视频描述里的章节时间戳是否符合 YouTube 帮助中心的规则:
1) 第一个时间戳是 00:00;2) 至少 3 个,按升序;3) 每章至少 10 秒。
用法:python chapters.py description.txt [视频总时长秒数]"""
import re, sys

TS = re.compile(r"^\s*(?:(\d{1,2}):)?(\d{1,2}):(\d{2})\s+[-–—:]?\s*(.+?)\s*$")

def parse(text):
    out = []
    for n, line in enumerate(text.splitlines(), 1):
        m = TS.match(line)
        if m:
            h, mi, s, title = m.groups()
            if int(s) >= 60 or (h and int(mi) >= 60):
                out.append((n, None, line.strip())); continue
            out.append((n, int(h or 0) * 3600 + int(mi) * 60 + int(s), title))
    return out

def check(text, duration=None):
    ch, errs = parse(text), []
    for n, sec, t in ch:
        if sec is None: errs.append(f"第 {n} 行:时间格式不对 {t!r}")
    ch = [c for c in ch if c[1] is not None]
    if len(ch) < 3: errs.append(f"只有 {len(ch)} 个时间戳,至少需要 3 个")
    if ch and ch[0][1] != 0: errs.append(f"第一个时间戳必须是 00:00,现在是第 {ch[0][0]} 行")
    for (n1, a, t1), (n2, b, _) in zip(ch, ch[1:]):
        if b <= a: errs.append(f"第 {n2} 行:时间没有递增")
        elif b - a < 10: errs.append(f"第 {n1} 行“{t1}”只有 {b - a} 秒,每章至少 10 秒")
    if duration is not None and ch:
        last_n, last, t = ch[-1]
        if last >= duration: errs.append(f"第 {last_n} 行超出视频时长")
        elif duration - last < 10: errs.append(f"最后一章“{t}”只有 {duration - last} 秒")
    return ch, errs

def fmt(sec):
    h, r = divmod(sec, 3600); m, s = divmod(r, 60)
    return f"{h}:{m:02d}:{s:02d}" if h else f"{m:02d}:{s:02d}"

if __name__ == "__main__":
    text = open(sys.argv[1], encoding="utf-8").read()
    ch, errs = check(text, int(sys.argv[2]) if len(sys.argv) > 2 else None)
    for _, sec, t in ch: print(fmt(sec), t)
    for e in errs: print("ERROR", e)
    print("OK" if not errs else f"{len(errs)} 个问题")
    sys.exit(1 if errs else 0)

只有行首是时间戳的行才算章节。正文里出现的“12:30 开播”之类,只要不在行首,就不会被误判。

第 3 步:测试

test_chapters.py:

from chapters import check, fmt

def test_good():
    ch, e = check(open("desc_good.txt").read(), 600)
    assert e == [] and len(ch) == 5

def test_bad():
    _, e = check(open("desc_bad.txt").read())
    assert any("00:00" in x for x in e) and any("只有 5 秒" in x for x in e)

def test_hours_and_too_few():
    ch, e = check("0:00:00 a\n1:00:00 b")
    assert ch[1][1] == 3600 and any("至少需要 3" in x for x in e)

def test_bad_seconds_and_order():
    _, e = check("00:00 a\n00:75 b\n00:30 c\n00:20 d")
    assert any("格式不对" in x for x in e) and any("没有递增" in x for x in e)

def test_fmt():
    assert fmt(3725) == "1:02:05" and fmt(65) == "01:05"
python -m pytest -q     # 5 passed

第 4 步:检查两份描述

desc_bad.txt:

这期讲手冲咖啡的三个关键变量。

0:05 开场
1:30 研磨度
1:35 水温
5:10 注水节奏
$ python chapters.py desc_bad.txt
00:05 开场
01:30 研磨度
01:35 水温
05:10 注水节奏
ERROR 第一个时间戳必须是 00:00,现在是第 3 行
ERROR 第 4 行“研磨度”只有 5 秒,每章至少 10 秒
2 个问题

desc_good.txt:

这期讲手冲咖啡的三个关键变量。

00:00 开场
01:30 研磨度
02:40 水温
05:10 注水节奏
08:45 总结
$ python chapters.py desc_good.txt 600
00:00 开场
...
08:45 总结
OK

调试示例

格式都对,但最后一章太短

同一份 desc_good.txt,视频剪完后实际只有 8 分 50 秒(530 秒):

$ python chapters.py desc_good.txt 530
ERROR 最后一章“总结”只有 5 秒
1 个问题

官方规则只说每章至少 10 秒,最后一章的长度要靠视频总时长来算,所以脚本把时长作为可选参数。剪辑版本改了以后,要用新的时长再检查一次。

常见问题

现象 原因 处理
检查通过了但不显示章节 频道没开通该功能,或视频不符合条件 看帮助中心的说明
时间戳没被识别 前面有符号,比如 ▶ 00:00 时间戳放在行首
格式不对 秒数写成了 60 以上 改成正确的分:秒
想关闭自动章节 Studio 里的 Automatic chapters 选项 按帮助中心的步骤操作

模板规则

  • 章节单独成段,每行一个,时间戳放在行首。
  • 发布前用最终剪辑版的时长再跑一次检查。
  • 规则以帮助中心的原文为准,平台改规则后同步修改脚本。

项目资源

用途 地址
Video Chapters(帮助中心) https://support.google.com/youtube/answer/9884579
API 服务条款 https://developers.google.com/youtube/terms/api-services-terms-of-service

章节规则只有三条,但最常见的错误是“第一个时间戳不是 00:00”和“两个时间戳挨得太近”。把检查写成脚本,每次发布前跑一遍就能避免。