一.项目需求:
最近做的项目里面用到通过前端flv.js拉流播放直播视频(实时视频);这里给大家介绍一下流程,首先是前端发送请求后端给返回一个直播流指定地址,然后前端把这个地址通过flv处理放到video容器中进行播放;
二.flv相关知识点
- 直播与点播:直播就是具有实时性的视频,比如我们天天看的直播,他都是现场直播的 直播有一个东西叫流数据,这个数据是实时的,他可以通过http请求拿到,也可以用websocket拿,看需求。点播就是已经整理好的视频我们直接放到video标签就可以了,一般是mp4格式,我们只要放在video标签里面浏览器就会给我们处理好一切。
- 选flv的原因:前面也说了,直播需要实时性,延迟当然越短越好,决定视频延迟的因素有好多,其中一条就是视频本身的大小,我们最常见的mp4格式的视频,对前端来说mp4兼容性是最好的,但是mp4有一个缺点就是体积比较大,解析会复杂一些,在直播场景就不能直接用mp4了,而flv不一样,他的头部文件非常小,结构简单,解析就相对比较快,在直播场景很有优势。
- 除了flv之外还有其他格式:
1)RTM:底层是基于TCP协议的,在浏览器端依赖Flash 目前浏览器是禁用Flash的, 所以不适合
2)HTTP-FLV:基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV
3)HLS:全名Http Live Streaming,苹果提出基于HTTP的流媒体传输协议。HTML5可以直接打开播放 对应的视频格式是m3u8,看过快播的兄弟应该了解这个格式,他有个致命的缺点延迟高
4)RTP:基于UDP协议,延迟1秒,浏览器不支持 基本不用 - flv又分为HTTP-FLV和Websocket-FLV,他们有啥区别呢
前面我们也提到过直播流就是实时传输,需要持续的推拉流,流数据又是实时性德,遇到这种情况我们肯定想到的是websocket 因为它就是长连接,前后端实时互传。
HTTP-Flv用的是fetch请求方法,他也是基于http的,他是一种前端向后端发送请求,获取指定的资源 他可以说是一种黑科技,他就是天生处理流数据的,性能很好,使用起来也很方便。
三.下面我们根据官网来建一个flv小demo.
官网地址:https://github.com/Bilubili/flv.js/
import flvjs from "flv.js"
if (flvjs.insupported()) {
// 获取视频容器video的dom
var videoEl = document.getElementById('videoEl');
// 配置flv播放器
var flvPlayer = flvjs.createPlayer({
type: "flv", // 媒体类型 flv或者mp4 默认flv
cors: true, // 是否跨域 用canvas截图就需要跨域
hasAudio: false, //是否有音频
hasVideo: true, // 是否有视频
// 指定流地址 可以http(https)或者ws(wss)
url: 'http://test.stream.com/fetch-media.flv',
isLive: true, //是否是直播流 默认true
})
// 挂载流 将拉到的流放进视频容器中
flvPlayer.attachMediaElement(videoEl);
// 加载流
flvPlayer.load();
// 播放流
flvPlayer.play();
}
四.细节问题处理
这里主要是我们不能使用video容器自带的暂停和播放按钮了,我们要隐藏原来的自己实现暂停和播放。暂停和播放说白了就是断流和重新拉流
// 播放和暂停实现逻辑
const onclick = isplay => {
// isplay表示视频是否正在播放
if (isplay) {
// 在播放 断流
player.unload();
player.detachMediaElement(video.current);
} else {
// 已断流,重新拉流
player.attachMediaElement(videoEl.current);
player.load();
player.play();
}
}
五.flv如何监听错误(异常)
flvjs.Events表示事件
flvjs.ErrorTypes表示一级错误
flvjs.ErrorDetails表示二级错误
一级错误又分为:
NETWORK_ERROR:网络错误,表示连接问题
MEDIA_ERROR:媒体错误,格式或解码问题
OTHER_ERROR:其他错误
二级错误分为:
NETWORK_STATUS_CODE_INVALID:http状态码错误,说明指定流的地址url地址有误
NETWORK_TIMEOUT:连接超时,后台或者网络问题
MEDIA_FORMAT_UNSUPPORTED:媒体格式不支持,一般是流数据不是flv的格式
// 监听错误事件
flvPlayer.on(flvjs.Events.ERROR, (err, errdet) => {
// err表示一级异常,errdet表示二级异常
if (err == flvjs.ErrorTypes.MEDIA_ERROR) {
console.log("媒体错误");
if (errdet == flvjs.ErrorDetails.MEDIA_FORMAT_UNSUPPORTED) {
console.log("媒体格式不支持");
}
};
if (err == flvjs.ErrorTypes.NETWORK_ERROR) {
console.log("网络错误");
if (errdet == flvjs.ErrorDetails.NETWORK_STATUS_CODE_INVALID) {
console.log("http状态码异常");
}
}
if (err == flvjs.ErrorTypes.OTHER_ERROR) {
console.log("其他异常", errdet);
}
})