YouTube Shorts API 踩坑指南:官方文档没写清楚的几件事

YouTube 并没有专门的 Shorts API,上传 Shorts 用的就是普通的 videos.insert。本文整理了用 API 自动发布 Shorts 时最常遇到的问题:上传成功后视频仍在处理、每个项目每天 100 次上传的配额上限、自定义缩略图需要频道验证、categoryId 的地区限制、视频没被识别成 Short,以及 Analytics API 无法单独区分 Shorts 流量,并给出对应的处理方式和示例代码。

想用程序批量发 YouTube Shorts,第一步通常是去搜 “YouTube Shorts API”。搜完会发现,Google 的文档里根本没有一个叫 Shorts 的章节。

这篇文章根据 bundle.social 联合创始人 Marcel Czuryszkiewicz 的文章 YouTube Shorts API - What Google’s Documentation Won’t Tell You 改写。他们做社交媒体发布 API,和 Shorts 上传接口打了两年交道,下面是他们总结出来的几个坑。

先说结论

  • 没有 Shorts 专用接口:上传 Shorts 用的就是普通的视频上传接口,由 YouTube 判断这条视频算不算 Short。
  • 上传成功 ≠ 可以播放:接口几秒就返回成功,但视频要再处理几分钟才能看,产品交互要把这段时间考虑进去。
  • 配额是最先碰到的天花板:上传不再消耗公共配额,而是单独计数,每个项目每天 100 次 videos.insert,其余操作共用 10,000 单位。限额按项目算,不按频道算。

一、根本没有 “Shorts API”

从 API 的角度看,Shorts 只是满足特定条件的普通视频。YouTube 判断一条视频是不是 Short,主要看两点:

  • 竖屏或方形画幅,9:16 最理想
  • 时长不超过 3 分钟(180 秒)

没有需要设置的标记,没有专门的端点,也没有单独的上传流程。直接调用 YouTube Data API v3 的 videos.insert,传一个短的竖屏视频,剩下的交给 YouTube。

这件事文档里其实写了,只是散落在好几个页面里,没有一处明确提到 “Shorts”。不少开发者花了几个小时找 Shorts 专区,最后才发现自己一直在看的就是正确的文档。

好处是:如果你已经写过普通视频的上传代码,拿来传 Shorts 一行都不用改。端点、鉴权、元数据结构完全一样,区别只在上传的内容本身。

二、上传成功之后,视频还在“处理中”

这是生产环境里一定会遇到的问题。

通过 API 上传视频,几秒内就能拿到成功响应和视频 ID,界面上显示“发布成功”。然后用户点进去一看,是处理中的画面,甚至直接报错。

每条视频上传后,YouTube 都要做一系列后台处理:

  • 转码成多种分辨率
  • 生成缩略图(如果没传自定义缩略图)
  • 内容分析
  • 其他后端流程

一条 30 秒的 Short,通常需要 1~3 分钟。视频更长或者赶上高峰期,时间会更久。

处理状态可以通过 videos.list 查询,part 参数带上 processingDetails。问题在于,刚上传完的时候 processingDetails 字段可能根本不存在,所以既要轮询,也要处理字段缺失的情况:

const checkProcessingStatus = async (videoId, accessToken) => {
  const response = await fetch(
    `https://www.googleapis.com/youtube/v3/videos?id=${videoId}&part=processingDetails,status`,
    {
      headers: { Authorization: `Bearer ${accessToken}` }
    }
  );

  const data = await response.json();
  const video = data.items?.[0];

  // 刚上传时 items 可能为空,processingDetails 也可能还没生成
  if (!video || !video.processingDetails) {
    return { status: 'processing', progress: 'unknown' };
  }

  return {
    status: video.processingDetails.processingStatus,
    progress: video.processingDetails.processingProgress
  };
};

应用里可以从这几种方式里选:

  • 界面上展示“处理中”状态,轮询到处理完成为止
  • 使用 YouTube 的推送通知(有这个功能,但关于处理完成事件的文档很少)
  • 直接告诉用户,视频需要几分钟才能观看

