使用腾讯云 TRTC 实现主流和辅流视频源分开渲染
本文档基于腾讯云 TRTC SDK,详细介绍如何在 UniApp 项目中正确订阅并渲染主流视频源(Main Stream)和辅流视频源(Sub Stream)到不同的 view
组件,避免渲染覆盖问题。
问题背景
在项目中,A 端发布两个视频源(主流 A1 和辅流 A2),B 端订阅并使用两个 <view>
组件进行渲染。然而,默认实现中,主流和辅流视频源可能渲染到同一 <view>
上,并伴随控制台错误,如下图所示:
// 播放远端视频 TRTCService.js;
setRemoteVideo(view) {
this.trtcSdk.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
if (event.streamType === TRTC.TYPE.STREAM_TYPE_MAIN) {
console.log("开启主流视频源", view);
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view,
});
} else if (event.streamType === TRTC.TYPE.STREAM_TYPE_SUB) {
console.log("开启辅流视频源", view);
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view,
});
}
});
}
// vue组件中调用
this.setRemoteVideo(this.el_scan),
this.setRemoteVideo(this.el_other),
监听订阅远端视频事件里判断主流和辅流传不同的view实例,运行结果是主流和辅流视频渲染在同一个view上,控制台报错如下:
问题原因
每次触发 REMOTE_VIDEO_AVAILABLE 事件时都会调用 startRemoteVideo 方法,但由于 on事件监听器是全局的,每次调用 setRemoteVideo(view)方法时,都会为同一事件添加一个新的监听器。因此,当触发该事件时,多个监听器会被执行,导致视频源被渲染在多个视图上
解决这个问题的步骤如下:
- 在 setRemoteVideo(view) 中移除旧的监听器: 每次调用setRemoteVideo(view)时,先移除之前可能存在的监听器,防止重复监听
- 在事件监听器中判断 view 参数: 在触发事件时,根据传入的 view参数来区分主流视频源和辅流视频源,确保它们渲染到正确的视图上
代码如下:
setRemoteVideo(view) {
// 移除之前的监听器,防止重复监听
this.trtcSdk.off(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE);
this.trtcSdk.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
if (view === this.el_scan && event.streamType === TRTC.TYPE.STREAM_TYPE_MAIN) {
console.log("开启主流视频源");
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view,
});
} else if (view === this.el_other && event.streamType === TRTC.TYPE.STREAM_TYPE_SUB) {
console.log("开启辅流视频源");
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view,
});
}
});
}
运行结果:
控制台正常输出,但是主流视频源和辅流视频源还是渲染在同一个view上
继续分析:
由于两次调用 setRemoteVideo(view) 时,view 参数在 TRTC SDK内部没有正确区分,导致最后一次调用覆盖了前一次调用的效果。因此,尽管控制台只输出一次,但实际上两个视频流都渲染在了同一个 view 上
继续尝试:
- 确保每个视频流都有独立的渲染逻辑: 将主流和辅流的处理逻辑分开,避免它们在同一个 view 上覆盖
- 使用不同的事件监听器或参数区分: 可以通过将主流和辅流的视频渲染逻辑完全分离,在不同的监听器中处理它们,确保每个流都使用独立的 view
代码如下:
setRemoteVideoMain(viewMain) {
this.trtcSdk.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
if (event.streamType === TRTC.TYPE.STREAM_TYPE_MAIN) {
console.log("开启主流视频源");
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view: viewMain,
});
}
});
}
setRemoteVideoSub(viewSub) {
this.trtcSdk.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
if (event.streamType === TRTC.TYPE.STREAM_TYPE_SUB) {
console.log("开启辅流视频源");
this.trtcSdk.startRemoteVideo({
userId: event.userId,
streamType: event.streamType,
view: viewSub,
});
}
});
}
// 组件中调用
this.setRemoteVideoSub(this.el_scan),
this.setRemoteVideoMain(this.el_other),
完美解决问题,主流和辅流视频源渲染在指定的位置
注意事项
-
TRTC SDK 版本:
- 确保使用最新版本的腾讯云 TRTC SDK,并参考官方文档 TRTC Web SDK 验证
startRemoteVideo
API 的兼容性。
- 确保使用最新版本的腾讯云 TRTC SDK,并参考官方文档 TRTC Web SDK 验证
-
View 初始化:
- 确保
mainView
和subView
在 DOM 中已加载(可在mounted
钩子中验证)。 - 避免传入相同的
view
ID。
- 确保
-
性能优化:
- 避免频繁调用
initRemoteVideo
,建议在组件初始化时调用一次。 - 使用
destroy
方法清理资源,特别是在动态切换视频流时。
- 避免频繁调用
-
调试建议:
- 检查控制台日志,确认
userId
和streamType
是否正确。 - 若视频未渲染,验证
view
ID 是否匹配 DOM 元素,并检查 TRTC SDK 是否正确初始化。
- 检查控制台日志,确认