从零到一,全栈手搓 AI 智能播客平台------我的完整开发手记
引言:这个项目是做什么的?
Smart Podcast Platform 是一个端到端的智能播客制作平台。它的核心能力很简单:用户上传一段视频或音频,AI 自动理解内容、设计音色、生成播客,全程无需人工干预。
传统的 AI 音频工具通常停留在"生成文字脚本"的层面------用户拿到脚本后,还需要自己找配音、做剪辑、调音效,整个流程割裂且低效。这个项目试图把整个链条打通:从内容理解 到音色设计 ,从语音合成 到专业混音,全部由 AI Agent 自动完成。
这是我个人独立开发的全栈项目,从后端 Python 到前端 Vue 3,从 LangGraph Agent 编排到 pydub 音频处理,完整覆盖了一个 AI 音频应用的方方面面。
代码库地址:github.com/XingtongCai...
0、相关细节说明文章
以下三篇是关于这个Agent更详细说明:
1.第一个 AI Agent 项目:从零搭建 AI 音频创作助手(入门篇) : 这个是第一版本,里面主要进行初期框架搭建,包含Vue3 + ai-elements-vue 搭前端界面,LangChain 1.0 × AG-UI 协议 × Qwen TTS 驱动后端,支持定制音色,复刻音色和配音功能。
2.第一个 AI Agent 项目:从零搭建 AI 音频创作助手(进阶篇) : 这个是第二版本,新增了完整的播客后期制作能力,包括音频拼接、智能BGM选择、音轨混音三大核心功能,同时新增了音频资源管理API和语音输入功能,实现了从前端上传、语音输入到后端处理的全链路闭环。
3.第一个 AI Agent 项目:从零搭建 AI 音频创作助手(高级篇): 这个是第三版本,新增了音频、视频识别能力、临时-永久双层存储架构、定时清理机制和更智能的提示词系统,让播客 Agent 从单纯的"语音合成工具"升级为"全链路音频内容创作平台"。
一、项目架构总览
1.1 技术栈一览
| 层级 | 技术选型 | 核心作用 |
|---|---|---|
| 前端框架 | Vue 3 + TypeScript + Vite | 提供流式对话界面与播客管理 |
| UI 组件 | shadcn-vue + Tailwind CSS | 深色主题的现代化交互体验 |
| AI 框架 | LangChain + LangGraph | Agent 编排与多轮对话记忆 |
| 后端服务 | FastAPI + Uvicorn | REST API + SSE 流式响应 |
| 通信协议 | AG-UI Protocol | 前后端 Agent 事件标准化通信 |
| 语音引擎 | 阿里云 DashScope (Qwen-TTS) | 音色设计、语音克隆、语音合成 |
| 语音识别 | 阿里云 DashScope (Qwen-ASR) | 高精度语音转文字,支持 ITN 标准化 |
| 多模态模型 | qwen3.5-omni-plus | 图片/视频/音频统一理解 |
| 音频处理 | pydub + FFmpeg | 音频拼接、混音、后期制作 |
1.2 系统架构图
css
graph TB
A[用户浏览器] --> B[Vue 3 前端]
B --> C[FastAPI 后端]
C --> D[LangGraph Agent]
D --> E[LLM 推理引擎]
D --> F[工具调用层]
F --> G1[Qwen-TTS 音色设计]
F --> G2[Qwen-TTS 语音克隆]
F --> G3[Qwen-ASR 语音识别]
F --> G4[Qwen-Omni 多模态理解]
F --> G5[音频拼接与混音]
C --> H[存储层]
H --> H1[音频文件存储]
H --> H2[音色索引管理]
H --> H3[配置持久化]
B --> I[AG-UI 协议]
I --> C
二、核心技术深度解析
2.1 Agent 智能体:不只是"调用 API"
传统的 AI 应用通常是"用户输入 → 调用 API → 返回结果"的线性流程。但在播客制作场景中,这个流程要复杂得多:
- 用户可能上传视频(需要多模态理解)
- 用户可能上传音频(需要语音识别)
- 用户可能要求特定音色(需要音色设计)
- 最终需要混音输出(需要音频后期处理)
我们的 Agent 系统通过 LangGraph 实现了智能编排:
ini
# backend/app/services/agent_service.py
agent = create_agent(
name="tts_agent",
model=model, # LLM 推理引擎
tools=tools, # 注册 9 个专业工具
system_prompt=full_prompt, # 播客专家角色定义
checkpointer=InMemorySaver() # 多轮对话记忆
)
核心设计理念:
- 自主决策:Agent 根据用户输入自动判断需要调用哪些工具,无需预设固定流程
- 链式调用:复杂任务自动编排多步骤工具调用(理解内容 → 设计音色 → 合成语音 → 混音输出)
- 上下文感知:自动从对话历史中提取信息,避免重复询问用户
- 记忆持久化 :基于
InMemorySaver实现多轮对话状态保持
2.2 流式通信:AG-UI 协议的妙用
我们采用了 AG-UI 协议(Agent-User Interaction Protocol),将 Agent 的各种行为标准化为事件流:
python
# backend/app/services/stream_processor.py
class StreamProcessor:
async def process_stream(self, agent, messages):
# 1. 发送运行开始事件
yield RunStartedEvent(...)
# 2. 流式处理 Agent 输出
async for chunk in agent.astream(...):
if isinstance(chunk, AIMessage):
# 文本内容 → TextMessageContentEvent
yield TextMessageContentEvent(delta=content)
elif hasattr(chunk, 'tool_calls'):
# 工具调用 → ToolCallStartEvent + ToolCallArgsEvent
yield ToolCallStartEvent(tool_call_name=name)
协议事件类型:
| 事件 | 含义 | 前端展示 |
|---|---|---|
RUN_STARTED |
Agent 开始运行 | 加载动画 |
TEXT_MESSAGE_START/CONTENT/END |
文本流式输出 | 打字机效果 |
TOOL_CALL_START/ARGS/END |
工具调用过程 | 工具卡片展开 |
TOOL_CALL_RESULT |
工具返回结果 | 结果展示 |
前端通过 ai-elements-vue 组件库,将这些事件渲染为丰富的交互界面:思维链展示、工具调用卡片、代码块高亮等。
2.3 音色设计:让 AI "开口说话"
这是整个系统最核心的功能模块。我们基于阿里云 DashScope 的 Qwen-TTS 引擎,实现了两种音色生成方式:
方式一:文本描述生成音色(Voice Design)
用户只需用文字描述想要的音色特征:
python
# backend/app/tools/qwen_tts.py
@tool("qwen_voice_design", args_schema=VoiceDesignInput)
def qwen_voice_design_tool(
voice_description: str, # 如:"沉稳的中年男性,音色低沉浑厚,富有磁性"
text: str, # 测试文本
language: str = "zh"
) -> str:
# 调用 DashScope API,传入音色描述文本
# API 返回 voice_id 和预览音频
...
技术亮点:音色描述直接作为 API 参数,无需训练或微调,零样本生成。
方式二:参考音频复刻(Voice Cloning)
上传一段参考音频,AI 自动复刻其音色特征:
ini
@tool("qwen_voice_cloning", args_schema=VoiceCloningInput)
def qwen_voice_cloning_tool(
voice_id: str = "", # 已设计的音色ID
local_path: str = "", # 本地音频路径
reference_audio: str = "", # 上传的参考音频
text: str = ""
) -> str:
# 优先级:voice_id > local_path > reference_audio
# 1. 注册音色 → 2. 合成语音 → 3. 保存本地
...
参数优先级设计 :voice_id > local_path > reference_audio,确保已设计的音色可以复用,避免重复注册。
2.4 多模态理解:让 AI "看懂"和"听懂"
播客内容的来源不限于文字------用户可能上传视频、音频、图片等各种格式。我们集成了 qwen3.5-omni-plus 模型,提供统一的多模态理解能力:
python
# backend/app/tools/qwen_multimodal.py
@tool("qwen_multimodal_tool")
def qwen_multimodal_tool(media: str, prompt: str) -> str:
# 1. 智能解析媒体来源(URL / 本地路径 / base64)
media_content = _resolve_media_source(media)
# 2. 大视频自动分割(>21MB 自动切片)
if isinstance(media_content, list):
# 对每个片段分别调用 API,合并结果
# 3. 调用多模态 API
response = _call_multimodal_api(messages)
return _extract_text_from_response(response)
关键设计决策:
- 大视频分割策略 :当文件超过 21MB 时,自动使用
moviepy分割为多个片段,每段约 10MB,确保 base64 编码后不超过 API 限制 - 统一媒体抽象 :
_resolve_media_source()函数将 URL、本地路径、base64 统一转换为 API 所需的格式 - 格式智能识别 :根据文件扩展名自动选择
image_url/video_url/input_audio类型
音频理解:不只是"听",而是"懂"
除了视频和图片,多模态模型同样支持音频内容理解。用户上传一段音频,模型可以直接分析其中的语义内容、情感色彩、甚至识别说话人的语气和节奏------这对于播客内容创作尤为重要,因为很多用户会直接上传录音素材作为播客的原始材料。
ini
# 音频理解调用示例
messages = [
{"role": "user", "content": [
{"input_audio": "https://example.com/podcast-raw.mp3"},
{"text": "请分析这段音频的主要内容和情感基调"}
]}
]
response = client.chat.completions.create(
model="qwen3.5-omni-plus",
messages=messages
)
# 返回:内容摘要 + 情感分析 + 关键信息提取
2.5 音频后期制作:从"语音片段"到"专业播客"
生成语音只是第一步,真正的播客需要专业的后期处理。我们基于 pydub 实现了完整的音频处理管线:
python
# backend/app/tools/audio_mixing.py
# 工具1:音频拼接
@tool("concatenate_audio")
def concatenate_audio_tool(
audio_files: List[str],
crossfade_duration: int = 200, # 交叉淡入淡出
silence_duration: int = 1200 # 片段间静音
) -> str:
# 按顺序拼接多个音频片段
...
# 工具2:智能BGM选择
@tool("select_background_music")
def select_bgm_tool(
scene_description: str, # 如"欢快的开场"
duration_seconds: float = None
) -> str:
# 基于文件名关键词匹配 BGM
# 自动循环/裁剪以匹配时长
...
# 工具3:专业混音
@tool("mix_audio_with_bgm")
def mix_audio_with_bgm_tool(
voice_audio: str,
bgm_audio: str,
bgm_volume: float = -26, # BGM 约 5% 音量
intro_duration: float = 3.0 # 开场原声时长
) -> str:
# BGM 开场(原音量)→ 过渡(渐变)→ 背景(5%音量)
...
混音策略设计:
shell
BGM 音量曲线:
100% ┤ ┌────── 开场(原声 BGM)
│ │
5% ┤─────┼──────────────────── 背景(-26dB)
│ │
└─────┴────────────────────→ 时间
0s 3s 淡入过渡 2s
这种设计模拟了专业播客的听觉体验:开场时 BGM 烘托氛围,过渡后降低为背景音,确保人声清晰。
2.6 配置管理:多层级优先级策略
项目采用 配置文件 > 环境变量 > 默认值 的三级配置优先级:
ini
# backend/app/utils/config_manager.py
def get_config_value(key: str, env_key: str, default: str = "") -> str:
# 1. 先读 config.json(前端可视化配置)
config = load_config()
value = config.get("llm", {}).get("openai_api_key")
# 2. 再读环境变量
if not value:
value = os.getenv("OPENAI_API_KEY")
# 3. 最后用默认值
return value or default
设计意图 :用户可以通过前端界面(VisualConfig.vue)直接修改配置,无需手动编辑 .env 文件。配置自动持久化到 storage/config.json,降低使用门槛。
2.7 音频索引系统:轻量级的资源管理
我们没有引入数据库,而是用 JSON 文件实现了轻量级的音频资源索引:
less
// storage/voice_index.json
[ { "id": "uuid", "local_path": "storage/audios/xxx.wav", "voice_id": "voice-xxx", "model_name": "cosyvoice-v3.5-plus", "path": "audios", "createTime": "2026-07-10 14:30:00" }]
关键设计:
- 文件锁并发控制 :使用
fcntl.flock保证多请求并发写入安全 - path 字段分类 :
audios(定制音色)/bgm(背景音乐)/podcasts(播客成品),便于前端分类展示 - 临时文件自动清理 :
storage/temp/目录下的文件定期清理,避免磁盘堆积
三、前端交互设计
3.1 深色主题的沉浸式体验
前端采用深蓝紫的色调主题,深空背景 + 蓝紫光晕 + 亮蓝高亮,配置提取style.css中:
css
/* ------ 光晕装饰色 ------ */
--brand-glow-blue: #3a5cff;
--brand-glow-purple: #7c3aed;
--brand-glow-deep-blue: #1e40ff;
/* ------ 品牌高亮蓝 ------ */
--brand-blue: #4f7cff;
--brand-blue-light: #4f9dff;
--brand-blue-strong: #2b6ef7;
--brand-blue-soft: #7ea3ff;
--brand-blue-pale: #9ec2ff;
/* ------ 卡片封面渐变 ------ */
--brand-cover-from: #1e3a8a;
--brand-cover-via: #2a1e5f;
--brand-cover-to: #0d0524;
3.2 流式对话体验
基于 ai-elements-vue 组件库,前端实现了丰富的 Agent 交互界面:
- 思维链展示:Agent 的推理步骤以可折叠卡片形式展示
- 工具调用可视化:每个工具调用显示名称、参数、结果
- 音频播放器:生成的音频直接在对话中嵌入播放
- 文件上传:支持拖拽上传音频/视频文件
3.3 四个核心页面
| 页面 | 功能 | 路由 | 效果描述 |
|---|---|---|---|
| ChatAgent | 流式对话 Agent,核心创作入口 | / |
深色主题对话界面,Agent 逐步展示思考过程、工具调用和生成结果,支持音频播放和文件拖拽上传 |
| PodcastList | 播客成品列表,展示和管理作品 | /podcasts |
卡片网格布局展示所有已生成的播客作品,每个卡片包含封面、标题、时长信息,悬停有微动效 |
| ResourceLibrary | 资源库管理,管理音色/BGM/素材 | /resources |
分类管理音色、BGM、播客素材,支持上传、预览、删除操作,左侧分类导航 + 右侧内容列表 |
| VisualConfig | 可视化配置 API Key 和模型参数 | /config |
表单式配置界面,分为"对话模型"和"语音播客"两个区块,支持密码可见性切换和自动持久化 |
四、工程实践与经验
4.1 工具设计的"单一职责"原则
我们将音频处理拆分为 9 个独立工具,每个工具只做一件事:
| 工具 | 职责 | 输入 | 输出 |
|---|---|---|---|
qwen_multimodal_tool |
多模态内容理解 | 媒体文件 | 文本描述 |
qwen_asr_tool |
语音识别 | 音频文件 | 文字转录 |
qwen_voice_design |
音色设计 | 文本描述 | 音色ID+音频 |
qwen_voice_cloning |
语音合成 | 音色ID+文本 | 音频文件 |
save_voice |
音色保存 | 音频路径 | 永久存储 |
concatenate_audio |
音频拼接 | 音频列表 | 拼接文件 |
select_background_music |
BGM 选择 | 场景描述 | BGM 路径 |
mix_audio_with_bgm |
专业混音 | 人声+BGM | 最终播客 |
这种设计让 Agent 可以灵活组合工具,而不是被预设的"大而全"工具束缚。
4.2 临时文件与永久存储的分离
- 临时目录 (
storage/temp/):工具生成的中间产物,10 分钟自动清理 - 永久目录 (
storage/audios/):用户确认保存的音色,持久化存储 - 成品目录 (
storage/podcasts/):混音后的最终播客
这个设计避免了磁盘空间浪费,同时保证了用户主动保存的内容不会丢失。
4.3 流式输出的"真"流式
我们使用 stream_mode="messages" 模式,确保 Agent 的输出是逐 token 流式的,而非"生成完再发送"的伪流式:
csharp
async for chunk in agent.astream(
{"messages": langchain_messages},
{"configurable": {"thread_id": self.thread_id}},
stream_mode="messages" # 关键:逐消息流式输出
):
async for event in self._handle_chunk(chunk):
yield event # 立即发送,不等待
4.4 配置可视化:降低技术门槛
传统 AI 项目需要用户手动编辑 .env 文件,对非技术用户极不友好。我们通过 VisualConfig.vue 页面,将配置项以表单形式呈现:
- API Key 输入框(支持密码可见性切换)
- 模型选择下拉框
- 配置自动持久化到
config.json - 前后端通过
/api/config接口同步
五.结果展示




六、总结
这个项目展示了 AI Agent 在垂直内容创作领域 的完整实践:
- 端到端自动化:从内容理解到播客输出,全流程 AI 驱动
- 多模态融合:文字、图片、音频、视频统一处理
- 专业级音频质量:音色设计 + 智能混音,输出广播级品质
- 低门槛使用:可视化配置 + 自然语言交互,无需技术背景
附录:快速开始
bash
# 1. 克隆项目
git clone <repo-url>
# 2. 启动后端
cd backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # 填写 API Key
python main.py
# 3. 启动前端
cd fronted
npm install
npm run dev
# 4. 访问 http://localhost:3000