新知实验室 TRTC在线上教育场景中的一种应用实践

一、参赛说明

很荣幸参与此次征文活动,我是从2年多以前,接触腾讯云TRTC相关产品,正逢疫情肆虐,很多业务迫切需要从线下转移到线上。

经过2年的实践,TRTC本身也经历了多次的迭代,功能更强大,也更稳定。我们基于TRTC开发的产品,也慢慢的支持了更多的功能,可以和公司原有的业务系统对接组合,提供更丰富的场景服务。

此次参赛,我会剔除掉强业务的部分,尽量完整的展现,基于TRTC搭建的云直播专题活动平台。

二、参赛主题

自定义主题。

三、场景说明

我所负责的主要业务是,基于腾讯云的TRTC及相关产品线,搭建面向青少年的科普在线直播平台。

涉及到的主要流程如下

  1. 由1名或多名(不超过16名)的嘉宾,进入我们的Web端实时音视频会议室,并通过屏幕分享,来开启主题讲座;
  2. 服务端集成TRTC SDK,利用云端混流功能,结合我们自己开发的推流面板,设置推流模板和直播参数,将专家的直播间画面,推流到云直播平台;
  3. 用户端,通过访问我们的在线学习平台,可以观看线上直播。
  4. 直播期间用户可以提交文字留言和视频连线申请,由于是教育平台,所以文字留言和视频连线申请,都是需要管理员审核的,审核通过后,专家即可看到用户留言,同时,用户也可以进入到专家的音视频房间,和专家学者进行面对面交流,用户端进入音视频直播间的渠道,提供了微信小程序和web端两种形式。
  5. 所有的直播,均可以在直播面板进行推流参数的控制和录制。

四、整体流程

这个部分,我想分别从云服务侧,和我们自己的业务侧,两个层面来分别阐述。其中云服务侧的流程主要是配置和自己总结的一些注意事项供参考,业务侧的流程,就是怎么具体操作,完成一场完整的线上直播公开课。

业务结构图如下👇 

4.1 云服务侧

这里我想说明的是,我这里的配置流程,是基于我们的产品需求进行的配置,包含了实时音视频,云直播和云点播三个部分。

4.1.1 实时音视频服务

  1. 实名认证,根据政策法规,在开始使用云服务之前,首先需要完成的步骤,具体操作可以参加官方文档👉:账号相关 实名认证账号归属介绍-实名认证-文档中心-腾讯云
  2. 开通实时音视频服务,地址👉:登录 - 腾讯云
  3. 创建应用,这里创建应用只需要提供应用名即可;
  4. 配置旁路转推,在应用列表中,选择创建应用右测的【功能配置】,开启【旁路转推】注意转推方式选【指定流旁路】(这里腾讯还提供了【全局自动旁路】的选项,但由于该选项成本较高,可根据自身实力酌情选择)
  5. 配置云端录制,同样在【功能配置】页面,开启【启用云端录制】选项,同时录制形式选择【指定用户录制】(这里腾讯云还提供了【全局自动录制】选项,不选择的原因同上);
  6. 其他配置,我这里还用到了素材和回调功能,主要是用来配置混流模板时的占位图以及进入线上直播间时发送邮件通知;
  7. 最后,保存好应用的SDKAppID,SDKSecretKey,以及旁路直播的appid,bizid,在后续的开发中分别用来生成UserSig和直播转推等功能。

4.1.2 云直播服务

  1. 开通云直播服务,地址👉:登录 - 腾讯云
  2. 配置推流域名和播放域名,其中推流域名在开通直播服务后会白给一个,可以直接用,但播放域名需要自行添加,具体规则👉:云直播 域名管理-控制台指南-文档中心-腾讯云
  3. 其他配置,根据个人需求,可以配置是否开启https,推流域名可以配置录制模板,播放域名可以配置转码模板等,我这里时配置了录制模板,开启了https,并配置了直播回调事件,方便在执行推流操作时发送邮件通知;
  4. 根据实际情况买点流量包,首次开通官方会赠送一点,足够测试。

4.1.2 云点播服务

  1. 开通云点播服务,地址👉:登录 - 腾讯云
  2. 根据实际情况买点存储包,用来保存录制的回放视频。

