You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+PeerJs视频通话构建报错:play()请求被新加载请求中断

React+PeerJs视频聊天应用Chrome播放错误解决方案

错误现象

使用React结合PeerJs开发视频聊天应用时,在Chrome浏览器发起或接收视频通话时,出现以下错误:

Uncaught (in promise) DOMException: The play() request was interrupted by a new load request

尝试过改用navigator.mediaDevices.getUserMedia的then链式调用、用getElementById替代useRef获取元素,问题仍未解决。

错误含义与产生原因

错误含义

该错误表示:视频元素的play()请求正在处理过程中,元素的数据源(如srcObject)被重新加载/替换,导致正在进行的播放请求被强制中断,从而抛出DOM异常。

产生原因

  1. 重复调用play():代码中存在多次调用同一视频元素play()的情况(例如原代码中myVideoPromise.then回调里再次调用play()),前一次play请求还未完成,后一次又触发,导致冲突。
  2. 未等待视频就绪就播放:设置srcObject后立即调用play(),此时视频元数据尚未加载完成,浏览器还未准备好播放,后续数据源的微小变更就会中断播放请求。
  3. DOM操作与React生命周期冲突:直接使用getElementById操作DOM,脱离React虚拟DOM的管控,可能导致元素状态被意外覆盖,引发数据源重复设置。

修复方案

  1. 避免重复调用play():每个视频元素仅调用一次play(),且要确保在数据源设置完成后执行。
  2. 使用React useRef管理视频元素:适配React组件生命周期,避免DOM操作与虚拟DOM的冲突。
  3. 等待视频元数据加载完成再播放:监听视频元素的loadedmetadata事件,确保视频就绪后再触发播放。
  4. 正确处理play的Promise:捕获play可能抛出的异常,避免未处理的Promise错误。

修正后的代码示例

组件内定义useRef

import { useRef } from 'react';

// 在组件内部声明视频元素的ref
const myVideoRef = useRef(null);
const remoteVideoRef = useRef(null);

接收通话逻辑

peer.on('call', (call) => {
  if (navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({ 
      audio: true, 
      video: { width: 1280, height: 720 } 
    })
    .then((stream) => {
      // 设置本地视频流并监听就绪事件
      if (myVideoRef.current) {
        myVideoRef.current.srcObject = stream;
        myVideoRef.current.addEventListener('loadedmetadata', () => {
          myVideoRef.current.play().catch(err => {
            console.error("本地视频播放失败:", err);
          });
        });
      }

      call.answer(stream);
      call.on('stream', (remoteStream) => {
        // 设置远程视频流并监听就绪事件
        if (remoteVideoRef.current) {
          remoteVideoRef.current.srcObject = remoteStream;
          remoteVideoRef.current.addEventListener('loadedmetadata', () => {
            remoteVideoRef.current.play().catch(err => {
              console.error("远程视频播放失败:", err);
            });
          });
        }
      });
    })
    .catch(err => {
      console.error("获取媒体流失败:", err);
    });
  }
});

发起通话逻辑

const videoCall = () => {
  if (navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({ 
      audio: true, 
      video: { width: 1280, height: 720 } 
    })
    .then((stream) => {
      // 设置本地视频流并监听就绪事件
      if (myVideoRef.current) {
        myVideoRef.current.srcObject = stream;
        myVideoRef.current.addEventListener('loadedmetadata', () => {
          myVideoRef.current.play().catch(err => {
            console.error("本地视频播放失败:", err);
          });
        });
      }

      const call = peer.call(myconnection.friendId, stream);
      call.on('stream', (remoteStream) => {
        // 设置远程视频流并监听就绪事件
        if (remoteVideoRef.current) {
          remoteVideoRef.current.srcObject = remoteStream;
          remoteVideoRef.current.addEventListener('loadedmetadata', () => {
            remoteVideoRef.current.play().catch(err => {
              console.error("远程视频播放失败:", err);
            });
          });
        }
      });
    })
    .catch(err => {
      console.error("获取媒体流失败:", err);
    });
  }
};

页面中的视频元素

{/* 本地视频:添加muted规避自动播放限制,playsInline适配移动端 */}
<video ref={myVideoRef} muted playsInline />
{/* 远程视频 */}
<video ref={remoteVideoRef} playsInline />

内容的提问来源于stack exchange,提问作者Qih Se

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:01:23