视频会议
This commit is contained in:
@@ -117,49 +117,74 @@ const resolveDom = (refValue) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const applyVideo = () => {
|
||||
// 当前已经贴到 video / audio 元素上的 track,用于幂等判断,避免重复 setSrcObject 触发闪烁
|
||||
let boundVideoTrack = null
|
||||
let boundAudioTrack = null
|
||||
|
||||
const applyVideo = (retry = 0) => {
|
||||
// #ifdef H5
|
||||
if (props.videoTrack && props.videoEnabled) {
|
||||
const parent = resolveDom(mediaBox.value)
|
||||
if (!parent) {
|
||||
// DOM 尚未挂载,最多重试 10 次(≈500ms)
|
||||
if (retry < 10) {
|
||||
setTimeout(() => applyVideo(retry + 1), 50)
|
||||
}
|
||||
return
|
||||
}
|
||||
const el = ensureMediaEl('video')
|
||||
if (el) {
|
||||
if (!el) return
|
||||
el.muted = props.isLocal
|
||||
if (boundVideoTrack !== props.videoTrack) {
|
||||
el.srcObject = new MediaStream([props.videoTrack])
|
||||
boundVideoTrack = props.videoTrack
|
||||
}
|
||||
const playPromise = el.play && el.play()
|
||||
if (playPromise && typeof playPromise.catch === 'function') {
|
||||
playPromise.catch(() => {})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeMediaEl('video')
|
||||
boundVideoTrack = null
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
const applyAudio = () => {
|
||||
const applyAudio = (retry = 0) => {
|
||||
// #ifdef H5
|
||||
// 本地 tile 不挂载 audio(避免回声)
|
||||
if (!props.isLocal && props.audioTrack && props.audioEnabled) {
|
||||
const parent = resolveDom(mediaBox.value)
|
||||
if (!parent) {
|
||||
if (retry < 10) {
|
||||
setTimeout(() => applyAudio(retry + 1), 50)
|
||||
}
|
||||
return
|
||||
}
|
||||
const el = ensureMediaEl('audio')
|
||||
if (el) {
|
||||
if (!el) return
|
||||
if (boundAudioTrack !== props.audioTrack) {
|
||||
el.srcObject = new MediaStream([props.audioTrack])
|
||||
boundAudioTrack = props.audioTrack
|
||||
}
|
||||
const playPromise = el.play && el.play()
|
||||
if (playPromise && typeof playPromise.catch === 'function') {
|
||||
playPromise.catch(() => {})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeMediaEl('audio')
|
||||
boundAudioTrack = null
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
watch(() => [props.videoTrack, props.videoEnabled], () => nextTick(applyVideo), { immediate: true })
|
||||
watch(() => [props.audioTrack, props.audioEnabled, props.isLocal], () => nextTick(applyAudio), { immediate: true })
|
||||
watch(() => [props.videoTrack, props.videoEnabled], () => nextTick(() => applyVideo()), { immediate: true })
|
||||
watch(() => [props.audioTrack, props.audioEnabled, props.isLocal], () => nextTick(() => applyAudio()), { immediate: true })
|
||||
|
||||
// 修复刚进入会议时画面不显示问题:
|
||||
// watch 的 immediate:true 在 setup 阶段就触发 applyVideo,此时 mediaBox ref 尚未绑定真实 DOM;
|
||||
// 即便包了 nextTick,在 uni-h5 偶发条件下仍可能命中 ref 未就绪,导致 srcObject 没贴上。
|
||||
// 这里在 onMounted 里再补一次绑定,确保 DOM ready 后必然挂上 track。
|
||||
// 修复刚进入会议时画面不显示、必须点切换才出图的问题:
|
||||
// 1) watch 的 immediate:true 在 setup 阶段就触发 applyVideo,此时 mediaBox ref 尚未绑定真实 DOM;
|
||||
// 2) 即便包了 nextTick,在 uni-h5 下 ref 偶发未就绪;
|
||||
// 现在 applyVideo/applyAudio 在 DOM 未就绪时会自动重试,并在 onMounted 再强制兜底一次。
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
applyVideo()
|
||||
|
||||
Reference in New Issue
Block a user