关键词:
0 前言
最近朋友圈以及身边很多朋友都在研究GPT开发,做了各种各样的小工具小Demo,AI工具用起来是真的香!在他们的影响下,我也继续捣鼓GPT Demo,希望更多的开发者加入一起多多交流。
上一篇结合即时通 IM SDK捣鼓了一个Demo ChatGPT群聊机器人Demo ,也收到了一些还不错的反馈,有伙伴用于客服场景解放了一部分人工重复工作提升了效率。趁着周末我捣鼓了一个ChatGPT虚拟人直播,结合了同样热门的元宇宙技术。
本文将通过详细开发流程来为大家举例如何快速实现一个虚拟人直播,可用于无人直播场景。ChatGPT虚拟人可抓取直播中粉丝弹幕和评论并回复来进行用户互动,提升直播间的活跃与用户体验。
最终实现效果如下所示:
GPT虚拟人直播
1 实现思路
ChatGPT4.0虚拟人直播,首先得要有2个最基本的能力:ChatGPT4.0接口和虚拟人交互能力,这两块我们后面具体讲。整个流程如下图所示:
1.需要有具备文字驱动能力的虚拟人。具体来说,需要将文字转为语音,然后虚拟人能根据语音对口型。这里推荐使用即构Avatar,即构Avatar可以捏脸定制,同时具备文字驱动口型能力。
2. 直播推流。抖音、快手可以用直播伴侣实时截屏推流。
3. 获取实时弹幕/评论。虚拟人根据观众发的弹幕或者评论文本数据发送给ChatGPT,可以去github找开源代码。这里提供一个最简单的思路:在网页版注入JS代码,js实时读取网页上的弹幕。
4. 调用ChatGPT。将实时弹幕/评论数据发送给ChatGPT并获取回复。
5. 虚拟人播报ChatGPT的回复。
2 ChatGPT接入
目前openAI提供的接口是ChatGPT3.5,可以直接调用。bing在最新版Edge浏览器提供ChatGPT4.0体验,有一些开源库对其做了二次封装,只需提供Cookie即可体验。这里我们把两种方式都讲解。
2.1 ChatGPT 4.0 接入
首先注册bing账号:
1.前往https://www.microsoft.com/zh-cn/edge/download?ch&form=MA13FJ 下载最新的Edge浏览器。
2. 注册用户或使用已有账号登录,点击右上角「设置」图标,将所在区域设置如下
3. 打开Edge,输入网址https://www.bing.com/search?form=MY0291&OCID=MY0291&q=Bing+AI&showconv=1
接下来在代码里面封装ChatGPT4.0接口,先安装第三方基于Edge浏览器的库:
npm i @waylaidwanderer/chatgpt-api
接下来二次封装
import BingAIClient from \'@waylaidwanderer/chatgpt-api\';
export class BingGPT
/*
* http_proxy, apiKey
**/
constructor(http_proxy, userCookie)
this.api = this.init(http_proxy, userCookie);
init(http_proxy, userCookie)
console.log(http_proxy, userCookie)
const options =
// Necessary for some people in different countries, e.g. China (https://cn.bing.com)
host: \'https://www.bing.com\',
// "_U" cookie from bing.com
userToken: userCookie,
// If the above doesn\'t work, provide all your cookies as a string instead
cookies: \'\',
// A proxy string like "http://<ip>:<port>"
proxy: http_proxy,
// (Optional) Set to true to enable `console.debug()` logging
debug: false,
;
return new BingAIClient(options);
//调用chatpgt
chat(text, cb)
var res=""
var that = this;
console.log("正在向bing发送提问", text )
this.api.sendMessage(text,
toneStyle: \'balanced\',
onProgress: (token) =>
if(token.length==2 && token.charCodeAt(0)==55357&&token.charCodeAt(1)==56842)
cb(true, res);
res+=token;
);
注意到,除了需要提供vpn地址以外,还需要提供cookie数据。cookie可以在Edge浏览器中按F12打开开发工具,点击应用程序Tab,从左侧Cookie中找到_U的value即为想要的cookie,如下图所示:
2.2 ChatGPT 3.5接入
因为ChatGPT4.0基于浏览器,非官方提供的API,整体会有些不太稳定。而OpenAI官方提供了ChatGPT3.5,相比之下更稳定。
首先要有OpenAI的ChatGPT账号,在这里我们不细讲,不了解的同学可以参考我另一篇文章,链接: 《当我把ChatGPT拉进群聊里,我的朋友都玩疯了》接下来只需安装ChatGPT库:
npm install chatgpt
注意要使用nodejs 18.0以上版本安装,因为国内的IP无法使用ChatGPT,因此必须要有VPN代理。再安装一个代理库:
npm install https-proxy-agent node-fetch
接下来,二次封装一下:
import ChatGPTAPI from "chatgpt";
import proxy from "https-proxy-agent";
import nodeFetch from "node-fetch";
export class ChatGPT
constructor(http_proxy, apiKey)
this.api = this.init(http_proxy, apiKey);
this.conversationId = null;
this.ParentMessageId = null;
init(http_proxy, apiKey)
console.log(http_proxy, apiKey)
return new ChatGPTAPI(
apiKey: apiKey,
fetch: (url, options = ) =>
const defaultOptions =
agent: proxy(http_proxy),
;
const mergedOptions =
...defaultOptions,
...options,
;
return nodeFetch(url, mergedOptions);
,
);
//调用chatpgt
chat(text, cb)
let that = this
console.log("正在向ChatGPT发送提问:", text)
that.api.sendMessage(text,
conversationId: that.ConversationId,
parentMessageId: that.ParentMessageId
).then(
function (res)
that.ConversationId = res.conversationId
that.ParentMessageId = res.id
cb && cb(true, res.text)
).catch(function (err)
console.log(err)
cb && cb(false, err);
);
注意到除了需要提供VPN地址,还需要提供apiKey。登录OpenAI后,打开链接https://platform.openai.com/account/api-keys 即可获取apiKey,如下图所示
3 虚拟人接入
虚拟人提供商有很多,由于目前我们不仅仅需要有虚拟形象,还需要虚拟人能够说话(ChatGPT提供逻辑思维能力)。因此,我们这里直接选用 即构Avatar,它内置了文本驱动能力,可以很方便将ChatGPT的回复文字内容直接读出来,并有口型匹配。非常适合我们这个场景。
官方提供了非常详细的教程:官方教程地址,本文简单讲解一些关键实现,具体完整代码可以参考文末资源附件。
设置虚拟人形象:
private void setCharacter(User user)
String sex = ZegoCharacterHelper.MODEL_ID_MALE;
if (!user.isMan) sex = ZegoCharacterHelper.MODEL_ID_FEMALE;
// 创建 helper 简化调用
// base.bundle 是头模, human.bundle 是全身人模
mCharacterHelper = new ZegoCharacterHelper(FileUtils.getPhonePath(mApp, "human.bundle", "assets"));
mCharacterHelper.setExtendPackagePath(FileUtils.getPhonePath(mApp, "Packages", "assets"));
// 设置形象配置
mCharacterHelper.setDefaultAvatar(sex);
// 角色上屏, 必须在 UI 线程, 必须设置过avatar形象后才可调用(用 setDefaultAvatar 或者 setAvatarJson 都可以)
mCharacterHelper.setCharacterView(user.avatarView, () ->
);
mCharacterHelper.setViewport(ZegoAvatarViewState.half);
//设置头发、衣服等
mCharacterHelper.setPackage("ZEGO_Girl_Hair_0001");
mCharacterHelper.setPackage("ZEGO_Girl_Tshirt_0001_0002");
mCharacterHelper.setPackage("facepaint5");
mCharacterHelper.setPackage("irises2");
initTextApi();
updateUser(user);
可以看到,只需简单几行代码即可定制虚拟人“皮肤”,使用非常友好。在文字驱动虚拟人说话方面就更简单:
public void playText(String text)
if (mTextApi == null) return;
mTextApi.playTextExpression(text);
当然了,这里展示的是最关键代码。要想使用即构avatar还需要做一些权鉴认证、引擎初始化等工作,直接复用本文文末提供的代码附件即可。
需要注意的是,官方提供的Demo源码中只有基础资源。换句话说,还有很多非常酷炫的“皮肤”可以使用。但是因为资源太大,不方便打包。如果读者有更多资源需求,可以直接去官网找客服索要。
下面列出一些官方能提供的虚拟形象“皮肤”示例:
还有很多捏脸能力,这里不一一描述,感兴趣的同学可以直接去官网 (点击这里)去下载体验app,直接感受一下即构Avatar的强大。
4 基于即构SDK实现虚拟直播
对于B站、抖音、快手等第三方平台,想要做虚拟直播得借助官方提供的推流工具,如直播伴侣等。但官方没有提供实时获取直播间评论(或弹幕)的接口,当然了,你可以用一些技术手段来获取,这里不过多讲解。接下来我们讲解不用第三方平台,自己简单几行代码实现搭建直播平台。
4.1 搭建虚拟人直播平台思路
搭建虚拟直播平台有2个思路:
1.主播实时传输手机画面,观众实时接收主播发送的内容(图像),即构实时音视频RTC 该方案实现 可查看,RTC+Avatar方案可查看。
我之前基于抖音平台做的虚拟人直播Demo, B站、快手等第三方直播平台的实现原理类似。
2.基于即构ZIM,实时传输文字(文字)
虚拟人直播与其他直播有一个差别是虚拟人是在用户端上使用固定算法渲染出来的,而不是主播实时拍摄的画面。因此我们完全不需要主播实时传输画面(图像),只需通过广播文字内容(相当于群组聊天),观众接收到文字内容后实时渲染虚拟人表情即可。这样可以大大节省带宽成本。
即构ZIM提供全面的IM能力,支持单聊/群聊/房间聊天,可根据实际业务自由组合IM能力。群聊消息稳定可靠、延迟低,全球任何一个地区都有接入服务的节点保障消息到达。 了解更多
4.2 具体实现
从上面两个方案可以看到,对于虚拟直播间来说,使用文字实时传输到每个端上,再本地渲染虚拟人画面,可以做到最低成本。
具体来说,一个直播间可以通过一个房间(room)来管理,在即构IM的房间内,可以使用弹幕功能来实现收发文字。相比发送聊天消息,发送弹幕消息不会被存储,更适合直播间评论功能。用户创建直播间时,底层代码创建的是一个房间,并自动加入ChatGPT这个群成员。ChatGPT在群里接收到数据时,调用ChatGPT接口,得到文字回复后,再转发到群里。每个观众接收到ChatGPT回复的文字后,自动渲染虚拟人播报文字内容。
同样的,这里我们只展示关键代码。创建房间、加入房间、收到实时评论(弹幕)。
创建房间、加入房间:
//创建房间
public void createRoom(String masterId, String roomId, String roomName, CB cb)
ZIMRoomInfo groupInfo = new ZIMRoomInfo();
groupInfo.roomID = roomId;
groupInfo.roomName = roomName;
zim.createRoom(groupInfo, new ZIMRoomCreatedCallback()
@Override
public void onRoomCreated(ZIMRoomFullInfo roomInfo, ZIMError errorInfo)
if (errorInfo.code == ZIMErrorCode.SUCCESS)
inviteJoinRoom(masterId, roomId, CHATGPT_ID, cb);//这里把chagpt的用户id硬编码
else
cb.complete(false, "房号已存在,请更换一个房间号!");
);
//加入房间
public void joinRoom(String roomId, CB cb)
zim.joinRoom(roomId, new ZIMRoomJoinedCallback()
@Override
public void onRoomJoined(ZIMRoomFullInfo roomInfo, ZIMError errorInfo)
Log.e(TAG, ">>" + errorInfo.code);
if (errorInfo.code == ZIMErrorCode.ROOM_DOES_NOT_EXIST)
cb.complete(false, "房间不存在!");
else if (errorInfo.code == ZIMErrorCode.SUCCESS || errorInfo.code == ZIMErrorCode.THE_ROOM_ALREADY_EXISTS)
cb.complete(true, roomInfo.baseInfo.roomName);
);
接收到消息
//接收到文字消息
@Override
public void onRcvMsg(Msg msg)
switch (msg.proto) //判断消息类型
case ChatGPT: //来自ChatGPT的消息,语音播报文字
mZegoMngr.getAvatarMngr().playText(msg.msg);
sendDM(msg.msg.replace("\\n", ""), 0);
break;
case DanMu: //收到弹幕消息,直接在屏幕上展示
sendDM(msg.msg, msg.extInt);
break;
case DismissRoom: //收到解散房间消息,退出房间
mZegoMngr.getZIMMngr().leaveRoom(msg.msg, new CB()
@Override
public void complete(boolean succ, String msg)
ShowUtils.alert(RoomActivity.this, "提示", "房间已解散!", new ShowUtils.OnClickOkListener()
@Override
public void onOk()
back();
);
);
break;
5 开源-Github源码
- ChatGPT调用代码(nodejs)https://github.com/RTCWang/ChatGPT-Avatar-live?source=cnblogarticle66
- 直播客户端客户端(android)https://github.com/RTCWang/ChatGPT-Avatar-live?source=cnblogarticle66
6 ChatGPT虚拟人直播Demo 使用工具
- 直播产品:RTC SDK Android Java实时音视频实现流程 - 开发者中心
- 语聊房:ZIM SDK Android即时通讯SDK实现基本消息收发功能 - 开发者中心
- GPT4.0: New bing
- GPT3.5: ChatGPT
人人都能做产品经理吗?
...sp;阿里巴巴的产品经理苏杰写了一本非常火的书,叫做「人人都是产品经理」,介绍产品经理的思维方法,并且在生活的方方面面都可以运用产品经理的思维解决问题。这本书对于提高人们普遍意义的思考能力有一定的帮助, 查看详情
如何搭建chatgpt4.0模型-国内如何用chatgpt4.0
国内如何用chatGPT4.0在国内,目前可以通过以下途径使用OpenAI的ChatGPT4.0:自己搭建模型:如果您具备一定的技术能力,可以通过下载预训练模型和相关的开发工具包,自行搭建ChatGPT4.0模型。OpenAI提供了相关的... 查看详情
从个人到创业团队都能用的项目开发部署流程!建议收藏!(代码片段)
...。🐮目录前言概览-基本流程1.需求分析2.UI设计3.产品开发4.环境部署总结前言对于个人开发者,和处在初期的项目团队来讲,除了做什么——项目选型之外,还有一个很重要,就是怎么做——如何完善自己团... 查看详情
从个人到创业团队都能用的项目开发部署流程!建议收藏!(代码片段)
...。🐮目录前言概览-基本流程1.需求分析2.UI设计3.产品开发4.环境部署总结前言对于个人开发者,和处在初期的项目团队来讲,除了做什么——项目选型之外,还有一个很重要,就是怎么做——如何完善自己团... 查看详情
自动化测试框架如果都总结成这样,人人都能学好|51做专家(代码片段)
1、自动化测试框架设计的核心,可以概括为解决以下这些问题:1)测试数据要怎么准备,如何在框架中实现,是否可复用。2)测试用例的批量导入。3)用例之间是否存在逻辑关系,相互之间是否有影响,在... 查看详情
fasttunnel-打造人人都能搭建的内网穿透工具(代码片段)
FastTunnel是用.netcore开发的一款跨平台内网穿透工具,它可以实现将内网服务暴露到公网供自己或任何人访问。与其他穿透工具不同的是:FastTunnel项目致力于打造一个易于扩展、易于维护的内网穿透框架,任何人都可... 查看详情
树莓派都能做脑机接口了?实时处理8个电极信号,人人用得起|开源
行早发自凹非寺量子位报道|公众号QbitAI只需要一块树莓派的板子,就可以做一个脑机接口?没有开玩笑,这位俄罗斯小哥Rakhmatulin还真做出来了,这接地气的设备只用一块树莓派板子做处理器,可以实时处理... 查看详情
让aed急救包不再是摆设,华为云+国产厂商开发ai培训系统,人人都能当急救员...
允中发自凹非寺量子位|公众号QbitAI据《中国心血管健康与疾病报告2021》显示,我国每年有超过55万人逝于心源性猝死。其中80%以上的意外发生在医院之外,现场救助条件不完善,导致很多人失去了宝贵生命。在急救... 查看详情
人人都能看懂的6种限流实现方案(代码片段)
为了上班方便,去年我把自己在北郊的房子租出去了,搬到了南郊,这样离我上班的地方就近了,它为我节约了很多的时间成本,我可以用它来做很多有意义的事,最起码不会因为堵车而闹心了,幸福感直线上升。 但即... 查看详情
有了它,人人都能玩转ar名片
原文标题:有了它,人人都能玩转AR名片 在商业活动中,名片即门面,是你身份的象征!它不仅能反应你的业务能力,更能凸显公司的形象。如何在众多名片中给人留下深刻的第一影响呢?一张创意十足的名片... 查看详情
人人都能看懂的spring源码解析,spring如何解决循环依赖
人人都能看懂的Spring源码解析,Spring如何解决循环依赖原理解析什么是循环依赖循环依赖会有什么问题?如何解决循环依赖问题的根本原因如何解决为什么需要三级缓存?Spring的三级缓存源码走读Spring的三级缓存提前... 查看详情
人人都能学会系列之threadlocal(代码片段)
1、概览本文我们来看下java.lang包中的ThreadLocal,它赋予我们给每个线程存储自己数据的能力。2、ThreadLocalAPIThreadLocal允许我们存储的数据只能被特定的线程``访问。我们现在存储一个整形并把它和一个特定的线程绑定:ThreadLocal<... 查看详情
人人都能看懂的lstm
点击上方“迈微AI研习社”,选择“星标★”公众号重磅干货,第一时间送达大家好,我是Charmve。熟悉深度学习的朋友知道,LSTM是一种RNN模型,可以方便地处理时间序列数据,在NLP等领域有广泛应用。在看了台大李宏毅教授的... 查看详情
review:人人都能看懂pod与容器设计模式
Review:人人都能看懂Pod与容器设计模式[]:https://mp.weixin.qq.com/s?__biz=MzA4ODg0NDkzOA==&mid=2247488010&idx=1&sn=37e4a3bff67d5ce466685b646cbab279&chksm=9022adefa75524f9f63ddc98d05210958725b79ba9823 查看详情
c#的类的属性与类的变量有啥区别?不是都能用"."访问吗?
...属性是对类变量的一种封装,使其使用更安全。我们在做开发时,基本上不会把变量暴露给外部类的,都会使用属性进行封装。 参考技术B类是单继承的,一个基类可以派生多个子类,就算是有get、set父类也不可能访问子类,只... 查看详情
微信小程序都能用啥语言开发呢
1、支持的前端开发语言有:前端主要是用WXML、WXSS以及JavaScript来开发。本质上就是JS+CSS+HTML5,不过不能直接用HTML标签,微信提供一个组件库,没有DOM和其他浏览器上的API;网络、Canvas等也重新包装过。【点击查看APP开发的真正... 查看详情
树莓派dietpi是否raspbian能用的软件都能用
参考技术A不解藏踪迹, 查看详情
大白话聊聊微服务——人人都能看懂的演进过程
这篇博客的本意是希望看到这篇文章的读者能够很轻松的理解我想表达的意思。但程序向的分享经常会不经意间就贴上了代码,很可能就会让人看的很懵。而且我认为分享一个东西,只有对方真正明白了其中的逻辑,才是有意义... 查看详情