React 项目中如何使用 easyPlayer-pro.js

背景

项目中要使用 easyplayer-pro.js 播放视频,查了下资料,网上基本都是 在 Vue 项目中的使用,很少有在 React 项目中使用,即使找到一篇在 React 项目中使用的记录,那也是牛头不对马嘴,前面写的是 React ,后面就是 Vue 的写法,这不扯淡嘛。

所以在经过一番努力学习验证后,写上一篇日记来记录一下,便于自己也方便大家。

EasyPlayer.js H5播放器简单介绍

不愿意看这部分的可以跳过,直接从 【下载 EasyPlayer.js】 查看。

EasyPlayer.js 简介

EasyPlayer.js H5播放器,是一款能够同时支持HTTP、HTTP-FLV、HLS(m3u8)、WS、WEBRTC、FMP4视频直播与视频点播等多种协议,支持H.264、H.265、AAC等多种音视频编码格式,支持MSE、WASM、WebCodec等多种解码方式,支持Windows、Linux、Android、iOS全平台终端的H5播放器,使用简单, 功能强大。

EasyPlayer.js 功能说明:

  • 支持 MSE H264和H265硬解码;
  • 支持 WebCodec H264和H265硬解码;
  • 支持 WASM H264和H265硬解码/软解码;
  • 支持 m3u8/HLS (H265/H265)播放;
  • 支持 Mpeg4格式(H264)播放;
  • 支持 HTTP-FLV/WS-FLV (H265/H265)播放;
  • 支持 HTTP-FMP4/WS-FMP4 (H265/H265)播放;
  • <支持 WEBRTC(easy支持H264/H265、其他流媒体支持H264)播放;
  • 支持 裸流(H264/H265) 播放;
  • 支持 直播和点播播放;
  • 支持 点播多清晰度播放;
  • 支持 全屏或比例显示;
  • 支持 电子放大;
  • 支持 水印(动态水印、幽灵水印);
  • 支持 显示上一个视频最后一帧;
  • 支持 播放器快照截图;
  • 支持 视频录制(WebM格式(音频+视频)、Mp4格式(视频),Flv格式(音频+视频));
  • 支持 超时、断网重连、异常暂停播放等

额外介绍:这个仅支持 Vue 和 普通引入使用。

配置属性

参数说明类型默认值
container播放器容器--
decoderwasm解码地址String-
isResize是否拉伸Booleantrue
loadingText加载显示的文字String加载中
videoBuffer加载显设置最小缓冲时长,单位秒,播放器会自动消除延迟。示的文字Number1
hasAudio是否解析音频Booleantrue
useMSEMSE模式Booleanfasle
useWCSWCS模式Booleanfasle
useSIMD强制使用wasm模式Booleanfalse
background视频封面图片String-
qualityConfig配置清晰Array[‘普清’, ‘高清’, ‘超清’, ‘4K’, ‘8K’]
defaultStreamQuality默认显示的清晰度,如果不设置,会显示第一个清晰度String-
isNotMute是否渲染音频Booleanfalse
recordType视频录制默认mp4格式Stringmp4,flv
playbackForwardMaxRateDecodeIFrame录像倍数Number-
debug控制台日志打印Boolean false
debugLevel打印日志级别默认warnStringdebug,warn

事件回调

事件名说明
play播放事件
pause暂时事件
videoInfo视频信息
audioInfo音频信息
mute音频
error播放异常
kBps当前网速, 单位KB 每秒1次,
recordEnd录制结束的事件
recordStart录制开始的事件
fullscreen当前是否全屏
streamQualityChange清晰度回调
playbackSeek录像时间轴跳转回调
playbackPreRateChange录像倍数的回调
currentPts监听当前渲染帧的时间戳(流里面的)

方法

方法名说明参数
play播放‘url’
playback播放录像
pause暂停播放
isPause返回是否暂停中状态
setBufferTime设置最大缓冲时长 1
setVolume设置音量
getVolume获取音量
exitFullscreen退出全屏
mute静音
cancelMute取消静音
isMute返回是否静音
screenshot获取快照
setFullscreen全屏(取消全屏)播放视频
setStreamQuality设置分辨率必须是qualityConfig里面的数据
forward设置录像倍数
setPlaybackStartTime设置录像跳转时间/s
getVideoInfo获取视频信息
getAudioInfo获取音频信息
destroy关闭视频,释放底层资源

在这里插入图片描述

下载 EasyPlayer.js

按照下面的地址去下载下来,简单。

EasyPlayer.js 访问地址