至此,云服务端的配置基本结束,其中主要功能点的配置集中在实时音视频和云直播两个环节,云点播我这边主要使用于存储回放视频,后续的视频分发是通过下载源文件到本地做转码和分割等操作,还没有集成云点播以及腾讯云CDN的分发能力,所以这里只开通服务并保证有足够存储包就可以支撑我们的业务。

4.2 业务侧

在完成云服务侧的相关配置后,我们的业务侧就可以专注流程开发,我这里就以“如何完成一场线上公开课”为主题,介绍一下在我们业务侧系统的操作流程。

4.2.1 功能总览

在流程开始之前,我先简单描述下为了完成一场线上公开课,需要用到的一些主要功能

  • 课程管理:这部分就是纯业务侧的功能,主要是发布课程信息,和云服务侧关联的点就是课程的播放地址,如下图👇。

  • 房间管理:这部分是线上直播的关键部分,嘉宾通过我们提供的专属链接进入到线上直播间,同时直播播放链接的生成也需要拼接正确的房间号。这里我们的系统对房间的开启状态做了管理,即只有先开启指定房间号,嘉宾和用户才能进入直播间进行下一步的操作
  • 直播推流:这部分是通过在服务端集成TRTC SDK,实现云端混流,通过我们自己开发的推流面板,可以快速开启线上公开课的直播。

4.2.2 课程管理

由于这部分偏业务侧,这里不再多介绍,起到的作用就是,根据后台配置的播放地址,用户进入到对应的课程详情页里可以观看对应的直播课,同时还有一些内部的业务,如观看统计,打卡,课后答题等等,效果如下(配图马赛克请谅解)

 

4.2.3 房间管理

房间管理是业务侧的核心功能,我这里想按照,准备阶段,进行阶段和收尾阶段分别进行介绍

准备阶段

房间管理是正式开启直播前的必要操作,操作起点是管理人员开启指定的房间号,这一步的目的是由于业务特殊性,我们举办的线上公开课每次都要邀请一些嘉宾来主讲,而给到嘉宾的系统入口就是一个拼接好的链接,因此采用了控制房间开闭的方式,来保证安全性。

而房间管理的原理实际就是维护了一个存储于Redis的Hash表,通过简单的管理的界面来进行创建和销毁。

如果通过链接进入到没有开启的房间,会得到相应的提示,且无法正常进入音视频通话房间。同样,只有开启后的房间,才能通过链接和小程序扫进入。

进行阶段

