写个AI虚拟主播:看懂弹幕,妙语连珠,悲欢形于色,以一种简单的实现

这不是你期望的介绍深度学习大模型的文章。而是使用人人都能理解、编程、运行的简单技术(包括机器学习和非机器学习技术),通过一系列工程进行整合、组装,从而实现一个 AI 虚拟主播的故事。

muvtuber

让 AI 成为虚拟主播:看懂弹幕,妙语连珠,悲欢形于色,以一种简单的实现

元宇宙终于不再铺天盖地,ChatGPT 又来遮天蔽日。看不下去了,那当然是选择——加入这虚浮的演出,诶嘿~(误)

想法

蹭热度的想法是这样:元宇宙 => 皮套人,ChatGPT => 中之人,放到一起:AI 主播!

咳,实际上没那么假大空啦。真实的故事是这样:

既然我可以让 AI 看懂你的心情,并推荐应景的音乐,以一种简单的实现,那么,我还想再进一步!让 AI 站到唱机背后,聆听你的故事,为你播出此时此刻萦绕心中、却难以言表的那段旋律。曲终意犹未尽当时 ,一段 AI 细语入耳更入心 —— 机器不是冰冷的玩具,她比你更懂你,至少她更懂那个真实的你:她不会说谎,而你每天都在骗自己。

这个想法指向的产品是一个 AI 电台,我把它叫做 muradio。在细化设计的过程中,我不得不考虑电台的传播问题。我当然可以在本地完成一切,让 AI 电台只为你一人播,这样实现起来还简单;但是,电台果然还是要大家一起分享吧。所以,我考虑用一种现代的方式——视频直播。

那么,在实现 muradio 之前,先让 AI 学会直播吧!

设计

我把这个 AI 主播叫做 muvtuber 1

人是如何做的

要设计一个直播的机器,其实很简单。首先考察人是如何完成直播的:

  • 首先需要一个人作为主播:这个人是会动会说话的,心情是会写在脸上的;(只是以普遍理性而论,非必要条件,更非歧视残障人士。)
  • 在开始前有一个预订的主题,也可能没有;
  • 主线:推进主题:打游戏、一起看、点歌 …;
  • 支线:主线被弹幕打断,转而与观众互动:聊天;
  • 最后,需要一个直播推流工具,比如 OBS。

互动是直播的灵魂。直播没有主题仍是直播,而没有了互动就成了电视。简单起见,我们先忽略主题问题,只考虑注入灵魂的互动实现。互动的过程如下:

  • 观察:看到弹幕
  • 过滤:选择性忽略一些没有意义或太有意义的话
  • 思考:对过滤后留下来的话进行思考 => 回应的话
  • 过滤:想到的部分话可能是不适合说出的,也要过滤掉
  • 发声:把回应说出来
  • 动作与表情:伴随观察、思考、表达这个流程的动作控制、表情管理。

用机器模拟人

清楚了直播的处理过程,就容易用机器模拟:

  • 主播:我们可以用 Live2D 模型来作为主播本人。
  • 看弹幕:使用弹幕姬类程序,暴露接口即可:func danmaku(room) chan text
  • 思考:机器文本生成:func chat(question) answer
  • 发声:机器语音合成:func tts(text) audio
  • 过滤:func filter(text) bool
  • 动作表情:Live2D 模型可以具有动作、表情,可以通过某种方式驱动。

Live2D 和弹幕姬是现成的解决方案,而从看弹幕、到思考、到发声的整个流程也是非常模块化、函数式的,直观清晰。难点是如何让 Live2D 模型动起来?

模型何时该摆什么样的表情,何时该做什么样的动作?真人主播解决这个问题靠得是本能,虚拟主播解决这个问题靠得是动捕——归根到底还是人。看来现实不能直接借鉴,那么只好做个抽象了。

我认为,表情是心情的反映,动作是表达的延伸。淦我写不清关于心情 => 表达 => 动作,所以 动作 = f(心情) 的观点😭


(怎么会有人问 ChatGPT “我要如何解释我的观点?”😭)

所以说,我们可以用“心情”来驱动 Live2D,赋予 AI 主播表情与动作。

那么,我们又如何让机器拥有“心情”呢?事实上,在前文提到的 让 AI 看懂你的心情,并推荐应景的音乐,以一种简单的实现 一文的“中文文本情感分析”小节中,我们用一种及其简单的方式,实现了一种 文本 -> 心情 的模型。这里我们就沿用当时的成果,不作额外介绍了,新读者可以先去阅读那篇文章的对应部分。

总之,我们可以用“思考”的输出,即主播要说的话,通过文本情感分析技术,反推出主播的心情,然后根据心情,就可以控制 Live2D 模型做出合适的表情、动作。

整体设计

小结一下上述设计,我们用机器来模拟人类主播,完成与观众的闲聊交互,整个过程如下图所示:

