如何在React.js应用中用FFmpeg与JavaScript显示组播视频流?
可行性与解决方案
直接在浏览器中播放udp://协议的MPEG-TS流不可行,因为浏览器的安全模型和API限制不支持直接访问UDP网络资源,这也是你用video.js报错的核心原因——你错误地将UDP地址标记为HLS(HTTP Live Streaming)源,而HLS是基于HTTP的流媒体协议,和UDP完全不兼容。
为什么之前的代码失败?
- 浏览器没有内置的UDP媒体流解析能力,无法直接加载
udp://开头的资源 - 你在video.js的配置中指定了
type: "application/x-mpegURL"(HLS格式),但实际推流是MPEG-TS over UDP,格式不匹配导致播放失败
正确实现方式:中间服务转协议
最通用的解决方案是部署一个流媒体服务器,接收UDP组播的MPEG-TS流,将其转成浏览器支持的协议(如HTTP-FLV、HLS、WebRTC),再在React应用中播放转换后的流。
方案1:用NGINX+RTMP模块转流
NGINX是轻量的服务器,配合rtmp模块可以快速完成协议转换。
步骤1:配置NGINX
添加以下配置片段(需先安装nginx-rtmp-module):
rtmp { server { listen 1935; application live { live on; # 拉取你的UDP组播流 pull udp://235.235.235.235:12345; # 开启HTTP-FLV输出(低延迟) flv_live on; # 开启HLS输出(兼容性好,延迟稍高) hls on; hls_path /usr/local/nginx/html/hls; hls_fragment 1s; hls_playlist_length 3s; } } } http { server { listen 8080; # 提供HTTP-FLV访问路径 location /flv { flv_live on; chunked_transfer_encoding on; } # 提供HLS访问路径 location /hls { types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /usr/local/nginx/html; add_header Cache-Control no-cache; } } }
步骤2:在React中播放转换后的流
方式A:用flv.js播放HTTP-FLV(低延迟)
import React, { useEffect, useRef } from 'react'; import flvjs from 'flv.js'; const VideoPlayer = () => { const videoRef = useRef(null); let flvPlayer = null; useEffect(() => { if (flvjs.isSupported()) { const videoElement = videoRef.current; flvPlayer = flvjs.createPlayer({ type: 'flv', url: 'http://localhost:8080/flv/live' }); flvPlayer.attachMediaElement(videoElement); flvPlayer.load(); flvPlayer.play(); } return () => { flvPlayer?.destroy(); }; }, []); return ( <div> <video ref={videoRef} controls autoPlay muted className="video-player" /> </div> ); }; export default VideoPlayer;
方式B:用video.js播放HLS(兼容性好)
import React, { useEffect, useRef } from 'react'; import videojs from 'video.js'; import 'video.js/dist/video-js.css'; const VideoPlayer = () => { const videoRef = useRef(null); let player = null; useEffect(() => { const videoElement = videoRef.current; player = videojs(videoElement, { controls: true, autoplay: true, muted: true, sources: [{ src: 'http://localhost:8080/hls/live.m3u8', type: 'application/x-mpegURL' }] }); return () => { player?.dispose(); }; }, []); return ( <div> <video ref={videoRef} className="video-js vjs-default-skin" /> </div> ); }; export default VideoPlayer;
方案2:改用WebRTC推流(最低延迟)
WebRTC是浏览器原生支持的实时流媒体协议,延迟可以控制在几百毫秒内,适合对延迟敏感的场景。可以用SRS这类支持WebRTC的流媒体服务器,修改FFmpeg推流命令为WebRTC格式:
步骤1:FFmpeg推流命令修改
ffmpeg -f dshow -i video="HP Wide Vision HD Camera" -profile:v high -pix_fmt yuvj420p -level:v 4.1 -preset ultrafast -tune zerolatency -vcodec libx264 -r 10 -b:v 512k -s 640x360 -acodec aac -ac 2 -ab 32k -ar 44100 -f webrtc -flush_packets 0 rtc://localhost:1985/live/stream
步骤2:React中用WebRTC接收流
import React, { useEffect, useRef } from 'react'; const VideoPlayer = () => { const videoRef = useRef(null); let pc = null; useEffect(() => { const videoElement = videoRef.current; pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }); // 接收流并绑定到video元素 pc.ontrack = (event) => { videoElement.srcObject = event.streams[0]; }; // 向SRS服务器请求播放会话 fetch('http://localhost:1985/rtc/v1/play/?stream=live/stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api: 'offer' }) }) .then(res => res.json()) .then(data => pc.setRemoteDescription(new RTCSessionDescription(data.offer))) .then(() => pc.createAnswer()) .then(answer => pc.setLocalDescription(answer)) .then(() => { return fetch('http://localhost:1985/rtc/v1/play/?stream=live/stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ api: 'answer', answer: pc.localDescription }) }); }) .catch(err => console.error('WebRTC连接失败:', err)); return () => { pc?.close(); }; }, []); return ( <div> <video ref={videoRef} autoPlay muted controls /> </div> ); }; export default VideoPlayer;
可用的现成库
- flv.js:专门处理HTTP-FLV流,体积小,延迟低,适合实时场景
- video.js:配合
videojs-flvjs或videojs-contrib-hls插件,支持多种流媒体协议,生态完善 - react-player:React友好的播放器封装,支持HLS、FLV、WebRTC等多种格式
- simple-peer:轻量WebRTC库,适合自定义WebRTC流的收发逻辑
- Janus Gateway SDK:如果使用Janus作为流媒体服务器,提供了React适配的组件
替代方案总结
- 必须通过中间流媒体服务器转换协议,因为浏览器不支持直接播放UDP流
- 流媒体服务器选型:NGINX+RTMP(轻量易配置)、SRS(支持WebRTC,低延迟)、Janus(功能丰富的WebRTC网关)
- 协议选择优先级:WebRTC(最低延迟)> HTTP-FLV(低延迟)> HLS(兼容性最好,延迟稍高)
内容的提问来源于stack exchange,提问作者OmriHalifa
相关产品推荐
相关产品推荐

