CLI 工具:下载并增强 YouTube 播客字幕,支持 Azure OpenAI 转写与总结
Project description
podcast_transformer
podcast_transformer 是一个命令行工具,用于从 YouTube 视频中抽取字幕,并可选地调用 Azure OpenAI gpt-4o-transcribe-diarize 服务进行说话人分离。输出为包含时间戳、文本与说话人信息的 JSON。
功能特性
- 基于
youtube-transcript-api获取时间戳精确到秒的字幕段。 - 使用
yt_dlp+ffmpeg下载并转换音频,并提交至 Azure OpenAI 语音转写接口。 - 支持 B 站等多站点视频音频提取,按照 URL 主机自动设置 Referer 与缓存目录结构。
- 内置 Android 客户端回退逻辑,即使未配置 cookie 也能规避常见的 403 Forbidden 下载失败。
- 自动检测超长(超过 Azure 1,500 秒限制)或超大音频并切分成多个片段,逐段提交 Azure,并通过流式返回实时刷新进度条。
- 通过
gpt-4o-transcribe-diarize返回的说话人分段信息,将不同说话人合并入字幕。 - 兼容 Azure OpenAI
diarized_json响应中response.output[*].content等多层嵌套结构,自动提取segments/chunks字段,即使 YouTube 无字幕也能利用 Azure 转写结果产出文本。 - 支持通过
--azure-streaming/--no-azure-streaming控制 Azure 转写是否流式执行;启用时会实时刷新进度条,必要时可设置PODCAST_TRANSFORMER_DEBUG_PAYLOAD=1输出原始 chunk 便于排查。 - 摘要 Markdown 会自动复制一份到
PODCAST_TRANSFORMER_OUTBOX_DIR(默认~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Obsidian Vault/010 outbox),便于在 Obsidian 等笔记库中直接浏览。 - 当 Azure 暂未返回说话人分段时,会退回空说话人列表并继续使用已有字幕,避免 CLI 直接失败。
- 若视频已提供带时间轴的字幕,默认直接复用字幕并跳过 Azure 说话人分离,避免冗余的音频下载与 ASR 调用;如需强制执行可添加
--force-azure-diarization。 - 可选调用 Azure GPT-5 Pro(默认部署
gpt-5-pro),通过 Responses API 翻译与总结 ASR 片段,可使用--summary-prompt-file定制提示词。 - 支持通过
--summary-prompt-file指定外部 Prompt 配置文件,无需改动代码即可调整摘要策略。 - 摘要结果以标准 Markdown 格式输出,包含封面、目录与时间轴表格,并自动写入缓存目录的
summary.md文件。 - 自动加载工作目录或
PODCAST_TRANSFORMER_DOTENV指向的.env文件,简化凭据管理。 - 提供
--clean-cache与--check-cache选项,方便排查与清理缓存。 - 命令行输出 JSON,可通过
--pretty选项进行格式化。
安装依赖
如已发布至 PyPI,可直接执行:
pip install podcast-transformer
若从源码安装,可在 podcast_transformer 目录下运行:
pip install .
或使用传统方式:
pip install youtube-transcript-api yt-dlp openai
# 若网络环境需要代理,请额外安装 httpx[socks] 以支持 SOCKS 代理
pip install "httpx[socks]"
或者执行项目提供的 setup_and_run.sh 脚本,它会自动创建虚拟环境并安装必要依赖。
同时需要本地安装 ffmpeg,macOS 可通过 brew install ffmpeg,其他平台请参考官方安装说明。
Azure 配置
- 在 Azure 门户中创建 Azure OpenAI 资源,并为
gpt-4o-transcribe-diarize模型部署一个实例。 - 复制终结点、密钥以及 API 版本(未配置时默认
2024-06-01),并在命令行环境设置:
export AZURE_OPENAI_API_KEY="<your-key>"
export AZURE_OPENAI_ENDPOINT="<https://your-resource.openai.azure.com>"
# 可选:指定 API 版本与部署名称
export AZURE_OPENAI_API_VERSION="2025-03-01-preview"
export AZURE_OPENAI_TRANSCRIBE_DEPLOYMENT="gpt-4o-transcribe-diarize"
# chunking_strategy 默认使用 "auto";如需自定义可设置字符串或 JSON:
# export AZURE_OPENAI_CHUNKING_STRATEGY="server_vad"
# export AZURE_OPENAI_CHUNKING_STRATEGY='{"type": "server_vad", "threshold": 0.6}'
# 可选:配置 GPT-5 翻译/总结调用所用的 API 版本与部署名称
export AZURE_OPENAI_SUMMARY_API_VERSION="2025-01-01-preview"
export AZURE_OPENAI_SUMMARY_DEPLOYMENT="gpt-5-pro"
# 可选:覆盖 Responses API 基础地址(默认 <AZURE_OPENAI_ENDPOINT>/openai/v1)
# export AZURE_OPENAI_RESPONSES_BASE_URL="https://region-001.openai.azure.com/openai/v1"
可通过 --max-speakers 对说话人数量做最佳努力限制;超出时会将较小说话人映射到主要说话人之一。
提示:若执行
./setup_and_run.sh并包含--azure-diarization选项,脚本会在运行前检查AZURE_OPENAI_API_KEY与AZURE_OPENAI_ENDPOINT是否已设置。
环境变量管理
仓库提供 .env.example。复制后补齐密钥,即可让 CLI 自动加载:
cp .env.example .env
也可设置 PODCAST_TRANSFORMER_DOTENV=/path/to/.env 指向自定义位置,run 函数会在执行时自动读取文件并填充缺失的环境变量(不会覆盖已存在的设置)。
使用方法
# 首次或重复运行均可,脚本会自动复用 .venv
./setup_and_run.sh \
--url "https://www.youtube.com/watch?v=<video-id>" \
--language en \
--fallback-language zh-Hans \
--clean-cache \
--azure-diarization \
--azure-streaming \
--azure-summary \
--summary-prompt-file /absolute/path/to/prompt.txt \
--pretty
如果只需要字幕(无需说话人分离),省略 --azure-diarization 选项即可。若目标视频无所需语言字幕,可通过 --fallback-language 多次指定备用语言。当所有字幕均不可用时,启用 --azure-diarization 会自动调用 Azure OpenAI 完整转写与说话人分离。
默认情况下,即使添加了 --azure-diarization,只要成功获取带时间线的字幕段,CLI 就会直接输出字幕并跳过 Azure 调用;若需要强制执行 Azure 说话人分离,可附加 --force-azure-diarization,或提供 --known-speaker/--known-speaker-name/--max-speakers 参数以触发完整流程。
若希望辅助识别特定说话人,可附加 --known-speaker 名称=音频路径 选项(可多次指定),工具会自动将参照音频转为数据 URL 并传递给 Azure OpenAI。若仅有姓名提示,可使用 --known-speaker-name 姓名 多次指定(例如 --known-speaker-name Alice --known-speaker-name Bob),脚本会将所有姓名通过 known_speaker_names 参数直接发送给 Azure 接口,以提升说话人标签的准确率。
当 yt_dlp 遭遇无 cookie 时的 403 Forbidden,CLI 会自动改用 Android 客户端参数重新发起下载,并切换到移动端 User-Agent,以提升公开视频的成功率。
提示:非 YouTube URL 暂不具备内建字幕获取能力,若需转写请启用
--azure-diarization以调用 Azure OpenAI。
当生成的 WAV 超过约 25 分钟(1,500 秒)或 100MB 时,CLI 会在缓存目录下自动生成不超过约 23 分钟的 audio_partXXX.wav 片段并依序调用 Azure,从而绕过 audio duration ... is longer than 1500 seconds 等超限报错;若缓存中仍存在旧的超长片段,工具会自动清理并重新切分。若 Azure 返回空的说话人/转写结果,CLI 会回退为空列表并继续后续流程,可结合原始字幕输出完成后续摘要或导出。
当缓存文件异常或想强制重新下载音频时,可追加 --clean-cache 选项,脚本会在调用任何外部服务前删除当前 URL 的缓存目录。
若仅需检查缓存内容,可使用:
./setup_and_run.sh --url "https://www.youtube.com/watch?v=<video-id>" --check-cache
命令会输出缓存路径、存在的文件列表以及 audio.wav 是否存在。
音频文件与转换后的 WAV 会缓存于 ~/.cache/podcast_transformer/<video_id>/(或通过设置 PODCAST_TRANSFORMER_CACHE_DIR 自定义位置);对于非 YouTube 站点,会在缓存目录中包含域名与 URL 哈希前缀,重复执行时同样复用缓存,避免再次下载。
注意:部分视频仅提供其他语言字幕,脚本会尝试自动翻译为
--language指定的语言;如仍无法获取,请使用--fallback-language指明可用的字幕语言代码(可在报错信息中查看)。
GPT-5 翻译与总结
启用 --azure-summary 选项即可在原始字幕/转写结果基础上,调用 Azure GPT-5(默认部署名 gpt-5)生成翻译与总结,system prompt 详见 SUMMARY_PROMPT。命令示例:
./setup_and_run.sh \
--url "https://www.youtube.com/watch?v=<video-id>" \
--language en \
--azure-streaming \
--azure-summary \
--summary-prompt-file ./prompts/summary_prompt.txt
输出 JSON 将新增 summary 字段,内容遵循以下约定:
- 始终保留原始时间线;若原文非中文,先翻译成中文。
- 长内容会包含
Abstract、Keypoints与按主题分段的正文,每段不超过约 300 字。 - 多人对话按说话人分段,保持第一人称述说;专业名词可带原文注释。
- 同时会在对应视频缓存目录(例如
~/.cache/podcast_transformer/youtube/<video_id>/summary.md)写入一份结构化 Markdown 文件,含封面标题、目录与时间轴表格;CLI 输出会额外返回summary_path方便调用方读取该文件。
若需调整文案风格,可通过 AZURE_OPENAI_SUMMARY_DEPLOYMENT 更换部署,或在调用 CLI 时提供 --summary-prompt-file 指向自定义 prompt 文件;保持为空时则回退到内置的 SUMMARY_PROMPT。
调试提示:若需检查 Azure 分段返回的原始数据,可在命令前设置
PODCAST_TRANSFORMER_DEBUG_PAYLOAD=1,缓存目录会生成debug_payload_*.json供分析。
示例脚本
快速体验可运行:
./run_example.sh "https://www.youtube.com/watch?v=<video-id>"
脚本会自动加载同目录下的 .env 并调用 setup_and_run.sh。
Docker 部署
仓库提供 Dockerfile,可通过以下命令构建镜像:
docker build -t podcast-transformer ./podcast_transformer
运行时挂载缓存目录与 .env:
docker run --rm \
--env-file ./podcast_transformer/.env \
-v "$HOME/.cache/podcast_transformer:/app/.cache/podcast_transformer" \
podcast-transformer \
--url "https://www.youtube.com/watch?v=<video-id>" \
--language en \
--pretty
测试
项目根目录(即 podcast_transformer 目录)执行:
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest test/test_cli.py
若在其父目录运行,可将路径改为 pytest podcast_transformer/test/test_cli.py。
限制
- 需要网络访问 YouTube 以及 Azure OpenAI 服务。
- Azure OpenAI 识别质量受音频质量、部署规格与配额影响;可根据实际情况调整
--max-speakers。 - 当前实现依赖
ffmpeg进行音频转码,若本地缺失需提前安装。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file podcast_transformer-0.1.2.tar.gz.
File metadata
- Download URL: podcast_transformer-0.1.2.tar.gz
- Upload date:
- Size: 45.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb291c2e726c6f8cad0455659d7828eb17a2cfa67127b8c8c7f1b2bf9cc13222
|
|
| MD5 |
85e9193f5fbd3dc9ffa70f6df87f5802
|
|
| BLAKE2b-256 |
86d356e479644c5f0be82003e69d62be9aea34ec28a95ba29ccc5f5fd090757d
|
File details
Details for the file podcast_transformer-0.1.2-py3-none-any.whl.
File metadata
- Download URL: podcast_transformer-0.1.2-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12dabc332341bfea5192722c0764ff8e5eac7cf527f3fb7351e579b533d00056
|
|
| MD5 |
9a1d4aae58b3fad7c11777875816defa
|
|
| BLAKE2b-256 |
f8faad831946ffa8b0c404e445d2eef49664c6fffba12dc1ba18bff0173b6904
|