我们把 muvtuber 分成了一个个独立的模块。每个模块使用独立的技术栈,实现自己的工作,并通过某种方式暴露 API,供他人调用。最后,我们会通过一个“驱动程序”muvtuberdriver 来调用各个模块,通过一个顺序流程,实现上图所示的数据流动。

组件实现

本节介绍对上述 muvtuber 设计方案的实现。我会先写各个独立组件,再写如何把他们组装到一起完成工作。喜欢“自顶向下”的读者请自行安排阅读顺序。

这是一个拥有众多组件的项目,装起 numpy 从头撸似乎不够明智。我们会心怀感激地借助一些开源项目。我希望提供一种最简单的实现——面向麻(my)瓜(self)编程——只写必要的、能理解的代码。

先修课程:这是个 Web 前端 + 后端 + 机器学习的综合项目,需要使用到 Vue(TypeScript)、Go、Python 等相关语言和技术。

文短码长,下文只给出必要的设计、核心的代码,忽略错误处理、并发安全等等工程中实际的问题。真实的代码实现,请读者参考源码:

服务 说明
xfgryujk/blivechat 获取直播间弹幕消息
Live2dView 前端:显示 Live2D 模型
Live2dDriver 驱动前端 Live2D 模型动作表情
ChatGPTChatbot 基于 ChatGPT 的优质聊天机器人
MusharingChatbot 基于 ChatterBot 的简单聊天机
Emotext 中文文本情感分析
muvtuberdriver 组装各模块,驱动整个流程

弹幕姬

技术栈:Node,Python。

为了和其他模块对接,我们需要那种能通过比较底层的方式输出弹幕的工具。我们要给机器看的,而不是一个给人看的黑箱的图形界面。

好在也不必自己从头写。xfgryujk/blivedm 就是这样的一个工具。作者大大还顺别提供了显示给人看的界面 blivechat

这里我们直接使用封装好的 blivechat。这个东西后端通过 WebSocket 把弹幕、礼物等消息发送给前端的界面。拉取、编译、运行 blivechat(blivechat 的 README 里有详细的安装、使用方法,此处从简。):

# clone repo
git clone --recursive https://github.com/xfgryujk/blivechat.git
cd blivechat

# 编译前端
cd frontend
npm install
npm run build
cd ..

# 运行服务
pip3 install -r requirements.txt
python3 main.py

虽然没有文档,但稍微抓包,就可以模仿出一个前端,通过 WebSocket 接口获取到弹幕:

// 建立链接
let ws = new WebSocket('ws://localhost:12450/api/chat');

// 订阅直播间
ws.send(JSON.stringify({
   
    "cmd": 1,
    "data": {
    "roomId": 000 }
}));

// 接收弹幕消息
ws.onmessage = (e) => {
   
  console.log(JSON.parse(e.data))
};

// KeepAlive:每 10 秒发一次 heartbeat
setInterval(() => {
   
  ws.send(`{"cmd":0,"data":{}}`)
}, 1000 * 10);

除此之外,我们还可以使用它自带的图形界面(有没有一种可能,这才是这个项目的正确用法),这个弹幕框可以由 OBS 采集输出到直播间里:

优质聊天机器人:ChatGPT

技术栈:Python

这应该是最有意思的部分,却也是最难的。幸好,有 ChatGPT。

acheong08/ChatGPT 项目提供了一个很好的 ChatGPT 接口。

安装:

pip3 install revChatGPT

使用:

from revChatGPT.V1 import Chatbot

chatbot = Chatbot(config={
   
  "access_token": "浏览器访问https://chat.openai.com/api/auth/session获取"
})

prompt = "你好"
response = ""

for data in chatbot.ask(prompt):
    response = data["message"]

print(response)

我们只要编写一条合适的 prompt,即可让 ChatGPT 化身“虚拟主播”,例如:

请使用女性化的、口语化的、抒情的、感性的、可爱的、调皮的、幽默的、害羞的、态度傲娇的语言风格,扮演一个正在直播的 vtuber,之后我的输入均为用户评论,请用简短的一句话回答它们吧。

大概是这种效果:

我并不擅长写 prompt,上面这段也改编自网络(原版大概是让做猫娘的),如果你有更好的 prompt,欢迎与我分享。

注:prompt 笑话一则:

嘿,知道吗?以后不需要程序员啦!只要描述出需求,ChatGPT 就能写出代码!

——太棒了,那么如何写出简洁清晰无歧义的需求描述呢?

呃,未来或许会有那么一种语言…

——你说的可能是:计算机程序设计语言 😃

我们把这个东西简单封装出一个 HTTP API,方便其他组件调用:

$ curl -X POST localhost:9006/renew -d '{"access_token": "eyJhb***99A"}' -i
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 2

ok
$ curl -X POST localhost:9006/ask -d '{"prompt": "你好"}'
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 
  • 15
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值