引入使用

  1. 将下载的文件拷贝到 React 项目的 public 目录下

    注意:不能拷贝到其他文件,只能在这里,有兴趣的同学也可以尝试一下其他地址

    在这里插入图片描述

  2. 然后在 index.html 文件中引入 easyplayer-pro.js

    <!DOCTYPE html>
    <html lang="en">
    	<head>
    		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
    		<meta charset="utf-8" />
    		<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    		<title>你的爱豆</title>
    	</head>
    
    	<body>
    	
    		<!-- easyplayer-pro.js 文件 -->
    		<script type="text/javascript" src="./js/easyplayer-pro.js"></script>
    		
    		<!-- react 挂载根节点 -->
    		<div id="root"></div>
    	
    	</body>
    	
    	<script>
    		// 将 EasyPlayerPro 挂载到 window 上,便于全局使用
    		window.EasyPlayerPro = EasyPlayerPro;
    	</script>
    </html>
    
    
  3. 将下载的文件再次拷贝一份到需要使用的组件下

    在这里插入图片描述

  4. 创建视频播放组件,并在组件中添加播放内容

import React, { useEffect, useImperativeHandle, useRef } from "react";
import { Button, Icon, Modal } from "antd";
import { useState } from "react";

// 根据自己的需要定义样式
import './index.less';

// 调用接口
import { getVideoManagerPlay } from "server/video.api";

const _myWindow:any = window;

const EasyPlayerVideoDialog = ({onRef}:any) => {

    const easyPlayerRef:any = useRef(null);

    const [open, setOpen] = useState<boolean>(false);
    const [videoUrl, setVideoUrl] = useState<string>('');
    

    useImperativeHandle(onRef, () => ({
        showModal: (record:any) => {
            
            const {deviceId} = record;
            getVideoUrlFn(deviceId);
            
            setOpen(true);
        }
    }));


    // 获取播放视频地址
    const getVideoUrlFn = async (deviceId:string|undefined) => {
        if (!deviceId) return;
        
        try {
            const params = {
                deviceId,
            };
            const res = await getVideoManagerPlay(params);
            const {code, data}:any = res;
            if (code === 200 && data && typeof data === 'string' && data.length > 0) {
                setVideoUrl(data);
            } else {
                setVideoUrl(''); 
            }
            
        } catch (error) {
            setVideoUrl('');
        }
    };


    useEffect(() => {
        if (!videoUrl) return;
        playCreate();
    }, [videoUrl])


    const playCreate = () => {

        const EasyPlayerPro = _myWindow?.['EasyPlayerPro'];

        if (EasyPlayerPro) {

			// 可以根据自己的需要自行配置
            const easyplayer = new EasyPlayerPro({
                container: document.getElementById('player_box1'),
				
				// 这里需要注意,根据自己打包需求设定
                decoder: process.env.NODE_ENV === 'development' ? './js/decoder-pro.js' : './static/js/easyPlayerPro/decoder-pro.js',  // wasm解码地址
                videoBuffer: 2, // 加载显设置最小缓冲时长,单位秒,播放器会自动消除延迟。
                isResize: false, // 是否拉伸
                text: "",
                loadingText: "加载中",
                // debug: true,
                // debugLevel: 'debug',
                useMSE: true, // MSE模式
                useWCS: true, // WCS模式
                isMulti: true,
                useSIMD: false, // 强制使用wasm模式
                hasAudio: true, // 是否解析音频
                showBandwidth: false, // 显示网速
                showPerformance: false,
                operateBtns: {
                    fullscreen: true,
                    screenshot: true,
                    play: true,
                    audio: true,
                    record: true,
                    quality: true,
                    performance: true,
                },
                watermarkConfig: {
                text: {
                    content: ''
                },
                right: 10,
                top: 10
                },
                playbackForwardMaxRateDecodeIFrame: 1,
                isWebrtcForOthers:true,
                demuxUseWorker: true,
                supportHls265:true,
            });

			// 一些监听事件
            easyplayer.on("fullscreen", function (flag:any) {
                console.log('is fullscreen', flag)
            })

            easyplayer.on('playbackPreRateChange', (rate:any) => {
                easyplayer.forward(rate);
            })

            easyplayer.on('playbackSeek', (data:any) => {
                easyplayer.setPlaybackStartTime(data.ts);
            })

            if (easyPlayerRef.current) easyPlayerRef.current = null;
            easyPlayerRef.current = easyplayer;

            // 开启自动播放
            easyplayer.play(videoUrl);
        }
    }

	// 隐藏弹框重置数据
    const onCancelFn = () => {
        easyPlayerRef.current?.pause();
        easyPlayerRef.current?.destroy();
        easyPlayerRef.current = null;
        setVideoUrl('');
        setOpen(false);
    };

    return (
        <Modal
            className="easyPlayerModal"
            // title="视频监控"
            getContainer={false}
            visible={open}
            footer={null}
            width={1200}
            centered={true}
            maskClosable={true}
            onCancel={onCancelFn}
        >
            <div className="easy-player-wrp">
                <div className="easy-player-box" id="player_box1"/>
            </div>

        </Modal>
    )
};

