白板推流
更新时间: 2024/07/24 13:59:48
互动白板作为教学场景中的辅助工具之一,往往离不开和音视频一起使用。在小班课多人连麦实时音视频场景中,音视频和互动白板的数据流通过不同的数据通道传输,因此可能存在音画不同步的现象。如果使用直播方式推音视频流,学生端使用cdn,或者低延时拉流,则音视频和互动白板的时间差会更大。如何保证互动白板和音视频之间同步,成为两者同时使用时必须解决的问题。
互动白板推流
云信互动白板可以将白板中内容转化为实时视频流(MediaStream),然后通过云信的实时音视频
技术,将互动白板的视频流通过辅流推送至实时音视频房间。然后实时音服务器根据参数,可以选择是否对实时音视频和互动白板流进行混录,并推送至CDN服务器,或者进行低延时直播推送。
由于互动白板是作为辅流和实时音视频一起推送的,因此两者之间是天然同步的。具体的设计图如下所示:
成本优势
上述方案除了能够解决互动白板和音视频不同步的问题外,还降低了用户的使用成本。互动白板的计费方式为时长计费。房间内人数越多,一堂课的时长越高,一堂课的费用也会越高。使用互动白板推流方案之后,仅需要老师,或者参与互动的若干个学生加入房间即可。不需要互动的学生可以通过实时音视频、CDN拉流、或者低延时拉流的方式得到白板的内容。用户可以根据自己的需求,选择适合自己的接入方案。如果用户对于时间不敏感,则可以使用性价比最高的CDN推拉流的方案。如果用户希望延迟可以控制在2s,甚至更低,可以考虑低延时直播,或者是实时音视频互动直播。
Demo
白板直播推流可以使用智慧云课堂的直播大班课模式体验,地址为:https://yiyong.netease.im/yiyong-static/statics/wisdom-education/index.html#/
注意事项
白板推流仅支持将白板 canvas 上内容转成视频流。如果你在画布中添加视频、音频等文件,这部分内容无法通过白板推流共享。
接入
互动白板推流需要同时接入互动白板SDK,以及云信的实时音视频SDK。具体的使用到的接口如下所示:
互动白板
getStream
获取白板视频流。开发者可以使用函数的返回的视频流,通过rtc,或者其他的方式推出去。如果调用时白板正在采集视频流,则正在采集的视频流会被停止。
js/**
* 详情请参考:https://doc.yunxin.163.com/whiteboard/api-refer/web/typedoc/Latest/zh/html/interfaces/DrawPlugin.DrawPlugin-1.html#getStream
*/
getStream(opt?: { keepDPI?: boolean; width?: number }): MediaStream
const stream = drawPlugin.getStream({
keepDPI: false
})
tracks = stream.getVideoTracks()
rtc.localStream.open({
type: 'screen',
screenVideoSource: tracks[0]
})
updateStream
更新现有的stream。如果当前不存在stream,则返回一个新的stream。 如果存在stream,则直接更新现有stream的分辨率
js/**
* 详情请参考:https://doc.yunxin.163.com/whiteboard/api-refer/web/typedoc/Latest/zh/html/interfaces/DrawPlugin.DrawPlugin-1.html#updateStream
*/
updateStream(opt?: { keepDPI?: boolean; width?: number }): MediaStream
const stream = drawPlugin.updateStream({
keepDPI: false
})
tracks = stream.getVideoTracks()
rtc.localStream.open({
type: 'screen',
screenVideoSource: tracks[0]
})
stopStream
白板停止推送白板的视频数据。
关闭白板视频流。
drawPlugin.stopStream()
实时音视频
下面的接口需要使用实时音视频最新的功能,请联系网易商务获取实时音视频支持自定义辅流的版本。
createStream
初始化时开启自定义辅流
jsconst stream = drawPlugin.getStream()
tracks = stream.getVideoTracks()
rtc.localStream = NERTC.createStream({
uid, // 本端的uid
audio: true, // 是否从麦克风采集音频
video: true, // 是否从摄像头采集视频
microphoneId,
cameraId,
screen: true,
screenVideoSource: tracks[0]
})
open
初始化时如果没有开启自定义辅流,可以使用open
开启自定义辅流
jsconst stream = drawPlugin.getStream()
tracks = stream.getVideoTracks()
rtc.localStream.open({
type: 'screen',
screenVideoSource: tracks[0]
})
switchScreenStream
自定义辅流已开启,通过此接口切换屏幕共享辅流与自定义辅流。
jsconst stream = drawPlugin.getStream()
tracks = stream.getVideoTracks({
keepDPI: false
})
/**
* 切换白板作为辅流
*/
rtc.localStream.switchScreenStream({
screenVideoSource: tracks[0]
})
/**
* 切换屏幕共享作为辅流
*/
rtc.localStream.switchScreenStream({ screenAudio: false })
close
close
函数可以关闭辅流
jsrtc.localStream.close({type: 'screen'})
.then(() => {
console.log('关闭自定义辅流成功')
})
.catch(err => {
console.log('关闭自定义辅流失败', err)
})