zicojiao/worldcupvoice
GitHub: zicojiao/worldcupvoice
为体育直播流提供 AI 实时语音解说,通过视觉模型分析 RTC 视频画面并自动生成多语言解说音频与字幕。
Stars: 7 | Forks: 0
# WorldCupVoice
**体育直播的 AI 实时解说员。**
为实时直播流添加 AI 实时解说:AI 会观看与观众相同的 RTC 视频,
并进行实时解说。世界杯是展示场景,
但相同的 pipeline 适用于任何直播流。
[](./LICENSE)





**English** · [简体中文](./README.zh-CN.md)
WorldCupVoice 是一款用于体育直播的实时 AI 解说员:直播画面进入实时媒体频道,AI 会观看与观众相同的流,并将生成的语音作为实时解说返回到直播间。
它是为世界杯等直播体育赛事打造的,其中一个特别适合的用例是可访问性(无障碍功能):AI 实时解说可以为盲人和低视力球迷提供现场级别的细节,这是人类实时解说经常会遗漏的,例如球在哪里、压力从哪一侧形成,以及谁正在前插跑位。我们的目标并不是取代人类解说员。
## 演示
观看 WorldCupVoice 如何将实时比赛流转化为 AI 解说:
https://github.com/user-attachments/assets/307ca759-29f7-40d8-b3be-e9d5e5104e48
## 架构
```
flowchart LR
Encoder["Live source
OBS / encoder"]
RTMP["RTMP push"]
Gateway["Agora Media Gateway"]
Channel["Agora RTC channel"]
Viewer["Browser viewer
Agora Web SDK"]
Agent["AI commentator backend
Agora Python Server SDK"]
Vision["Vision model"]
Voice["TTS voice"]
Encoder --> RTMP --> Gateway --> Channel
Channel --> Viewer
Channel --> Agent
Agent --> Vision --> Voice --> Channel
```
运行时角色:
- 直播流:RTC 频道内的 RTMP/Gateway 推流者。
- AI 解说员:负责采样视频帧、撰写解说并发布生成语音的后端参与者。
- 浏览器观众:播放直播流、AI 音频、字幕和解说席状态的网页客户端。
## 功能
- 基于观众正在观看的 RTC 流提供实时 AI 实况解说。
- 任何直播源(OBS、编码器等)均可通过 RTMP 和 Agora Media Gateway 导入。
- 服务端视频帧采样,为视觉化匹配的比赛提供解说。
- 可配置的解说员声音,支持 OpenAI TTS、ElevenLabs 或 Fish Audio。
- 将 AI 音频发布回 RTC,并带有同步的文本记录和解说席状态。
- 显式的 `Start AI` / `Stop AI`、观众心跳检测以及严格的会话 TTL,以控制 AI 开销。
## 快速开始
### 前端环境
安装前端依赖:
```
pnpm install
cp .env.example .env.local
```
填写 `.env.local`:
首先生成一个后端密钥:
```
openssl rand -hex 32
```
将生成好的值分别粘贴到前端和后端的环境配置文件中:
```
NEXT_PUBLIC_AGORA_APP_ID=
NEXT_AGORA_APP_CERTIFICATE=
AGENT_BACKEND_URL=http://localhost:8000
BACKEND_API_SECRET=
ACCESS_PASSWORD=
```
`NEXT_AGORA_APP_CERTIFICATE`(前端)和 `AGORA_APP_CERTIFICATE`(后端)是同一个 Agora 证书,只是根据各自的命名规范进行了命名。
可选配置覆盖:
```
NEXT_PUBLIC_LIVE_CHANNEL_NAME=worldcup-live
NEXT_PUBLIC_MATCH_FEED_UID=234567
NEXT_PUBLIC_AGENT_UID=123456
# 对 access cookie 进行签名。在本地为可选(默认为 ACCESS_PASSWORD);在生产环境中设置一个
# 专用值并将其添加到 Vercel。
ACCESS_SESSION_SECRET=
```
### 后端
准备后端环境:
```
cd server
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
cp .env.example .env.local
```
填写 `server/.env.local`:
```
AGORA_APP_ID=
AGORA_APP_CERTIFICATE=
BACKEND_API_SECRET=
OPENAI_API_KEY=
```
### TTS 语音
默认的 OpenAI TTS 路径足以运行该项目,但语音是 AI 解说员效果的重要组成部分。对于演示和类似生产环境的直播,建议使用 ElevenLabs,因为专门定制的体育解说员声音会使解说感觉更像真实的直播转播室。
Fish Audio 也可以用作 TTS 提供商,并且非常值得尝试用于中文解说声音:
```
TTS_PROVIDER=fish_audio
FISH_AUDIO_API_KEY=
FISH_AUDIO_VOICE_ID_ZH_MEME=
FISH_AUDIO_VOICE_ID_ZH_TACTICAL=
```
开源项目随附的是解说员配置文件和提示词,而不是私有 voice ID。请创建您自己的 Fish Audio 声音,并将其 ID 放入对应的环境变量中。如果既没有配置特定的配置文件,也没有配置通用的第三方 voice ID,后端将回退使用 OpenAI TTS,以确保本地设置依然可用。
内置配置文件语音变量:
| 配置文件 | 提供商 | 语音环境变量 |
| --- | --- | --- |
| 英语体育解说员 | ElevenLabs | `ELEVENLABS_VOICE_ID_EN_SPORTSCASTER` |
| 法语体育解说员 | ElevenLabs | `ELEVENLABS_VOICE_ID_FR_SPORTSCASTER` |
| 中文趣味解说 | Fish Audio | `FISH_AUDIO_VOICE_ID_ZH_MEME` |
| 中文战术解说 | Fish Audio | `FISH_AUDIO_VOICE_ID_ZH_TACTICAL` |
创建您自己的 ElevenLabs 声音,并将其 voice ID 放入 `server/.env.local`:
```
TTS_PROVIDER=elevenlabs
ELEVENLABS_API_KEY=
ELEVENLABS_VOICE_ID=
ELEVENLABS_VOICE_ID_EN_SPORTSCASTER=
ELEVENLABS_VOICE_ID_FR_SPORTSCASTER=
```
在 ElevenLabs 中:
1. 打开 **VoiceLab**。
2. 点击 **Create Voice**。
3. 选择 **Voice Design**。
4. 粘贴下方的提示词并生成一个体育解说员声音。
5. 保存声音,然后将其 **Voice ID** 复制到 `ELEVENLABS_VOICE_ID` 中。
演示中用于生成声音的 ElevenLabs 语音提示词:
```
Native English, neutral American broadcast style. Male, 35-50. Broadcast quality.
Persona: elite sports commentator. Emotion: explosive, urgent, passionate.
A powerful, resonant, high-energy voice built for live football and basketball commentary. Deep but agile timbre, crisp articulation, close-mic broadcast presence, and clean studio-quality audio. Speaks at a fast, rhythmic pace during live action, with sudden bursts of excitement, sharp emphasis on player names, and dramatic pauses after huge moments. The delivery should feel like a professional television play-by-play announcer calling a World Cup final: intense, emotionally invested, breathless during attacks, and thunderous when a goal or game-changing moment happens.
```
填写完环境配置文件后,启动后端:
```
python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
```
### 运行应用
启动前端:
```
pnpm dev
```
打开 [http://localhost:3000](http://localhost:3000),进入解说席,然后从 OBS 推流,或推送您提供的本地视频片段。
### Media Gateway 推流密钥
Agora Media Gateway 需要两个 RTMP 值:服务器域名和推流密钥。控制台页面可以启用 Media Gateway,但不显示现成的推流密钥。当您使用 Agora 统一的 RTMP 域名时,请通过 Media Gateway REST API 创建推流密钥。
对于本项目,为默认的直播流生成密钥:
```
Channel: worldcup-live
UID: 234567
```
如果您更改了 `NEXT_PUBLIC_LIVE_CHANNEL_NAME` 或 `NEXT_PUBLIC_MATCH_FEED_UID`,请使用更改后的值。
在 [Agora 控制台](https://console.agora.io/) 中:
1. 从控制台侧边栏打开 **Projects** 并选择您的项目。
2. 从项目的功能列表中启用 **Media Gateway**。
3. 在控制台中打开 **Developer Toolkit -> RESTful API**,并创建或复制 Customer ID 和 Customer Secret。Agora 在 [RESTful 身份验证](https://docs.agora.io/en/signaling/rest-api/restful-authentication) 中记录了此流程。
4. 仅将它们添加到本地 `.env.local` 中:
```
AGORA_CUSTOMER_ID=
AGORA_CUSTOMER_SECRET=
AGORA_MEDIA_GATEWAY_REGION=
```
选择最接近您的编码器或云 RTMP 源的 Media Gateway 区域,例如 `eu`、`na`、`as`、`cn`、`jp` 或 `in`。
创建推流密钥:
```
pnpm run media-gateway:key
```
将生成的 RTMP 详细信息复制到您接下来要使用的任何源中:
```
RTMP server: rtmp://rtls-ingress-prod-.agoramdn.com/live
Stream key:
```
请对 Customer Secret 和推流密钥保密。切勿将它们提交到 GitHub 或放入 Vercel 中。
Agora 官方文档解释说,统一的 RTMP 服务器使用 `rtls-ingress-prod-.agoramdn.com/live` 域名,并且推流密钥是通过 Media Gateway REST API 创建的。请参阅 [Media Gateway 快速入门](https://docs.agora.io/en/media-gateway/get-started/quickstart) 和 [创建推流密钥](https://docs.agora.io/en/media-gateway/reference/rest-api/endpoints/streaming-key/create-streaming-key)。
### 选择 RTMP 源
有了 RTMP 服务器和推流密钥后,选择一个 RTMP 源:
| 源 | 最适用于 | 运行位置 | 备注 |
| --- | --- | --- | --- |
| `pnpm run stream:sample` | 快速的本地冒烟测试 | 您的笔记本电脑 | 使用 ffmpeg 循环播放您提供的本地视频片段。使用 `Ctrl+C` 停止。 |
| OBS | 手动演示和真实的摄像头/屏幕推流 | 您的笔记本电脑或编码器机器 | 适合交互式控制、叠加层、音频路由和屏幕捕获。 |
| StreamFlow 或其他云 RTMP 编码器 | 较长的预录或定时直播流 | VPS 或云主机 | 对于 24/7 全天候预录直播流,比笔记本电脑更稳定,但依然只是一个 RTMP 生产者。 |
所有三个选项都推流到相同的 Agora Media Gateway RTMP 服务器和推流密钥。应用和 AI 解说员始终将结果作为直播 Agora RTC 视频进行消费。
### 推送本地视频片段
本仓库不附带任何视频——转播的比赛录像受版权保护,不能重新分发,因此请**自带足球视频片段**(任何 16:9 的 `.mp4`)。该视频片段仅作为本地转播源;应用不会直接播放它。
为了获得更好的解说效果,请先描述您的比赛,以便 AI 能够识别球员。每场比赛都是 `data/matches/` 下的一个 JSON 文件(包含球队、球衣颜色、球员名单、故事情节)——复制 `_template.json`,进行编辑,然后在 [`lib/commentary.ts`](./lib/commentary.ts) 中注册它。完整指南请参阅 [`data/matches/README.md`](./data/matches/README.md)。
安装 ffmpeg,然后通过 Agora Media Gateway 推送您的视频片段:
```
brew install ffmpeg
RTMP_STREAM_KEY= \
RTMP_INPUT=/path/to/your-match.mp4 \
pnpm run stream:sample
```
如果未设置 `RTMP_INPUT`,脚本将推流它在 `samples/` 中找到的第一个 `.mp4` 文件。它会循环播放该片段,直到您按下 `Ctrl+C`;浏览器和 AI 解说员会将其作为直播 Agora RTC 视频接收。
### 使用 StreamFlow 的云 RTMP
[StreamFlow](https://github.com/bangtutorial/streamflow) 是一款可选的自托管 Web 应用,用于管理预录制的直播流。它提供视频上传/管理、定时直播、循环模式、比特率/FPS/分辨率设置以及自定义 RTMP 输出。
当您希望从 VPS 而不是笔记本电脑上进行类似生产环境的预录制转播时,请使用 StreamFlow:
1. 在 VPS 或 Docker 主机上部署 StreamFlow。
2. 上传您自己的足球视频片段。
3. 使用 `pnpm run media-gateway:key` 打印出的 RTMP 服务器和推流密钥。
4. 根据需要启用循环播放或定时设置。
5. 从 StreamFlow 开始直播。
这不会替代 Agora Media Gateway。StreamFlow 仅作为上游 RTMP 生产者;Agora Media Gateway 依然会将该 RTMP 输入转换为浏览器和 AI 解说员观看的 RTC 流。
### OBS 设置
使用自定义直播服务:
```
Service: Custom
Server: rtmp://rtls-ingress-prod-.agoramdn.com/live
Stream Key:
```
推荐的初始设置:
- 编码器: H.264
- FPS: 30
- 关键帧间隔: 2秒
- 码率控制: CBR
- 比特率: 1080p 为 4500-6500 Kbps
- 音频: AAC, 48 kHz
### 部署
前端:
```
vercel link
vercel env add NEXT_PUBLIC_AGORA_APP_ID production
vercel env add NEXT_AGORA_APP_CERTIFICATE production
vercel env add AGENT_BACKEND_URL production
vercel env add BACKEND_API_SECRET production
vercel env add ACCESS_PASSWORD production
vercel env add ACCESS_SESSION_SECRET production
vercel deploy --prod
```
后端:
- 将 `server/` 部署为 Railway Docker 服务。
- 设置 [`server/.env.example`](./server/.env.example) 中的变量。
- 在 Railway 和 Vercel 中使用相同的 `BACKEND_API_SECRET` 值。
- 将前端的 `AGENT_BACKEND_URL` 设置为 Railway 的公开 URL。
## 运行时成本控制
后端不会仅仅因为部署了就消耗 AI token。
- `/sessions/start` 启动 AI 解说员。
- `/sessions/heartbeat` 在有观众在场时保持其运行。
- `/sessions/stop` 显式停止它。
- `BACKEND_API_SECRET` 保护公开的 Python 后端免受直接的会话控制调用。
- 当观众心跳消失时,过期的会话会自动停止。
- 每个会话都有严格的运行时上限。
超时、模型、语音、视频帧采样和音频节奏的默认值位于 [`server/app/config.py`](./server/app/config.py) 中。只有在您刻意调整运行时时,才覆盖它们。
解说席监视器会显示 AI 是处于空闲、等待视频、活跃、已停止还是丢失状态。
## 项目布局
```
app/api/ Next.js API routes for tokens, access, and session proxying
components/ Live booth UI, transcript, metrics, and lobby
data/matches/ Per-match context (one JSON per game) sent to the AI
lib/commentary.ts Loads the match JSON and builds the AI prompt context
server/app/ FastAPI backend and AI commentator
server/tests/ Backend smoke tests
public/ Logos, icons, and poster imagery
```
## 路线图
- [ ] 降低视频帧与 AI 解说输出之间的延迟。
- [ ] 多解说员:多个 AI 解说员协同工作。
- [ ] 为盲人和低视力球迷提供专门的无障碍模式,提供更密集的球场/空间细节。
- [ ] 更多语音和语言:不同国家的语言和声音风格。
## 许可证
MIT标签:Agora RTC, AI解说, Petitpotam, 体育直播, 实时音视频, 无障碍辅助, 视觉模型, 语音合成, 逆向工具