进入到进行阶段,正常来说就是房间内已经有嘉宾进入了,这里我们提供了2种模式,“普通模式”就是根据腾讯云TRTC For Web SDK官方的BaseJs版本,简单修改,集成了水印和虚拟背景的功能,外加一些业务整合而成。而“会议模式”则是根据TRTC提供的TUIRoom,也是稍加修改整理而成。不同的风格见截图👇

  • 普通模式效果73ed8e0b3120fe5dccd1de19c6de3f9c.png

  • 普通模式含水印

  • 普通模式开启虚拟背景效果(关于虚拟背景的集成,我之前也写过一篇粗陋的博文3eb4f6c6f90fbe740fa629a1f428b6dc.png

  • 会议模式效果

  • 小程序效果

这里在进入直播间后,我们也提供了一个房间列表的管理界面,可以查看房间内人员,设备信息等操作

其中,点击【查看人员】按钮可以查看房间内成员,并进行一些强制措施,【直播设置】按钮进入在线导播台,【解散房间】按钮则会结束当前在线房间的会话,同时关闭房间。

回收阶段

直播结束后,管理人员停止推流,或者直接解散正在进行的音视频通话房间,都将中止直播,此时无论是业务侧的相关数据统计,还是云服务端的流量消耗和云端录制,都会停止。

此时,需要管理人员登录腾讯云控制台,到云点播界面下载录制文件到本地,进行后续的处理和上传工作。

4.2.4 直播推流

直播阶段,就是在上述【房间管理】的【进行阶段】提供的管理列表页,进入到处于进行中状态的房间内,进行直播推流。

主要包含三大配置项

  • 基础配置:配置房间号,流ID,是否录制和推流方式。其中房间号和流ID会自动生成,如无特殊情况,不需要管理人员自行修改。而”云端录制“功能则需要按需开启,开启后会有计费项产生。
  • 推流配置:根据情况设置推流的相关参数,分辨率,帧率,码率,采样率等。
  • 布局配置:配置推流模板,主画面,混流人员等。

这里我也给预设模板绑定了预设参数,如果使用【预设模板】,则【推流配置】的参数都会自动生成,一般不需要手动调整。

预设模板的作用就是设置推流布局,适应不同风格的直播画面。

点击导播台的模板编辑入口后,可以进入模板编辑页面,如果点击进入时,没有选中任何模板,则会创建新的模板,反之则加载之前的模板,可进行修改操作。

配置好模板,就可以进行实际的推流操作了,最终在该页面的“直播预览”窗口展示的,就是最终普通用户看到的直播画面。

对于用户端观看直播,我们还集成了腾讯云的超级播放器SDK,用于支持低延时直播协议(webrtc)。

这个部分主要是集成的服务端SDK,文档地址👉:实时音视频 API 概览-服务端 API -文档中心-腾讯云

此外云端混流提供的自定义布局模板参数,主要参考PresetLayoutConfig的参数模型,文档地址👉:实时音视频 数据结构-API 中心-腾讯云

而关于自定义模板的设置,这里主要是继承了Farbic.js插件的能力,关于该插件,我在别的平台有写过一 篇博客(已转发至CSDN写作中心),当然也可以到其官网查看。

五、贴点代码

我非常清楚那句话,“Talk is Cheap”。所以,在看了一些其他人的作品,我也觉得需要在博文里贴点代码。其实提交的参赛作品里已经有提交的仓库地址了,我这里就拿整个线上直播中的几个流程,贴一下关键代码。

5.1 生成userSig(服务端)

我这边给出的是基于.net core开发框架的例子

public IActionResult GetUserSig(string username)
{
    int appId = Convert.ToInt32(ConfigurationHelper.GetSectionValue("trtcId"));
    string secret = ConfigurationHelper.GetSectionValue("trtcSecret");
    string userSig = new TLSSigAPILib(appId, secret).genUserSig(username);
    string userShareSig = new TLSSigAPILib(appId, secret).genUserSig("share_" + username);
    return Json(resp.success(new { userSig, userShareSig }));
}

5.2 云端混流(服务端)

public static async Task<Response> PushLive(PushStreamModel model)
{
    try
{
    ClientProfile clientProfile = new ClientProfile();
    HttpProfile httpProfile = new HttpProfile();
    httpProfile.Endpoint = ("trtc.tencentcloudapi.com");
    clientProfile.HttpProfile = httpProfile;

    TrtcClient client = new TrtcClient(cred, "ap-guangzhou", clientProfile);
    StartMCUMixTranscodeRequest req = new StartMCUMixTranscodeRequest();
    req.SdkAppId = Convert.ToUInt64(Common.ConfigurationHelper.GetSectionValue("trtcId"));
    req.RoomId = model.RoomId;
    OutputParams outputParams1 = new OutputParams()
{
    StreamId = model.OutputParams.StreamId,
    PureAudioStream = model.OutputParams.PureAudioStream,
    RecordId = model.OutputParams.RecordId,
    RecordAudioOnly = model.OutputParams.RecordAudioOnly
    };
    req.OutputParams = outputParams1;
    EncodeParams encodeParams = new EncodeParams()
{
    AudioBitrate = model.EncodeParams.AudioBitrate,
    AudioChannels = model.EncodeParams.AudioChannels,
    AudioSampleRate = model.EncodeParams.AudioSampleRate,
    BackgroundColor = model.EncodeParams.BackgroundColor,
    BackgroundImageId = model.EncodeParams.BackgroundImageId,
    VideoBitrate = model.EncodeParams.VideoBitrate,
    VideoFramerate = model.EncodeParams.VideoFramerate,
    VideoGop = model.EncodeParams.VideoGop,
    VideoHeight = model.EncodeParams.VideoHeight,
    VideoWidth = model.EncodeParams.VideoWidth,
    AudioCodec = model.EncodeParams.AudioCodec,
    BackgroundImageUrl = model.EncodeParams.BackgroundImageUrl
    };
    req.EncodeParams = encodeParams;
    LayoutParams layoutParams = new LayoutParams()
{
    MainVideoUserId = model.layoutParams.MainVideoUserId,
    MainVideoRightAlign = model.layoutParams.MainVideoRightAlign,
    MainVideoStreamType = model.layoutParams.MainVideoStreamType,
    MixVideoUids = model.layoutParams.MixVideoUids,
    Template = model.layoutParams.Template,                    
};
    if (model.layoutParams.presetLayoutConfigs!=null)
{
    List<PresetLayoutConfig> list = new List<PresetLayoutConfig>(model.layoutParams.presetLayoutConfigs.Length);
    foreach (var config in model.layoutParams.presetLayoutConfigs)
{
    list.Add(new PresetLayoutConfig()
         {
    UserId = config.UserId,
    StreamType = config.StreamType,
    ImageHeight = config.ImageHeight,
    ImageWidth = config.ImageWidth,
    MixInputType = config.MixInputType,
    PlaceImageId = config.PlaceImageID,
    LocationX = config.LocationX,
    LocationY = config.LocationY,
    RenderMode = config.RenderMode,
    ZOrder = config.ZOrder
    });
}
    layoutParams.PresetLayoutConfig = list.ToArray();
}
    req.LayoutParams = layoutParams;

    if (model.publishCdnParams != null)
{
    PublishCdnParams publishCdnParams = new PublishCdnParams();
    publishCdnParams.BizId = Convert.ToUInt64(model.publishCdnParams.BizId);
    publishCdnParams.PublishCdnUrls = model.publishCdnParams.PublishCdnUrls;
    req.PublishCdnParams = publishCdnParams;
}
    StartMCUMixTranscodeResponse dresp = await client.StartMCUMixTranscode(req);
    //layoutParams.SmallVideoLayoutParams = ;                
    resp.code = 1;
    resp.data = dresp;
}
    catch (Exception ex)
{
    resp.code = -1;
    resp.message = $"推流失败,{ex.Message},{ex.StackTrace}";
}
    return resp;
}

5.3 接入IM(服务端)

接入IM的部分其实可以展开聊,因为TRTC的一些功能是依赖IM的,比如踢人,这里我给出之前写的一个博客地址(已经转发至CSDN平台),这里就不在这里展开贴代码了,👉:

通过集成腾讯 IM 来浅尝一下.net 6 的 MINI API_为自己_带盐的博客-CSDN博客

5.4 虚拟背景(客户端)

客户端因为我们提供的普通模式就是在腾讯云trtc web sdk的demo基础上,稍微加工了一下,集成我们业务侧的一些逻辑,所以确实没什么好说的。

想聊一下虚拟背景是因为,这个在实际的业务场景中还是有需求的,为了不灌太多代码,我这里也给出自己之前在其他平台写的一个关于TRTC集成虚拟背景的一个博客地址(已经转发至CSDN平台)👉:

微服务先等等,我去刷个“虚拟背景”的副本_为自己_带盐的博客-CSDN博客

5.5 TUIRoom(客户端)

TUIRoom在刚推出的时候,我个人觉得界面风格非常讨喜,也是迫不及待的就试了一下,并接入到了我们的业务系统里,关于这部分的集成,我也写过两篇博客,分了、下两篇(已经转发至CSDN平台)👉:

浅尝不辄止系列之试试腾讯云的 TUIRoom(上)_为自己_带盐的博客-CSDN博客

浅尝不辄止系列之试试腾讯云的 TUIRoom(下)_为自己_带盐的博客-CSDN博客

5.6 设置混流自定义模板(客户端)

这部分我在上面的直播推流阶段聊过了,主要是通过fabric.js来生成自定义的模型参数,然后利用TRTC云端混流接口,完成直播推流。

博客地址👉:用了 Fabric.js 后突然想到了..._为自己_带盐的博客-CSDN博客

额。。。不会因为我引用在别的平台发的文章而犯规吧(⊙﹏⊙)

已于2022.12.5将本文引用的所有在其他平台发布的文章转载至CSDN~

六、总结

本项目最核心的功能还是集成了TRTC提供的音视频通话和云端混流的能力,通过集成服务端SDK,我们的项目涵盖了trtc服务端提供的管理能力,再通过整合我们自己的业务逻辑,基本可以实现,仅需一位运营人员就能至少主持一场中小规模的在线直播活动。

这个结果对于我们实际的应用场景来说,就是可以频繁且高效的举办线上专题讲座。

最后,展示几个实际活动的直播截图。

  • 举办河北客户的专场活​(配图马赛克请谅解)

 

  • 举办山东客户的专场活动(配图马赛克请谅解)

 

  • 举办新疆客户的专场活动(配图马赛克请谅解)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为自己_带盐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值