Skip to Content

YouTube 导入流程

用户粘贴 YouTube 链接后,API 仅创建元数据记录;音频下载与转写由 Worker 异步完成。

流程图

API 侧:轻量创建

POST /api/media/youtube 解析 URL 提取 videoId,支持 youtube.comyoutu.bemusic.youtube.com

创建记录时:

  • sourceType: youtube
  • youtubeVideoIdyoutubeUrl 唯一索引去重
  • coverUrl: https://i.ytimg.com/vi/{videoId}/hqdefault.jpg
  • 不下载音频audioS3Key 为空
  • subtitleStatus: pending

若同一视频已被其他用户添加,当前用户仅创建 UserMedia 关联,复用全局 Media 及其处理进度/字幕。

Worker 侧:下载 + 登记

元数据探测

Worker 调用 yt-dlp --dump-single-json --skip-download 获取标题与时长,回写 API 更新占位标题(如 YouTube {videoId} → 真实标题)。

音频下载

yt-dlp -x --audio-format m4a 下载到临时目录。可通过环境变量配置:

  • YTDLP_BIN:可执行文件路径
  • YTDLP_COOKIES_FROM_BROWSER:从浏览器导入 Cookie(默认 chrome

上传与登记

  1. 计算文件 SHA-256
  2. POST /worker/jobs/{id}/audio-upload-url 获取预签名 URL
  3. PUT 上传到 R2
  4. POST /worker/jobs/{id}/audio 登记 fileHashaudioS3Key

registerAudiosubtitleStatus 重置为 pending(等待转写),并尝试 attachSubtitlesByFileHash——若该音频指纹已有字幕则跳过转写。

链式转写

YouTube 下载完成后,Worker 在同一进程继续调用 processTranscribeJob,无需等待下一轮轮询。

App 侧播放

YouTube 媒体通过 react-native-youtube-iframe / WebView 播放,字幕仍从 API 拉取,与本地文件播放体验一致。

播放器在 subtitleStatuspending / processing 期间轮询字幕,首段产出后即可展示。

注意事项

  • YouTube 下载依赖 yt-dlp,受平台策略影响可能需要 Cookie 或代理
  • 占位标题会在 Worker 探测元数据后更新
  • 音频指纹去重与本地文件共用同一套 fileHash 机制——若用户曾上传相同音频的本地副本,登记后会直接复用字幕