diff --git a/src/index.js b/src/index.js index a346d0d..84511c2 100644 --- a/src/index.js +++ b/src/index.js @@ -673,8 +673,10 @@ class WebRTCChat { overlay.style.backgroundImage = `url(${frameData})`; overlay.style.backgroundSize = 'cover'; overlay.style.backgroundPosition = 'center'; + overlay.style.backgroundRepeat = 'no-repeat'; overlay.style.zIndex = '10'; overlay.style.pointerEvents = 'none'; + overlay.style.willChange = 'auto'; // 优化渲染性能 overlay.id = 'video-frame-overlay'; return overlay; @@ -699,6 +701,9 @@ class WebRTCChat { if (frameData) { frameOverlay = this.createFrameOverlay(frameData); currentVideo.parentElement.appendChild(frameOverlay); + + // 确保覆盖层立即显示 + frameOverlay.offsetHeight; // 强制重绘 } // 3. 检查是否已缓存 @@ -724,11 +729,14 @@ class WebRTCChat { // 5. 在缓冲视频元素中预加载新视频 bufferVideo.srcObject = newStream; - // 6. 等待新视频完全准备好(至少渲染一帧) + // 6. 增强的视频准备检测 await new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('视频加载超时')); - }, 5000); + }, 8000); // 增加超时时间到10秒 + + let frameCount = 0; + const minFrames = 8; // 增加到8帧确保更稳定的切换 const onReady = () => { clearTimeout(timeout); @@ -741,16 +749,39 @@ class WebRTCChat { const onCanPlay = () => { // 开始播放新视频 bufferVideo.play().then(() => { - // 等待至少一帧渲染 - if (bufferVideo.currentTime > 0) { - onReady(); - } + // 等待多帧渲染确保稳定 + const checkFrames = () => { + if (bufferVideo.currentTime > 0) { + frameCount++; + if (frameCount >= minFrames) { + // 额外等待三个渲染周期确保完全稳定 + requestAnimationFrame(() => { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + onReady(); + }); + }); + }); + } else { + requestAnimationFrame(checkFrames); + } + } else { + requestAnimationFrame(checkFrames); + } + }; + requestAnimationFrame(checkFrames); }).catch(reject); }; const onTimeUpdate = () => { if (bufferVideo.currentTime > 0) { - onReady(); + frameCount++; + if (frameCount >= minFrames) { + // 额外等待确保帧稳定 + setTimeout(() => { + onReady(); + }, 100); // 增加等待时间到100ms + } } }; @@ -771,26 +802,58 @@ class WebRTCChat { } }); - // 7. 立即切换视频显示(无过渡) + // 7. 三重确认新视频已准备好 + await new Promise(resolve => { + let confirmCount = 0; + const maxConfirms = 5; // 增加确认次数 + + const finalCheck = () => { + if (bufferVideo.readyState >= 2 && bufferVideo.currentTime > 0) { + confirmCount++; + if (confirmCount >= maxConfirms) { + // 再等待三个渲染周期确保完全准备好 + requestAnimationFrame(() => { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + resolve(); + }); + }); + }); + } else { + requestAnimationFrame(finalCheck); + } + } else { + requestAnimationFrame(finalCheck); + } + }; + finalCheck(); + }); + + // 8. 立即切换视频显示(无过渡) bufferVideo.style.zIndex = '2'; currentVideo.style.zIndex = '1'; - // 8. 移除静态帧覆盖层 + // 9. 延迟移除静态帧覆盖层(进一步增加显示时长) if (frameOverlay) { - frameOverlay.remove(); + // 等待更长时间确保新视频完全显示 + setTimeout(() => { + if (frameOverlay && frameOverlay.parentElement) { + frameOverlay.remove(); + } + }, 300); // 增加到300ms } - // 9. 隐藏加载指示器 + // 10. 隐藏加载指示器 if (!isCached) { this.hideVideoLoading(); } - // 10. 更新状态 + // 11. 更新状态 this.currentVideoStream = newStream; this.currentVideo = videoFile; this.activeVideoElement = this.activeVideoElement === 'main' ? 'buffer' : 'main'; - // 11. 延迟清理旧视频流 + // 12. 延迟清理旧视频流 setTimeout(() => { if (currentVideo.srcObject && currentVideo.srcObject !== newStream) { currentVideo.srcObject.getTracks().forEach(track => track.stop()); @@ -798,7 +861,7 @@ class WebRTCChat { } }, 1000); - // 12. 更新WebRTC连接 + // 13. 更新WebRTC连接 if (this.peerConnection && this.videoSender) { const newVideoTrack = newStream.getVideoTracks()[0]; if (newVideoTrack) { @@ -806,7 +869,7 @@ class WebRTCChat { } } - // 13. 更新显示信息 + // 14. 更新显示信息 if (text) { this.currentVideoName.textContent = `交互视频: ${videoFile} (${type}: ${text})`; this.logMessage(`成功切换到交互视频流: ${videoFile} (${type}: ${text})`, 'success');