如何使video标签可以支持播放flv,fmp4,WebRTC三种格式

在H5中新增的video标签使得我们可以直接在浏览器中播放视频,但有些视频格式却不支持直接利用video的src属性进行播放,比如上述三种格式中的flv和webrtc格式。要使 HTML 的 <video> 标签支持播放 FLV 和 WebRTC 格式的视频,我们需要使用一些额外的技术和库,下面是三种播放格式配合video标签的具体实现代码,由于我目前使用的框架为react,所以下面代码实现均为React + TS。

  1. 播放 FLV 格式:

    • 使用 JavaScript 库,如 flv.js,它允许在不支持 Flash 的浏览器中播放 FLV 视频。
    • <video> 标签与 flv.js 结合使用,该库可以接收 FLV 流并通过 Media Source Extensions (MSE) API 在浏览器中播放。
import 复制代码
import flv from 'flv.js';

const FLVPlayer = ({ url }) => {
    const videoRef = useRef(null);

    useEffect(() => {
        if (flv.isSupported()) {
            const flvPlayer = flv.createPlayer({
                type: 'flv',
                url: url
            });
            flvPlayer.attachMediaElement(videoRef.current);
            flvPlayer.load();

            return () => {
                flvPlayer.destroy();
            };
        }
    }, [url]);

    return <video ref={videoRef} controls style={{ width: '100%' }} />;
};

export default FLVPlayer;
  1. 播放 FMP4 (Fragmented MP4) 格式:

    • FMP4 通常与 Adaptive Streaming 如 HLS 或 DASH 结合使用。
    • 可以使用如 hls.jsdash.js 等库来播放这种格式的视频。
    • 这些库使用 MSE API 在浏览器中播放分段的 MP4 文件。

示例基于hls.js实现

import 复制代码
import Hls from 'hls.js';

const FMP4Player = ({ url }) => {
    const videoRef = useRef(null);

    useEffect(() => {
        const hls = new Hls();
        hls.loadSource(url);
        hls.attachMedia(videoRef.current);

        return () => {
            hls.destroy();
        };
    }, [url]);

    return <video ref={videoRef} controls style={{ width: '100%' }} />;
};

export default FMP4Player;
  1. 播放 WebRTC 格式:

WebRTC 的实现更加复杂,因为它涉及到实时通信。想做到通过webrtc实现视频的播放,首先需要服务端部署信令服务,按照客户端通过 RTCPeerConnection 实例的 createOffer 方法生成媒体描述并监听 track 事件,将生成的客户端媒体描述给到服务端去换取服务端生成的媒体描述,然后将换取后的服务端生成的媒体描述给到 客户端的RTCPeerConnection 会自动触发 track事件,在触发的 track 事件中可以获取媒体流,此时将媒体流给到 video 的 srcObject 属性就可以通过 webRtc 实现视频播放。

下面示例是基于已经获取到媒体流的情况下去实现的,具体如何获取媒体流较为复杂,后面会出一起详细的讲解如何获取。

import 复制代码
const WebRTCPlayer = ({ stream }) => {
    const videoRef = useRef(null);

    useEffect(() => {
        if (videoRef.current) {
            videoRef.current.srcObject = stream;
        }
    }, [stream]);

    return <video ref={videoRef} autoPlay controls style={{ width: '100%' }} />;
};

export default WebRTCPlayer;

上面我们已经将三种视频格式分别进行实现,下面我们只需要将上面三种格式都整合到一个组件中去进行使用,并且用type字段来判断当前具体需要使用哪种播放格式来进行对应的处理就好。

import 复制代码
import flv from 'flv.js'; 
import Hls from 'hls.js'; 

// 定义组件的 props 类型
type Props = {
  url: string; 
  type: 'flv' | 'fmp4' | 'webrtc'; 
  stream?: MediaStream; // WebRTC 的媒体流(仅当类型为 webrtc 时使用)
};

const VideoPlayer: React.FC<Props> = ({ url, type, stream }) => {
  const videoRef = useRef<HTMLVideoElement>(null); // 使用 useRef 创建对 video 元素的引用

  useEffect(() => {
    let player; // 用于存储播放器实例

    // 根据视频类型来初始化不同的播放器
    if (type === 'flv' && flv.isSupported()) {
      // 对于 FLV 格式,使用 flv.js
      player = flv.createPlayer({
        type: 'flv',
        url: url,
      });
      player.attachMediaElement(videoRef.current!); // 将视频元素绑定到播放器
      player.load(); // 加载视频
    } else if (type === 'fmp4' && Hls.isSupported()) {
      // 对于 FMP4 格式,使用 hls.js
      player = new Hls();
      player.loadSource(url); // 加载视频源
      player.attachMedia(videoRef.current!); // 将视频元素绑定到播放器
    } else if (type === 'webrtc' && stream) {
      // 对于 WebRTC,直接将 MediaStream 绑定到 video 元素
      videoRef.current!.srcObject = stream;
    }

    // 组件卸载时销毁播放器
    return () => {
      if (player) {
        player.destroy();
      }
    };
  }, [url, type, stream]); 

  
  return <video ref={videoRef} controls autoPlay style={{ width: '100%' }} />;
};

export default VideoPlayer;

使用方法

在其他组件中使用 VideoPlayer 组件时,您需要根据视频类型传入相应的 urlstream。例如:

import 复制代码
// FLV 示例
<VideoPlayer url="path/to/your.flv" type="flv" />

// FMP4 示例
<VideoPlayer url="path/to/your.m3u8" type="fmp4" />

// WebRTC 示例
// 假设 `webrtcStream` 是一个 MediaStream 对象
<VideoPlayer type="webrtc" stream={webrtcStream} />

但要注意的是,这个组件是基于我们已经有了 WebRTC 的 MediaStream 对象来实现的,如果没有获取到WebRTC 的 MediaStream对象,当前组件是无法直接播放WebRTC格式的。

相关推荐
10年前端老司机2 分钟前
React 受控组件和非受控组件区别和使用场景
前端·javascript·react.js
夏晚星3 分钟前
vue实现微信聊天emoji表情
前端·javascript
停止重构5 分钟前
【方案】前端UI布局的绝技,响应式布局,多端适配
前端·网页布局·响应式布局·grid布局·网页适配多端
極光未晚5 分钟前
TypeScript在前端项目中的那些事儿:不止于类型的守护者
前端·javascript·typescript
ze_juejin6 分钟前
Vue3 + Vite + Ant Design Vue + Axios + Pinia 脚手架搭建
前端·vue.js
lichenyang4538 分钟前
React项目(移动app)
前端
用户61848240219519 分钟前
Vue-library-start,一个基于Vite的vue组件库开发模板
前端
美团技术团队21 分钟前
报名 | 美团技术沙龙第86期:多业务场景下,美团如何做性能优化
前端
安替-AnTi1 小时前
基于 React 和 TypeScript 搭建的机器学米其林餐厅数据分析项目
react.js·typescript·数据分析·毕设·米其林
Rrvive1 小时前
localhost 和 127.0.0.1 的核心区别
前端