1.flv格式的视频
import React, { useEffect, useRef, useState } from 'react';
import { Icon } from 'antd';
import flvjs from 'flv.js';
import cls from 'classnames';
import styles from './index.scss';
const VIDEO_MESSAGE = {
LOADING: '正在载入视频...',
FAILED: '视频载入失败',
}
export default function FlvVideo({ url }) {
const videoRef = useRef(null);
const playerRef = useRef(null);
const [msg, setMsg] = useState('');
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
// unmount时销毁
useEffect(() => {
return () => {
if (playerRef.current) {
playerRef.current.destroy();
}
}
}, []);
useEffect(() => {
if (playerRef.current) {
playerRef.current.destroy();
playerRef.current = null;
setLoading(false);
setMsg('');
}
if (url) {
const videoElement = videoRef.current;
if (flvjs.isSupported()) {
const flvPlayer = flvjs.createPlayer({
type: 'flv',
url,
isLive: true,
cors: true,
hasVideo: true,
hasAudio: false,
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
setLoading(true);
setMsg(VIDEO_MESSAGE.LOADING);
flvPlayer.play().then(() => {
console.log('[success] video loaded.');
setMsg('');
setSuccess(true);
setLoading(false);
});
flvPlayer.on(flvjs.Events.ERROR, err => {
setMsg(VIDEO_MESSAGE.FAILED);
setSuccess(false);
setLoading(false);
console.error(`[${err}] ${VIDEO_MESSAGE.FAILED}`);
});
playerRef.current = flvPlayer;
} else {
setSuccess(false);
setMsg('当前浏览器不支持播放')
}
}
}, [url]);
return <div className={cls(styles['video-view'])}>
{!success && <div className={styles.msg}>
{loading && <div><Icon type="loading" spin /></div>}
<div className={cls({ [styles.blue]: loading })}>{msg}</div>
</div>}
{!!url && <video ref={videoRef} className={cls(styles.video, {[styles.hidden]: !success })} muted controls disablePictureInPicture controlsList="nodownload">Your browser does not support HTML5 video.</video>}
</div>
}
2.m3u8
import React, { useRef, useEffect, useState } from 'react';
import Hls from 'hls.js';
import styles from './index.scss';
const VIDEO_MESSAGE = {
LOADING: '正在载入视频...',
FAILED: '视频载入失败',
RETRY: '正在尝试重新载入...',
NOT_SUPPORTED: '当前浏览器不支持播放',
NO_SOURCE: '无视频源',
};
export default function HlsVideo({ url }) {
const videoRef = useRef();
const [msg, setMsg] = useState('');
useEffect(() => {
const videoEle = videoRef.current;
if (url && videoEle) {
if (Hls.isSupported()) {
setMsg(VIDEO_MESSAGE.LOADING);
const hls = new Hls();
hls.loadSource(url);
hls.attachMedia(videoEle);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
setMsg('');
videoEle.play();
});
hls.on(Hls.Events.FRAG_PARSED, function() {
setMsg('');
});
// 简单错误处理
hls.on(Hls.Events.ERROR, function(event, data) {
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.log('fatal network error encountered, try to recover');
setMsg(VIDEO_MESSAGE.RETRY);
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.log('fatal media error encountered, try to recover');
setMsg(VIDEO_MESSAGE.RETRY);
hls.recoverMediaError();
break;
default:
hls.destroy();
setMsg(VIDEO_MESSAGE.FAILED);
break;
}
} else {
// 非 fatal 级别的错误,hls会自动重试
setMsg(VIDEO_MESSAGE.RETRY);
}
});
} else {
setMsg(VIDEO_MESSAGE.NOT_SUPPORTED);
}
} else {
// setMsg(VIDEO_MESSAGE.NO_SOURCE);
}
}, [url]);
return <div className={styles['video-view-hls']}>
{!!msg && <div className={styles.msg}>{msg}</div>}
<video
className={styles.video}
ref={videoRef}
muted
controls
disablePictureInPicture
controlsList="nodownload"
>
Your browser does not support HTML5 video.
</video>
</div>;
}