0 前言
最近朋友圈以及身边很多敌人都在钻研GPT开发,做了各种各样的小工具小Demo,AI工具用起来是真的香!在他们的影响下,我也持续捣鼓GPT Demo,心愿更多的开发者退出一起多多交换。
上一篇联合即时通 IM SDK捣鼓了一个Demo ChatGPT群聊机器人Demo ,也收到了一些还不错的反馈,有搭档用于客服场景解放了一部分人工反复工作晋升了效率。趁着周末我捣鼓了一个ChatGPT虚拟人直播,联合了同样热门的元宇宙技术。
本文将通过具体开发流程来为大家举例如何疾速实现一个虚拟人直播,可用于无人直播场景。ChatGPT虚拟人可抓取直播中粉丝弹幕和评论并回复来进行用户互动,晋升直播间的沉闷与用户体验。
最终实现成果如下所示:
GPT虚拟人直播
1 实现思路
ChatGPT4.0虚拟人直播,首先得要有2个最根本的能力:ChatGPT4.0接口和虚拟人交互能力,这两块咱们前面具体讲。整个流程如下图所示:
1.须要有具备文字驱动能力的虚拟人。具体来说,须要将文字转为语音,而后虚拟人能依据语音对口型。这里举荐应用即构Avatar,即构Avatar能够捏脸定制,同时具备文字驱动口型能力。
- 直播推流。抖音、快手能够用直播伴侣实时截屏推流。
- 获取实时弹幕/评论。虚拟人依据观众发的弹幕或者评论文本数据发送给ChatGPT,能够去github找开源代码。这里提供一个最简略的思路:在网页版注入JS代码,js实时读取网页上的弹幕。
- 调用ChatGPT。将实时弹幕/评论数据发送给ChatGPT并获取回复。
虚拟人播报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浏览器。- 开启VPN,注册用户或应用已有账号登录,点击右上角「设置」图标,将所在区域设置如下
- 关上Edge,输出网址https://www.bing.com/search?form=MY0291&OCID=MY0291&q=Bing+AI...
接下来在代码外面封装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); } } });}
接管到音讯
//接管到文字音讯@Overridepublic 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=sfarticle66
- 直播客户端客户端(android)https://github.com/RTCWang/ChatGPT-Avatar-live?source=sfarticle66
6 ChatGPT虚拟人直播Demo 应用工具
- 直播产品:RTC SDK Android Java实时音视频实现流程 - 开发者核心
- 语聊房:ZIM SDK Android即时通讯SDK实现根本音讯收发性能 - 开发者核心
- GPT4.0: New bing
- GPT3.5: ChatGPT