总之,别在上传接口返回成功时就认为视频可以看了,否则用户一定会来反馈。

三、配额:最先卡住你的地方

YouTube API 的配额机制不太直观,而且它会比你预想的更早成为应用的瓶颈。

每个 API 操作都要消耗一定的配额。根据官方配额说明,一个项目每天有 100 次 videos.insert、100 次 search.list,这两个各自单独计数,其他操作共用 10,000 单位。具体消耗可以查配额计算器:

操作 消耗 每日上限
上传视频(videos.insert) 1 次,单独计数 100 次
设置自定义缩略图(thumbnails.set) 50 单位 约 200 次
列出视频(videos.list) 1 单位 10,000 单位内
读取视频元数据 1 单位 10,000 单位内

每天 100 次上传,对单个创作者来说足够了。但如果你做的是多频道排期发布工具,这就是最先撞上的上限。而且它是按项目算的,接入再多频道也不会多出上传次数。

超出配额时返回的是一个通用的 403,reason 为 quotaExceeded,不会告诉你什么时候重置(太平洋时间午夜),也不会告诉你已经用了多少。

要做正式的生产应用,就得在 Google Cloud Console 里申请提高配额:填表说明用途、估算用量,然后等 Google 审核,通常要几天到几周。在向用户承诺上传功能之前,就应该把这段等待时间算进去。

在配额批下来之前,代码里需要自己记账:

// 这些操作从每日 10,000 单位的公共池里扣
const QUOTA_COSTS = {
  'videos.list': 1,
  'channels.list': 1,
  'thumbnails.set': 50
};

// videos.insert 和 search.list 各自单独计数,不占公共池
const BUCKETS = {
  'videos.insert': { limit: 100, cost: 1 },
  'search.list': { limit: 100, cost: 1 }
};

// 配额在太平洋时间午夜重置,用太平洋时区的日期作为“当天”的标识
const pacificDay = () =>
  new Intl.DateTimeFormat('en-CA', { timeZone: 'America/Los_Angeles' }).format(new Date());

class QuotaTracker {
  constructor(dailyLimit = 10000) {
    this.dailyLimit = dailyLimit;
    this.reset();
  }

  reset() {
    this.day = pacificDay();
    this.used = 0;
    this.bucketUsed = {};
  }

  rollover() {
    if (pacificDay() !== this.day) this.reset();
  }

  canAfford(operation) {
    this.rollover();
    const bucket = BUCKETS[operation];
    if (bucket) {
      return (this.bucketUsed[operation] ?? 0) + bucket.cost <= bucket.limit;
    }
    return this.used + QUOTA_COSTS[operation] <= this.dailyLimit;
  }

  record(operation) {
    this.rollover();
    const bucket = BUCKETS[operation];
    if (bucket) {
      this.bucketUsed[operation] = (this.bucketUsed[operation] ?? 0) + bucket.cost;
      return;
    }
    this.used += QUOTA_COSTS[operation];
  }
}

调用前先 canAfford,调用成功后 record。如果服务是多实例部署,这个计数要放到 Redis 或数据库里,不能只存在进程内存中。

四、自定义缩略图

Shorts 的自定义缩略图可以设置,但行为和想象的不太一样。

普通视频的缩略图很重要,观众刷首页时第一眼看到的就是它。Shorts 就没那么依赖缩略图了,因为 Shorts 信息流里直接播放视频本身。不过在频道主页、搜索结果、嵌入和分享等场景里,缩略图仍然会出现。

通过 thumbnails.set 可以上传自定义缩略图,文档没讲清楚的有两点:

  • 缩略图的处理和视频处理是分开的。可能视频已经能播了,缩略图还在 pending;也可能视频上传成功,缩略图却静默失败。
  • 频道必须完成手机号验证,才能上传自定义缩略图。如果你的应用让用户接入自己的频道,就会遇到部分用户缩略图上传失败的情况,而错误信息不一定会直接说明是验证的问题。

