graph TD
A[初始化AliRtcEngine] --> B[生成Token]
B --> C[加入频道]
C --> D[设置本地预览]
D --> E[监听远端用户事件]
E --> F[处理订阅状态变化]
F --> G[管理视频元素生命周期]
joinChannel(): 加入音视频频道setLocalViewConfig(): 设置本地视频预览setRemoteViewConfig(): 设置远端视频渲染leaveChannel(): 离开频道AliRtcSubscribeState: 订阅状态(1:未订阅, 3:已订阅)AliRtcVideoTrack: 视频轨道类型(Camera/Screen)本地预览设置:
// 加入频道成功后设置本地预览
aliRtcEngine.current!.setLocalViewConfig(
'localPreviewer',
AliRtcVideoTrack.AliRtcVideoTrackCamera
);
视频元素管理:
使用<video id="localPreviewer">元素显示本地摄像头画面
通过muted属性静音本地音频避免回声
stateDiagram-v2
[*] --> 未订阅: 初始状态
未订阅 --> 已订阅: videoSubscribeStateChanged(3)
已订阅 --> 未订阅: videoSubscribeStateChanged(1)
已订阅 --> 创建视频元素: newState=3
未订阅 --> 移除视频元素: newState=1
创建时机:
// 当订阅状态变为3(已订阅)时创建视频元素
if (newState === 3) {
const video = document.createElement('video');
video.autoplay = true;
remoteVideoElMap.current[vid] = video;
remoteVideoContainer.current?.appendChild(video);
aliRtcEngine.current!.setRemoteViewConfig(video, userId, trackType);
}
销毁时机:
function removeRemoteVideo(userId: string, type: 'camera' | 'screen') {
aliRtcEngine.current!.setRemoteViewConfig(null, userId, trackType);
el.pause();
remoteVideoContainer.current?.removeChild(el);
delete remoteVideoElMap.current[vid];
}
处理逻辑:
移除对应的视频元素
removeRemoteVideo(userId, 'camera');
removeRemoteVideo(userId, 'screen');
userId: 远端用户IDoldState: 旧状态newState: 新状态(3:订阅成功, 1:取消订阅)核心逻辑:
if (newState === 3) {
// 创建并配置视频元素
} else if (newState === 1) {
// 移除视频元素
}
加入频道失败:
try {
await aliRtcEngine.current.joinChannel(...);
} catch (error) {
console.log('加入频道失败', error);
showToast('error', '加入频道失败');
}
全局错误监听:
通过on('bye')事件处理异常退出
通过Toast组件显示错误信息