发布视频前检查描述里的章节时间戳:按 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”和“两个时间戳挨得太近”。把检查写成脚本,每次发布前跑一遍就能避免。