AI vtuber 探索

邦邦特化AI聊天(2代live2d)

本分支为适应本地快速部署的轻量化版本,可从main分支或者其它分支查看中小型网页部署版或开发版

1
2
3
4
#本机部署
git clone https://github.com/Paraworks/BangDreamAi
pip install -r requirements.txt
python app.py

默认5000端口

配置live2d模型

BangDream的live2d可以直接从bestdori手动下载。Github上也有许多提取好的仓库

五团(卡面比较多)

七团

b站北极暖水港大佬

你需要将这些模型放在/static/Resources

按照如下标准

1
/Resources/{乐队}/{角色}/{模型名}/model.json

这样程序可以自动识别乐队和角色,否则无法在前端选择

模型配置

如果没什么大问题,可以直接在前端页面配置,但也可以本地直接修改config.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
默认配置
{
"api": "chatgpt",
"apiKey": "",
"apiLink": "",
"band": "Afterglow",
"duration": 2,
"frequence": 0.5,
"modelPath": "static/Resources/Afterglow/蘭/live/model.json",
"mouseTrack": 1,
"positionX": 300,
"positionY": 50,
"scale": 0.3,
"speaker": "蘭",
"stopBreath": 0,
"text": {
"response": "初始化成功",
"expression": null,
"motion": null
},
"textApiBaseUrl": "http://127.0.0.1:5000/api/sentence/test",
"ttsApiBaseUrl": "http://127.0.0.1:8000/?is_chat=false",
"volum": 70
}

启动TTS合成

TTS(Bang dream Bert vits示例):

1
2
3
4
5
6
git clone https://huggingface.co/spaces/Mahiruoshi/MyGO_VIts-bert
cd MyGO_VIts-bert
pip install -r requirements.txt
pip install Flask
pip install Flask-CORS
python server.py

自定义chatbot

由于在前端配置完apikey后,直接跑chatgpt也大概率跑不通,建议自行修改chat.py的相关配置以及逻辑

To do list

自定义直播间管人配置(未完成)

1
{url}/{session_id}/{task_id}

OBS 配置详解:

live2d 配置

  • 来源 > + > 浏览器 > 新建 > URL:填入上一步生成的live2d链接,一般是localhost:xxxx

弹幕姬

  • 来源 > + > 浏览器 > 新建 > URL:参照说明填入链接以及css

B 站推流配置

  • (obs内)设置(Preferences)> 直播 > 服务 > 自定义 > 填写 bilibili服务器以及推流码…
  • 推流码填写「B 站首页 > 头像 > 推荐服务 > 直播中心 > 左侧“我的直播间”> 填好直播分类、房间标题 > 开始直播,然后会显示的串流密钥」

开发历程

服务器部署中踩过的一些坑:
TTS模型非常吃内存,而中文的bert模型大小是日语的几倍,在我使用的4核4G内存的服务器上就只能进行日语TTS了。
就目前而言推荐用Mygo的bert模型,不论是大小还是效果都理想一些。

技术细节:用pixi-live2d-display驱动live2d

live2d我之前也没碰过,就跟着这个项目走了下来,然后发现这玩意整成皮套人可能还是最容易的。然后我还是遇到了那个问题。
pixi-live2d-display不支持口型同步,其实cubism本体也需要自己手搓相关代码。
于是我找到了这个issue
每个live2d模型都有对张嘴角度的设定,也就是lip

1
2
model.internalModel.coreModel.setParameterValueById('ParamMouthOpenY',v);

而bang dream使用的是二代模型,参数不通用

1
model.internalModel.coreModel.setParamFloat('PARAM_MOUTH_OPEN_Y', v);

之后要做的事说白了就是先调用函数分析wav文件的响度,将其转化成lip参数对应的区间(0~1)

1
2
3
4
5
6
7
8
9
10
11
const run = () => {
if (!playing) return;
const frequencyData = getByteFrequencyData(analyser, new Uint8Array(analyser.frequencyBinCount));
const arr = [];
for (let i = 0; i < 1000; i += o) {
arr.push(frequencyData[i]);
}
setMouthOpenY((arrayAdd(arr) / arr.length - 20) / 60);
setTimeout(run, 1000 / 30);
};
run();

因为所用到的是wav文件,需要对参数进行微调。
这样就可以让皮套人说话了,就是index.js
程序会向目标端口发送请求获取待合成文本

1
2
3
4
5
6
7
8
9

let text;
try {//从launcher.py启动的flask服务中获取待读文本
const response = await fetch('http://127.0.0.1:5180/show');
text = await response.text();
} catch (error) {
console.error('Failed to get text from the server', error);
return;
}

之后将其发送给TTS端

1
request.open('GET', `http://127.0.0.1:5000/tts?text=${encodeURIComponent(text)}&speaker=ましろ`, true);

实现

综上:
前端组件+chatot程序+live2d+TTS = 服务器或本地端”AI vtuber”
弹幕监听+chatbot(两者可以直接整合在一起)+TTS+vtuber = AI Vtuber