# cyber-xiaoya-live
**Repository Path**: wangdada40/cyber-xiaoya-live
## Basic Information
- **Project Name**: cyber-xiaoya-live
- **Description**: 互动数字人
- **Primary Language**: Unknown
- **License**: AGPL-3.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-11-05
- **Last Updated**: 2026-11-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 赛博小雅直播版 · 组件版数字人(Vidu s2)
> **本项目永久免费开源。** 唯一官方来源:https://github.com/cyber-xiaoya/cyber-xiaoya-live
> 任何付费售卖、代下载、代部署均未经授权,欢迎举报(举报:提 [Issue](https://github.com/cyber-xiaoya/cyber-xiaoya-live/issues) 或在本项目官方群里 @我)。
> 👤 **作者:天工开帧** · [抖音](https://v.douyin.com/BgCJXnllitM/) · [哔哩哔哩](https://space.bilibili.com/11946287) · [YouTube](https://www.youtube.com/@jintaoyi) · [博客](https://www.19980303.xyz/)
> 📦 **配套仓库**:[赛博小雅 · 弹幕采集器](https://github.com/cyber-xiaoya/cyber-xiaoya-danmaku) —— 抖音 / B站 / YouTube / 视频号,
> 装好并把 `tts.output` 设成 `dh` 就能把观众弹幕灌进本仓库的桥。
> ⚠️ **先说清楚:这不是"下载双击就能播"的成品。**
> 仓库里给的是**整套软件**(舞台页 + 本地桥 + 弹幕/歌单/录播全链路),
> 但**不包含**作者的人物形象、克隆音色、人设、动作库、歌库和任何 API Key —— 那些需要你自己准备。
> 这份 README 会把"从零跑起来"需要做的每一步写清楚,照着做大约 **1 小时**。
---
## 效果
这是**手机端抖音直播的实拍截图**:观众弹幕进来 → 舞台页把指令翻译成动作 → 数字人执行(画面里是"拿出墨镜戴上"),
底部是她正在说的话(由 LLM 生成 + 本机 TTS 合成)。
> 6 秒实拍。能看到:弹幕 → 动作指令 → 数字人真的执行了。
> 🎬 [**带声音的原片**(720×1560,v1.0.0 附件)](https://github.com/cyber-xiaoya/cyber-xiaoya-live/releases/download/v1.0.0/demo-sound.mp4) · 无声版 [demo.mp4](assets/demo.mp4)
这是**主播这端看到的「舞台页」**:左边是数字人画面 + 实时字幕,右边是快捷指令 / 点播 / 参考图面板,
底部一行是打字、直发动作、点播、中断、设置。(界面示例,字幕为演示数据)
---
## 0. 你需要准备什么
| 项目 | 是否必须 | 说明 |
|---|---|---|
| Windows 10/11 + NVIDIA 显卡(≥8GB 显存) | 必须 | 渲染在云端,但 TTS 在本机跑 |
| Vidu 账号 + API Key | 必须 | 数字人渲染与推流,按秒计费(1 积分/秒) |
| LLM API Key(DeepSeek 或任意 OpenAI 兼容) | 必须 | 她的"脑子" |
| TTS 服务(OmniVoice / 见 §2.4) | 必须,否则没声音 | 本机跑,WSL2 + CUDA |
| ffmpeg | 必须 | 音频解码统一走它 |
| 弹幕采集器(抖音/B站/YouTube) | 可选 | 不装就只能手动打字互动 |
| 点播歌库 | 可选 | 不放歌就没有点播 |
| 摄像头/推流软件(OBS 等) | 可选 | 想把画面推给平台才需要 |
---
## 1. 它到底是怎么跑起来的
```
浏览器「舞台页」 ──文字──▶ 本地桥(FastAPI :8795) ──type9──▶ Vidu 云端
▲ │
│ LLM 流式 → 分句 → TTS(本机) → PCM 流
│ │
└── WebRTC 订阅画面 ◀── Vidu 渲染口型+动作 ──▶ RTC 频道
```
- **Vidu 只负责"变成画面"**:给文字/音频,它渲染口型、表情、动作并推流
- **其余全在本机**:LLM 思考、TTS 发声、弹幕处理、点播、录播下载
- 舞台页是本地网页(`http://127.0.0.1:8795/stage`),你在浏览器里操作,不需要公网
**为什么这么设计**:不用买云端 ASR/LLM/TTS 套餐,成本只剩 Vidu 的渲染费;音色、人设、歌单全在你自己手里。
---
## 2. 准备工作(照着做)
### 2.1 Vidu 账号、形象、动作库
1. 注册 ,充值(按 1 积分/秒计费,余额 <45 积分开不了场)
2. 在控制台创建一个**形象**(上传一张正脸照或一段视频),记下它的 **avatar_id**
3. (可选)建一个**动作库**,往里加动作,记下 **library_id**;不建就填 `0` 用平台默认库
4. 在「API Key」页面生成 key,形如 `vda_xxx`
### 2.2 LLM API Key
默认用 DeepSeek(`https://api.deepseek.com`,模型 `deepseek-flash`)。
把 key 存成一个文本文件,路径填进 `config.json → llm.key_file`;也可以直接用环境变量 `DEEPSEEK_API_KEY`。
### 2.3 本机环境
```powershell
# 1) Python 3.12 + uv
winget install --id Python.Python.3.12
pip install uv
# 2) 装依赖
uv venv .venv --python 3.12
uv pip install -r requirements.txt --default-index https://pypi.tuna.tsinghua.edu.cn/simple
# 3) ffmpeg(作者放在 C:\ffmpeg7.1.1\bin,你也可以直接放进 PATH)
ffmpeg -version
```
### 2.4 TTS —— 这一步最容易卡住
项目**只认 OmniVoice**(`tts.engine = "omnivoice"`),因为要支持"克隆音色 + 直播中热切音色"。
#### 方案 A:OmniVoice + WSL2(推荐,作者本机就是这样跑的)
要求:WSL2 + Ubuntu-22.04 + NVIDIA 驱动 + 至少 8GB 可用显存(作者实测稳定占用 ~11GB)。
> 💡 **⚠️ 先说明一个最容易卡住的地方**:`demo_flashinfer.py` **不是 OmniVoice 上游自带的文件**,
> 它是本项目提供的一层封装(把模型起成 `:9877` 服务 + 套 FlashInfer/CUDA Graph 加速 + 自动清理合成缓存)。
> 所以 clone 完上游在 `~/omnivoice-wsl/` 里**看不到它是正常的**,需要从本仓库 `tools/omnivoice/` 拷过去。
> 完整图文步骤 + 报错对照表:**[tools/omnivoice/README.md](tools/omnivoice/README.md)**
```bash
# ── 第 1 步:拉上游 + 建环境(以下全部在 WSL2 的 Ubuntu-22.04 里执行)──
sudo apt update && sudo apt install -y ffmpeg git
git clone https://github.com/k2-fsa/OmniVoice ~/omnivoice-wsl
cd ~/omnivoice-wsl
# 建环境(Python 3.12;Blackwell / RTX 50 系必须 cu13 系列,cu129 会报 requires GPUs with sm75)
uv venv .venv --python 3.12 && source .venv/bin/activate
uv pip install torch --index-url https://download.pytorch.org/whl/cu130
uv pip install flashinfer-python flashinfer-jit-cache
uv pip install -r requirements.txt
# ── 第 2 步:把本仓库的服务脚本拷进来(关键!缺的就是这两个文件)──
# 把 <盘>/<仓库路径> 换成你实际 clone 的位置
cp /mnt/d/<仓库路径>/tools/omnivoice/{demo_flashinfer.py,start_server.sh} ~/omnivoice-wsl/
chmod +x ~/omnivoice-wsl/start_server.sh
# ── 第 3 步:启动(脚本会先做 4 项预检:目录 / 启动文件 / venv / 是否已在跑)──
bash ~/omnivoice-wsl/start_server.sh
# 有本地模型就指定,跳过自动下载:
# bash ~/omnivoice-wsl/start_server.sh /mnt/e/llama-models/models/OmniVoice-bf16
```
> 没指定模型时脚本按这个顺序找:**命令行参数 → 环境变量 `OMNIVOICE_MODEL` → 常见本地路径 → 从 HuggingFace 下载 `k2-fsa/OmniVoice`**。
> 首次下载约 **10GB**(10~60 分钟,只下一次);网络慢可先 `export HF_ENDPOINT=https://hf-mirror.com`。
启动后从 Windows 验证:
```powershell
curl.exe -s -o NUL -w "%{http_code}" http://127.0.0.1:9877/ # 期望 200
```
- **WSL2 镜像网络模式**下用 `127.0.0.1:9877`
- 默认 NAT 模式下用 `wsl hostname -I` 拿到的 IP,填进 `config.json → tts.omnivoice_base`
- WSL2 IP 每次重启可能变,改了要同步改配置(或者用一键脚本自动检测)
**音色从哪来**:`tts.voices_dir` 指向一个目录,里面每个子文件夹是一种音色:
| 文件夹内容 | 音色类型 | 例子 |
|---|---|---|
| `design.json` | 用属性"设计"音色(性别/年龄/音调/方言,不需要参考音频) | 御姐音 |
| `ref_audio.wav` + `ref_text.txt` + `omnivoice.txt` | 克隆音色 | 用你自己的录音克隆 |
| `ref_audio.wav` + `ref_text.txt` | 同上,少一个描述文件 | |
参考音频要求:**3–10 秒、单句、16kHz 单声道、无背景音**,`ref_text` 必须和音频逐字一致。
#### 方案 B:先不装 TTS(无声彩排)
桥没有 TTS 也能起来:舞台页能开、能连线、画面会动、字幕会滚,只是**她不会说话**。
适合先把 Vidu 链路和舞台页跑通,再回头折腾 TTS。
---
### 2.5(可选)接弹幕 —— 以抖音为例(群友最常用)
**最省事的做法**:直接用配套仓库 [赛博小雅 · 弹幕采集器](https://github.com/cyber-xiaoya/cyber-xiaoya-danmaku),
它把抖音/B站/YouTube/视频号 四家都封装好了,`tts.output` 设成 `dh`(默认就是)即可:
```powershell
git clone https://github.com/cyber-xiaoya/cyber-xiaoya-danmaku.git
cd cyber-xiaoya-danmaku
copy config.example.json config.json # 填房间号
.venv\Scripts\python.exe reader.py # 抖音还需另装 douyinLive(见下文)
```
只想做抖音、不想再挂一个仓库?也可以按下面三步,用公开的上游项目 + 本仓库自带的转发器:
---
抖音的弹幕**不能直接从网页读**(要签名),社区通行做法是先跑一个**本地采集服务**,
再用本仓库自带的转发器把消息灌进桥。
#### 抖音三步
1. **拿采集服务**:开源项目 (Go 写的,自带 ws + http)。
自行编译或下载 release,改它目录下的 `config.yaml`(端口默认 `1089`、填抖音 cookie),启动。
2. **确认在跑**:
```powershell
curl.exe "http://127.0.0.1:1089/api/v1/rooms/<房间号>/status"
```
3. **起转发器**(本仓库自带,`tools/douyin_relay.py`,零额外依赖):
```powershell
.venv\Scripts\python.exe tools\douyin_relay.py --room <房间号> --verbose
```
它会连 `ws://127.0.0.1:1089/ws/<房间号>`,把**弹幕**和**礼物**翻译成
`POST http://127.0.0.1:8795/api/danmaku`。
通了之后,舞台页右侧「字幕 / 事件」里会出现 `【弹幕】` 条目。
> 转发器只做"翻译 + 转发",不依赖采集器的内部实现 —— 换成别的采集器,只要它发同样的
> JSON(`method` / `user.nickname` / `content` / `gift`)也能用。
> ⚠️ 第三方采集工具与平台的合规风险由使用者自负;本项目只提供 `/api/danmaku` 这一个接口。
#### 其它平台 / 自己写采集器
只要按这个格式发请求,桥就认:
```http
POST http://127.0.0.1:8795/api/danmaku
Content-Type: application/json
{"nick":"观众名","content":"弹幕内容","platform":"bilibili","text":"念出来的文本"}
```
送礼事件额外带 `kind:"gift"`、`gift_item`、`gift_num`、`gift_value`(折算钻)。
### 2.6(可选)点播歌单
把 mp3/flac/wav 丢进 `audio/` 目录,舞台页「🎵 点播歌单」就能看到。
想要逐行歌词字幕,需要 `lyrics-cache/<歌名>.lrc.json`(用 `tools/lyrics_align.py` 生成,需要 ASR 环境)。
歌**不要提交进仓库**(`.gitignore` 已排除,版权也不允许)。
---
## 3. 配置 `config.json`
```powershell
copy config.example.json config.json
```
| 字段 | 填什么 |
|---|---|
| `vidu.api_key` | 你的 `vda_...` |
| `avatar.avatar_id` | 你上传的形象 ID(有 `image_uri` 就用那个) |
| `action.library_id` | 动作库 ID;不建就填 `"0"` |
| `rtc.mode` | `managed`(平台托管,推荐)或 `customer`(自备 RTC,要填 `rtc.artc.*`) |
| `llm.key_file` | 存 key 的文本文件路径 |
| `llm.system_prompt` | **你自己的人设**(模板里是示例,务必改) |
| `tts.omnivoice_base` | OmniVoice 地址,默认 `http://127.0.0.1:9877` |
| `tts.voices_dir` | 音色目录 |
| `tts.files_dir` | 点播目录,默认 `audio` |
| `bridge.port` | 默认 8795 |
`config.json` 里有密钥,**已被 `.gitignore` 排除**,不要提交。
---
## 4. 启动
```powershell
# 只起桥 + 舞台页(最简单)
.venv\Scripts\python.exe -m src.main
# 或者一键脚本:桥 + TTS + 弹幕 + 打开舞台页(缺的组件自动跳过)
双击 启动-组件版全链路.cmd
```
打开 ,点「开始连线」,等 5–15 秒画面出来。
> ⚠️ 连线即开始计费(1 积分/秒)。测完记得点「断开」。
---
## 5. 舞台页能干什么
| 区域 | 功能 |
|---|---|
| 中间 | 数字人画面 + 字幕 + 动作指令特效(只显示弹幕抓出来的指令) |
| 底部输入框 | 打字跟她聊(走 LLM → TTS → 说话) |
| 🎬 直发 | 直接把动作指令发给 Vidu,不经过 LLM(她默默执行) |
| 🕹 快捷指令 | 点一下即发送;编辑模式可拖拽排序、改名、新建 |
| 🎵 点播歌单 | 放歌(带歌词字幕) |
| 🖼 参考图 | 换装 / 拿起商品 / 换背景 |
| ⏺ 自动录播 | 让 Vidu 服务端录下这一场,播完自动下载到本地 |
| ⚙ 设置 | 音色、开场白、字幕位置、黑名单词表等 |
> 📌 **快捷指令组只带了示例**:🍉吃喝 14 条 / 💇外表 11 条 / 🎭拟人化 10 条 / 🎁拿出 8 条。
> 拟人化那 10 条是随机留的样例,真正的动作库请你在舞台页「🕹 快捷指令 → ✏️ 编辑」里自己加
> (支持拖拽排序、双击改名、跨组移动、⇩导出/⇧导入)。
---
## 6. 常见问题
**Q:连不上 Vidu / 401?**
检查 `vidu.api_key` 是否正确、余额是否 <45 积分(会直接开不了场)。
**Q:她没有声音?**
99% 是 TTS 没起来。先 `curl http://127.0.0.1:9877/` 看是不是 200;WSL2 重启后需要重新拉起服务。
**Q:WSL2 重启后连不上 9877?**
IP 变了。`wsl hostname -I` 查新 IP,改 `tts.omnivoice_base`,或者用镜像网络模式走 `127.0.0.1`。
**Q:画面卡 / 说话延迟大?**
先看 GPU 占用;TTS 和渲染抢显存时,把 OmniVoice 的 `--graph-buckets` 减少一些。
**Q:录播下载不到文件?**
Vidu 侧封盘可能要几分钟到几十分钟;页面「↻ 拉取录播」可以手动重试。
**Q:能换别的 TTS 吗?**
代码里 `tts.engine` 目前只实现 `omnivoice`;要接 Edge-TTS / GPT-SoVITS 需要自己写一个适配层(`src/tts/` 下加一个类即可)。
---
## 7. 仓库里**没有**什么
为了避免"下载后发现跑不起来",这里明确列出作者**故意没放**的东西:
- ❌ 人物形象(图片/视频/形象模型)—— 需要你自己上传到 Vidu
- ❌ 克隆音色(参考音频、音色模型)
- ❌ 人设提示词正文、文案、歌单、动作库内容
- ❌ 任何 API Key、Cookie、账号凭据
- ❌ OmniVoice 模型权重(几 GB)、Python 依赖环境(2 GB+)、歌库音频
- ❌ 弹幕采集器(另一个项目,见 §2.5)
**这不是藏私**:形象、音色、人设是每个主播自己的东西,也是防止有人拿本项目做二次售卖的边界。
代码是完整的,缺的都是"你自己的内容"。
---
## 8. 许可证
- **代码**:[GNU AGPL-3.0](./LICENSE)
- **素材与品牌**:见 [NOTICE](./NOTICE),不在 AGPL 授权范围内
- 第三方依赖见 `requirements.txt`
## 9. 关于倒卖
本项目**代码免费、永久免费**,我们不会在任何平台出售它。
> ⚠️ **本项目没有官方 QQ 群、微信群,也不卖课、不卖安装服务。**
> 任何以「官方答疑群」「内部版」「授权版」「代部署」名义收费的,都不是我,请直接拉黑。
如果你看到有人在卖,那不是官方行为,欢迎把链接发到 [Issue](https://github.com/cyber-xiaoya/cyber-xiaoya-live/issues)。
也提醒买家:盗版没有更新、没有答疑、出了问题也没人负责。
---
## 10. 关注作者
赛博小雅是我(**天工开帧**)在业余时间做的开源项目。想看她直播、催更、或者聊聊实现细节,来这些地方找我:
| 平台 | 链接 |
|---|---|
| 🎵 抖音 | |
| 📺 哔哩哔哩 | |
| ▶️ YouTube | |
| ✖️ X / Twitter | |
| 📝 博客 · 教程 | |
| 💻 GitHub | |
> 项目相关的问题**优先提到本仓库的 [Issue](https://github.com/cyber-xiaoya/cyber-xiaoya-live/issues)** —— 公开可查,也方便后来人搜到答案;私信容易被淹没。
> 想直接看效果:抖音直播间搜「天工开帧」,晚上常有直播。
---
## 更新日志
### 2026-11-02
**新增**
- 🎬 **固定编排**:多组动作随机轮播(组内 2 秒 / 组间 15 秒可调),组内顺序可选「随机 / 按顺序」,
入口在「🕹 快捷指令」面板里的 **动作 / 编排** 两个页签
- 🎯 **编排动作挑选器**:从快捷指令现成的分组里点选动作加入编排,不用手打命令
- ⭐ **99 钻贵宾**:单个礼物单价 > 99 钻 → 她按模板"拿出礼物贴脸展示",该观众本场获得最高动作优先权
- ⭐ **专属会员欢迎**:名单里的观众进场 → 主动喊一句含名字的欢迎词(歌中排队、不打断歌曲)
- 📊 **本场统计面板**:Token 用量 / Vidu 积分消耗 / 礼物钻石 / 记忆剩余轮数,
显示在画面上、**可以用鼠标拖到任意位置**(双击复位),顶栏「📊 统计」开关控制显示
- 🚫 **说话侧敏感词过滤** + 动作黑名单豁免操作者通道(手点/直发/编排不会被误拦)
**改进**
- 动作优先级内核:贵宾动作 > 手动点击 > 固定编排 > 弹幕触发(弹幕不再被编排挤掉,改为排队)
- 数字随变化做补间动画,大数字加千分位
- 修复编排面板 DOM 未闭合导致脚本被吞的老问题
**部署相关**
- `start-component-stack.ps1` 与启动脚本兼容新版 WSL2 IP 变动(127.0.0.1 优先,失败回退内网 IP)