ZEGO教程:如何从零实现一个AI老师
上周,即构推出了AI智能课堂解决方案。方案采用即构独有的“切换推流视频无缝衔接”技术,解决了AI教师视频无延迟无卡顿实时切流播放、多个视频同时推流对服务器的巨大压力两大技术难点,实现教师视频片段无缝衔接,毫秒级合成,无限接近真人直播教学。具体可点击“即构推出AI智能课堂解决方案,加速AI老师落地应用”查看。今天,我们将AI智能课堂教师端技术实现的方法写出来,和大家分享如何从零开...
上周,即构推出了AI智能课堂解决方案。方案采用即构独有的“切换推流视频无缝衔接”技术,解决了AI教师视频无延迟无卡顿实时切流播放、多个视频同时推流对服务器的巨大压力两大技术难点,实现教师视频片段无缝衔接,毫秒级合成,无限接近真人直播教学。
具体可点击“即构推出AI智能课堂解决方案,加速AI老师落地应用”查看。
今天,我们将AI智能课堂教师端技术实现的方法写出来,和大家分享如何从零开始构建一个AI教师。
首先,我们来看AI智能课堂的整体架构:
1. 教师端(部署在Linux服务器上的程序)
2. 学生端(终端程序,如iOS/Android)
3. 传输桥梁(即构科技提供一整套实时音视频传输网络以及信令服务)
AI智能教师端实质是部署在Linux上的一个无界面程序。商用的AI智能课堂解决方案会带上语音识别等第三方模块,为了让读者能快速理解AI智能课堂解决方案的思路,5步完成AI教师模块的集成,本文仅从最简单的单选题形式去实现教师端与学生端的课堂互动。
一、准备
-
进入即构官网注册开发者账户,并获取App ID;
-
推荐使用ubuntu 18.04操作系统;
-
向即构技术支持联系获取ZegoLiveRoom SDK for Linux(MediaPublisher版本)
二、导入SDK
推荐使用Cmake组织工程,只需编写一份构建脚本,即可根据开发平台的不同生成不同平台的工程。
# 指定SDK头⽂件路径
include_directories(${CMAKE_CURRENT_LIST_DIR}/libs/linux/include/)
# 指定SDK库⽂件路径
link_directories(./libs)
# 链接库
target_link_libraries(AI-Demo libzegoliveroom.so)
三、集成 MediaPublisher 模块,直推mp4视频流
即构SDK提供MediaPublihser模块用于推mp4视频流,其优势在于mp4文件直接以码流的形式进行推流,在教师端不需要先经过解码操作,极大幅度降低CPU占用。同时,推流过程中可根据业务的需要中途无缝切换视频源,实现AI教学的效果。如:学生回答问题之后教师根据其作答给出对错判断,切换到不同的视频。
// 包含ZegoLiveRoom基础房间功能
#include "LiveRoom.h"
// 包含直推mp4码流功能
#include "zego-api-media-publisher.h"
int main(int argc, const char * argv[]) {
// 打印SDK版本号,成功输出则表示当前版本的SDK导入成功
printf("SDK Version: %s", LIVEROOM::GetSDKVersion());
// 设置SDK日志存放路径
char logDir[128] = { "./zegolog" };
LIVEROOM::SetLogDir(logDir);
// 打开调试输出开关
LIVEROOM::SetVerbose(true);
// 通过官网申请的App ID只配置了测试环境,因此该API必须设置为true
// 若需要配置正式环境,请联系即构技术支持
LIVEROOM::SetUseTestEnv(true);
// 请填写官网申请的App ID以及App Sign
unsigned int appId = xxxxxxxxx;
unsigned char appSign[] = {0x00,0x01...,0xff};
// 创建MediaPublisher模块,必须在InitSDK之前调用才能生效
MEDIAPUBLISHER::Create();
// 设置MediaPublisher事件回调,详情请参考头文件
MEDIAPUBLISHER::SetEventCallback(g_callback);
// 初始化SDK
LIVEROOM::InitSDK(appId, appSign, 32);
// 设置用户ID与用户名
LIVEROOM::SetUser("123456", "user-123");
// 以房主身份创建房间
LIVEROOM::LoginRoom("123", LIVEROOM::ZegoRoomRole::Anchor, "room-123");
// ...
// ...
}
四、集成即构自定义信令,实现师生间课堂交互
当学生与AI教师进入同一个房间后,即可使用自定义信令功能。核心API为SendCustomCommand,当一端调用SendCustomCommand后,另一端可通过OnRecvCustomCommand回调函数收到信令。开发者通过自定义信令的内容即可实现各种交互操作。以下通过几个例子说明信令的用法。
4.1 设置接收自定义信令的回调
int main(int argc, const char * argv[]) {
// ...
// ...
// 设置接收房间事件回调(包含自定义信令回调)
LIVEROOM::SetRoomCallback(g_room_callback);
// 初始化SDK
LIVEROOM::InitSDK(appId, appSign, 32);
// ...
// ...
}
4.2 开始上课
当学生向AI教师发送“开始上课”的信令后,AI教师开始将第一个视频进行推流。
// 收到来自学生的自定义信令
void OnRecvCustomCommand(const char *pszUserId, const char *pszUserName, const char *pszContent, const char *pszRoomID) {
// ...
// ...
// pszContent的内容可由开发者自己定制,推荐构造成json格式字符串;
rapidjson::Document doc;
doc.Parse(pszContent);
if(strcmp(doc["action"].GetString(), "start") == 0) {
// 将第一个待播放的视频文件放到播放队列中
MEDIAPUBLISHER::AddPath("./video/video1.mp4", false);
// 设置推流参数:分辨率640x360,帧率30fps,码率600k
// 开发者可自行调整参数
LIVEROOM::SetVideoFPS(30);
LIVEROOM::SetVideoBitrate(6000000);
LIVEROOM::SetVideoEncodeResolution(640, 360);
// 进行推流
LIVEROOM::StartPublishing("AI ROOM", "s-teacher-123", LIVEROOM::ZegoPublishFlag::ZEGO_JOIN_PUBLISH);
}
// ...
// ...
}
4.3 无缝切换视频
当学生通过信令发送答案到AI教师端时,AI教师端进行校验并且能够无缝切换到相对应的视频(如学生答对,则播放答对的视频,反之则播放答错的视频)。
// 收到来自学生的自定义信令
void OnRecvCustomCommand(const char *pszUserId, const char *pszUserName, const char *pszContent, const char *pszRoomID) {
// ...
// ...
// pszContent的内容可由开发者自己定制,推荐构造成json格式字符串;
rapidjson::Document doc;
doc.Parse(pszContent);
if(strcmp(doc["action"].GetString(), "answer")) {
auto data = doc["data"].GetObject();
// 判断答案正确与否(这里假定apple为正确答案)
if(strcmp(data["answer"].GetString(), "apple") == 0) {
//将回答正确的视频放到播放队列中
MEDIAPUBLISHER::AddPath("./video/video1-correct.mp4", false);
} else {
//将回答错误的视频放到播放队列中
MEDIAPUBLISHER::AddPath("./video/video1-wrong.mp4", false);
}
}
// ...
// ...
}
五、集成 MediaSideInfo 模块,实现题目下发
即构SDK提供MediaSideInfo模块用于下发媒体次要信息,开发者可根据自身的业务场景在合适的时间点向视频数据塞入自定义附加信息,拉流端在拉取到该视频数据时可解析出附加信息以进行业务逻辑的处理。
由于媒体次要信息与视频数据包是打包在一起传输的,因此媒体次要信息与视频是完全同步的。开发者若想要在视频播放的某个时刻下发题目,则必须使用媒体次要信息。(使用自定义信令不能保证画面与题目的同步)下面代码将展示AI教师根据设计好的时间点自动下发题目的操作:
在推流前设置使用 MediaSideInfo 模块
// 收到来自学生的自定义信令
void OnRecvCustomCommand(const char *pszUserId, const char *pszUserName, const char *pszContent, const char *pszRoomID) {
// ...
// ...
// pszContent的内容可由开发者自己定制,推荐构造成json格式字符串;
rapidjson::Document doc;
doc.Parse(pszContent);
if(strcmp(doc["action"].GetString(), "start") == 0) {
// 将第一个待播放的视频文件放到播放队列中
MEDIAPUBLISHER::AddPath("./video/video1.mp4", false);
// 设置推流参数:分辨率640x360,帧率30fps,码率600k
// 开发者可自行调整参数
LIVEROOM::SetVideoFPS(30);
LIVEROOM::SetVideoBitrate(6000000);
LIVEROOM::SetVideoEncodeResolution(640, 360);
// 启动 MediaSideInfo 模块
MEDIASIDEINFO::SetMediaSideFlags(true, false);
// 进行推流
LIVEROOM::StartPublishing("AI ROOM", "s-teacher-123", LIVEROOM::ZegoPublishFlag::ZEGO_JOIN_PUBLISH);
}
// ...
// ...
}
当视频开始播放后,通过以下回调处理事件。
// 每个视频文件开始出帧时回调
void ZegoAITeacher::OnFileDataBegin(const char* path) {
// 开启一个秒级定时器,作为视频播放的进度
m_cur_second = 0;
m_is_timer_active = true;
m_video_tick_timer->expires_after(std::chrono::seconds(1));
m_video_tick_timer->async_wAIt(std::bind(&ZegoAITeacher::OnVideoSecondTick, this));
// ...
// ...
}
// 定时器回调
void ZegoAITeacher::OnVideoSecondTick() {
// ...
// ...
//处理某个时间点的事件:假定第10秒发送一道题目
if(m_cur_second == 10) {
const char *question = "\"title\": \"1+1=?\",\"options\": [{\"answer\": \"1\"},{\"answer\": \"2\"}]";
MEDIASIDEINFO::SendMediaSideInfo(question, strlen(question), false);
}
// ...
// ...
m_cur_second++;
if(m_is_timer_active) {
m_video_tick_timer->expires_after(std::chrono::seconds(1));
m_video_tick_timer->async_wAIt(std::bind(&ZegoAITeacher::OnVideoSecondTick, this));
}
}
至此,AI教师所需的三大模块都已成功集成:
-
集成 MediaPublisher 模块,实现直推mp4视频流;
-
集成即构自定义信令,实现师生间课堂交互;
-
集成 MediaSideInfo 模块,实现教师端题目下发。
以上就是即构AI智能课堂教师端技术实现的方法,开发者可以根据实际业务逻辑作进一步扩展,将AI技术真正融入在线教育场景中,实现AI教学的产品创新。
更多推荐
所有评论(0)