export default EasyPlayerVideoDialog;

重写webpack

因为我项目中使用 customize-cra 插件,根据插件要求,在项目根目录创建 config-overrides.js 文件重写 webpack 配置。

点击此处可以查看 customize-cra 插件 的所有api及相关解释。

// 引入插件 customize-cra
const {
  override,
  fixBabelImports,
  addLessLoader,
  addWebpackPlugin,
  addWebpackAlias,
  disableEsLint,
  setWebpackOptimizationSplitChunks,
  useBabelRc,
  addBundleVisualizer,
  adjustWorkbox,
  overrideDevServer,
} = require('customize-cra');

// 引入css分离插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 下载拷贝文件插件
const CopyWebpackPlugin = require('copy-webpack-plugin');


// 输出文件配置
const appBuildOutput = () => (config) => {
	// 可以根据环境自定义配置输出文件
	
	switch(process.env.NODE_ENV){
		case 'development':
			break;
		case 'product':
			// 关闭sourceMap
		    config.devtool = false;
			
			// 更改生产模式输出的文件名
		    // main.js 不带hash
		    // 按需引入的文件带有hash
		    config.output = {
		      ...config.output,
		      path: paths.appBuild,
		      filename: 'static/js/[name].js',
		      chunkFilename: 'static/js/[name].[contenthash:8].chunk.js',
		    };
		    
		    config.optimization.runtimeChunk = false;

			// 针对 css 拆包
		    config.plugins.forEach((item, index, self) => {
		      if (item instanceof MiniCssExtractPlugin) {
		        self[index] = new MiniCssExtractPlugin({
		          filename: 'static/css/[name].css',
		          chunkFilename: 'static/css/[name].[contenthash:4].chunk.css',
		          ignoreOrder: true,
		        });
		      }
		    });

			// 拷贝 easyPlayer-pro.js到指定目录
			config.plugins.push(
		      new CopyWebpackPlugin(
		        [
		          {
		            from: 'public/js/*.js', // 指定public目录下js文件夹中的所有.js文件
		            to: 'static/js/easyPlayerPro/[name].[ext]', // 指定目标路径,[name]和[ext]是文件名和扩展名的占位符
		          },
		        ]
		      )
		    );
			break;
		// 其他...
	}
	
}


module.exports = {
  	webpack: override(
		// 其他配置...
		appBuildOutput(),
	),
	devServer: overrideDevServer((config) => {
		return {
			...config
			// 其他配置...
		}
	})
}

到这里就结束了吗,就能够正常运行了吗,不一定,请接着往下看。

在这里插入图片描述

问题处理

将打包好的文件放到线上测试环境部署,一运行就报如下错误,这是个啥呀,点击进去一看,都到人家的插件里面去了,那铁定不能去改啊,对吧,那就是我们自身的代码出了问题,继续排查排查。

在这里插入图片描述

经过不断地努力排除,最终定位到 easyPlayer-pro.js 解码视频还需要一个二进制的文件,这个文件没有拷贝进去,所以继续如下操作即可。

经过查找,缺失的这个二进制文件就是以 *.wasm 结尾的文件,问题找到了,那么只要将这个文件在打包的时候拷贝进去就好,所以继续修改我们的 config-overrides.js 文件。
在这里插入图片描述

// 其他...

// 拷贝 easyPlayer-pro.js到指定目录
config.plugins.push(
	new CopyWebpackPlugin(
		[
			// ********** 原来的 **********
			{
				from: 'public/js/*.js', // 指定public目录下js文件夹中的所有.js文件
				to: 'static/js/easyPlayerPro/[name].[ext]', // 指定目标路径,[name]和[ext]是文件名和扩展名的占位符
			},
			
			// ********** 重要 **********
			// 新增:一定要拷贝这里的 *.wasm 格式的文件,否则播放视频一定报错
			{
				from: 'public/js/*.wasm', // 指定public目录下js文件夹中的所有.wasm文件
				to: 'static/js/easyPlayerPro/[name].[ext]', // 指定目标路径,[name]和[ext]是文件名和扩展名的占位符
			}
		]
	)
);

// 其他...

证清白

在这里插入图片描述

因项目保密,就只展示这么一部分。

最后

关于在 React 项目中引用 EasyPlayer.js 到这里就结束了,希望能够对有需要的朋友一些帮助。

如果这篇文章对你还有点儿作用,麻烦点赞,搜藏,如果有哪里不对,可以评论,私信

在这里插入图片描述

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值