m3u8是苹果公司推出的视频播放标准,是m3u的一种,只是编码格式采用的是UTF-8。m3u8准确来说是一种索引文件,使用m3u8文件实际上是通过它来解析对应的放在服务器上的视频网络地址,从而实现在线播放。
m3u8格式的视频是将文件分成一小段一小段的ts文件,播放完一个在播放下一个,由于每次请求的ts文件都很小,所以基本可以做到无延时播放。目前WEB上主流的直播方案主要是HLS和RTMP,移动端主要是HLS,PC端主要是RTMP。
HLS是苹果推出的,移动端不管是IOS还是Android都天然支持HLS协议,直接在h5页面直接配置即可使用;PC端只有safari浏览器支持,其他浏览器均不支持。
需要借助hls插件,可以用video.js和videojs-contrib-hls.js。video.js是非常好用的插件
type:application/x-mpegURL // 告诉videojs,这是一个hls流
HLS
1、使用npm安装hls.js或者外部引入;
npm install --save hls.js
<script src="https://cdn.jsdelivr.net/npm/hls.js@1.2.7/dist/hls.js"></script>
2、使用
<template>
<div class="page">
<video controls id="video" autoplay="autoplay">
<source
type="application/x-mpegURL">
</video>
</div>
</template>
<script lang="ts">
// import HLS from 'hls.js';
import {defineComponent} from "vue";
var HLS = (window as any).Hls;
let hls = new HLS()
//声明两个变量
export default defineComponent({
methods: {
//点击播放
start(){
if (HLS.isSupported()) {
var video = <HTMLVideoElement>document.getElementById('video');
hls.attachMedia(video);
hls.loadSource('1.m3u8');
hls.on(HLS.Events.MANIFEST_PARSED, () => {
video.play();
console.log("加载成功");
});
hls.on(HLS.Events.ERROR, (event, data) => {
console.log("加载失败");
});
}
}
},
mounted(){
this.start();
}
})
</script>
3、接口
@RequestMapping("/video/{file}")
public void video( HttpServletResponse response, @PathVariable("file") String file){
try {
file = dir + file;
ServletOutputStream out = response.getOutputStream();
byte b[] = readFileToByteArray(file); //一开始固定读取1024字节,导致前端解析一直错误,应该是文件多少字节就读取多少字节内容
out.write(b);
out.flush();
} catch (Exception e){
}
}
hls.js库根据功能划分为多个controller,如abr-controller、buffer-controller、stream-controller等,每个controller任务明确,通过事件监听派发的方式完成视频流的拉取、解析、播放等。
hls.js从初始化到加载m3u8,到选择不同码率加载对应ts文件,再解码ts转为mp4最终在浏览器播放,整个过程非常复杂
主流程中有两个关键的定时器,第一个为StreamController启动用来轮询ts文件列表是否更新结束;第二个为在ts片加载过程中,用来轮询监听当前ts下载速率以动态调节不同的码率,hls.js初始默认码率为playlist的中间码率,如当前码率列表为360p、480p、720p,则初始默认取480p。
二、video.js + video.hls.js
官网:Home | Video.js Documentation
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>前端播放m3u8格式视频</title>
<!--https://www.bootcdn.cn/video.js/-->
<link href="https://cdn.bootcss.com/video.js/7.6.5/alt/video-js-cdn.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/video.js/6.6.2/video.js"></script>
<!--https://www.bootcdn.cn/videojs-contrib-hls/-->
<script src="https://cdn.bootcss.com/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js"></script>
</head>
<body>
<video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="1080" height="708" data-setup='{}'>
<source type="application/x-mpegURL"> //source 标签是设置静态资源的,如果是通过video的api动态设置文件,这标签不需要,不然会有一些问题
</video>
</body>
<script>
// videojs 简单使用
var myVideo = videojs('myVideo',{
bigPlayButton : true,
textTrackDisplay : false,
posterImage: false,
errorDisplay : false,
})
myVideo.src([
{
src: "视频.m3u8",
type: "application/x-mpegURL", // 告诉videojs,这是一个hls流
},
]);
myVideo.play() // 视频播放
myVideo.pause() // 视频暂停
</script>
</html>
或者直接使用video.js,会自动扫video元素加载
<!DOCTYPE html>
<html lang="">
<head>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
<script src="https://unpkg.com/video.js/dist/video.js"></script>
</head>
<body>
<video class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="1080" height="708" data-setup='{}'>
<source src="video.m3u8" type="application/x-mpegURL">
</video>
</body>
</html>