所以不少开发者干脆不给 Shorts 传自定义缩略图,让 YouTube 从视频里自动截取。对 Shorts 信息流来说影响不大,还少了一个出错的环节。另外别忘了 thumbnails.set 每次要消耗 50 单位配额。

五、categoryId 的地区限制

上传视频时必须指定 categoryId,这是代表内容分类(音乐、游戏、教育等)的数字编号。

文档没提到的是:不是所有分类在所有地区都可用。如果用户所在地区不支持某个分类,上传会失败,而且报错信息看不出原因。videoCategories.list 可以按地区查询可用分类,但大多数人要等到海外用户上传出错才会想起来查。

稳妥的做法有两种:

  • 默认使用 "22"(People & Blogs),这个分类在各地区都可用
  • 根据用户频道所在地区动态拉取可用分类,只展示这些选项

六、“这条到底算不算 Short?”

还有一种情况:视频完全符合条件(3 分钟以内、竖屏),YouTube 却没把它当成 Short。

这种事确实会发生,文档里找不到解释。

从 bundle.social 的观察来看,除了基本条件,YouTube 内部还有额外的判断逻辑。通过 API 上传的视频有时会落在灰色地带:是短视频,但没有进入 Shorts 信息流,也没有使用 Shorts 播放器。

在标题或描述里加上 #Shorts 似乎能提高识别成功率,尽管 Google 官方说过这不是必需的。

另外还有一些时间因素说不清楚:在某些时段上传,或者上传到某些特征的频道,分类结果似乎会不同。他们遇到过同一个视频相隔几分钟上传,结果被区别对待的情况。

实际能做的是:

  1. 把该满足的条件都满足(画幅正确、3 分钟以内)
  2. 在描述里加上 #Shorts 作为保险
  3. 接受有一定比例的上传不会被识别为 Short
  4. 如果分类结果对业务很关键,就加上校验和重试逻辑

七、Analytics 拆不出 Shorts 数据

如果要通过 API 拉 Shorts 的数据分析,也要有心理准备。YouTube Analytics API 设计时还没有 Shorts,这一点在使用中很明显。

Shorts 的播放量计入普通的观看指标,通过 API 很难把 Shorts 播放和普通视频播放分开。Shorts 货架、Shorts 信息流和直接播放的数据都是合在一起的。

这几年陆续加了一些 Shorts 相关指标(比如来自 Shorts 信息流的播放量),但文档往往比功能更新得慢,YouTube Studio 里能看到的数据,API 不一定已经开放。

bundle.social 的做法是:能拿到什么就展示什么,明确标注每个数字代表的含义,不假装拥有 API 并不提供的细分数据。误导用户对数据的理解,比承认平台有局限更糟。

小结

把上面的经验压缩一下:

  1. 用标准的视频上传流程。不用找不存在的 Shorts 专用接口,视频做成竖屏、控制时长,YouTube 会自己判断。
  2. 从第一天起就把配额纳入架构设计。记录用量、设置限制,在真正需要之前就去申请提额。
  3. 在交互上处理好视频处理延迟。不承诺立即可播,展示处理状态,需要立即展示视频时就轮询。
  4. 用多个地区、多种频道配置测试。分类、验证状态、地区限制这类边界情况,只用自己的开发者账号是测不出来的。
  5. 在描述里加 #Shorts 作为保险。理论上不需要,实际上对识别有帮助。
  6. 做好 API 随时变化的准备。接口、配额消耗、处理流程、Shorts 判定逻辑,Google 都可能不打招呼就调整。

YouTube 的这套 API 诞生在 Shorts 出现之前,Shorts 是后来加进去的,所以很多地方用起来不顺手。了解这些特性,是做好 YouTube 自动化发布的前提。

原文链接:YouTube Shorts API - What Google’s Documentation Won’t Tell You

关于

关注我获取更多资讯

月球基地博客公众号二维码,扫码关注获取更多 AI 与编程资讯
📢 公众号
月球基地博客作者个人微信二维码,扫码交流 AI 与编程话题
💬 个人号
使用 Hugo 构建
主题 Stack 由 Jimmy 设计