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流
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。
官网:Home | Video.js Documentation
- html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>前端播放m3u8格式视频title>
-
- <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>
-
- <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元素加载
- 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>