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

如何在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适配的组件

替代方案总结

  1. 必须通过中间流媒体服务器转换协议,因为浏览器不支持直接播放UDP流
  2. 流媒体服务器选型:NGINX+RTMP(轻量易配置)、SRS(支持WebRTC,低延迟)、Janus(功能丰富的WebRTC网关)
  3. 协议选择优先级:WebRTC(最低延迟)> HTTP-FLV(低延迟)> HLS(兼容性最好,延迟稍高)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:47:03