流媒体视频网站开发入门之m3u8

2021年4月14日 0 条评论 4.1k 次阅读 0 人点赞

偶然间接触到直播,才得以了解以 m3u8 后缀的文件格式,用一句话来说,刚入门 web 开发的同学做视频网站可能会误用 video 标签,就好像下面的代码。

<video src="https://xxxx.mp4"></video>

为什么说是误用呢?因为当 mp4 格式的文件一大,我们必须要在前端加载完整个文件才能进行下一步的播放。

其实我们能发现,所有视频网站都不是这么整的,如果打开 F12 调试窗口去几个视频网站,我们会发现许多都是使以 m3u8 形式的后缀链接。

这大概是个什么情况呢?我后续直接动手一探究竟。

先来看看 m3u8 文件中的内容,如下所示

我们可以看红色方框圈出来的部分,会发现这里有很多为 out00x.ts 形式的内容。

其实这 .ts 是大视频切分出来的视频分片。

这是一条 linux 命令展示的图片

图中我们将 1.mp4 这个文件使用工具拆分成 out000.ts - out012.ts 的分片,最后用 out.m3u8 文件去索引这些分片。这么说你可能就稍微有点理解了吧?

假设该视频的长度为 2 分钟,那么这12个.ts后缀的分片,每一个分片占据的视频长度就是 2*60/12=10秒。

而我们在 video 标签中使用的 m3u8 就代表着这12个文件的索引(如下图所示)

当视频播放时,他会自动取请求该视频分片。如下图所示

但是怎么将mp4转换成m3u8呢?此时就引出了 ffmpeg 软件

在 linux 下安装该转换软件,并执行以下命令

ffmpeg -i 这里填写MP4文件名.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 2 -hls_time 15 填写输出的m3u8名字可自行更改.m3u8

他就将文件转成了 m3u8 格式的

例如我是这样执行的

ffmpeg -i 1.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 0 -hls_time 15 out.m3u8

所以在文件下就生成了

最后启动 Web 服务,挂载静态目录即可。

还有要提的是,浏览器自带的 video 标签本身不支持 .m3u8 文件的播放,因此一般情况下我们都是用第三方的 video.js 库。

前端测试代码如下

<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 id="source" src="http://121.5.62.93:9090/out.m3u8" type="application/x-mpegURL">

</video>

</body>

<script>

    // videojs 简单使用

    var myVideo = videojs('myVideo',{

        bigPlayButton : true,

        textTrackDisplay : false,

        posterImage: false,

        errorDisplay : false,

    })

    myVideo.play() // 视频播放

    myVideo.pause() // 视频暂停

</script>

</html>

后端Go web 服务代码如下

func main () {
	// 挂载目录
	const dir = "/usr/local/workspace/test/oss"
	const port = 9090
	http.Handle( "/" , addHeaders(http.FileServer(http.Dir(dir))))
	// 启动服务
	log.Fatal(http.ListenAndServe(fmt.Sprintf( ":%v" , port), nil ))
}

// addHeaders 解决跨域
func addHeaders (h http.Handler) http.HandlerFunc {
	return func (w http.ResponseWriter, r *http.Request) {
		w.Header().Set( "Access-Control-Allow-Origin" , "*" )
		h.ServeHTTP(w, r)
	}
}

兰陵美酒郁金香

大道至简 Simplicity is the ultimate form of sophistication.

文章评论(0)

你必须 登录 才能发表评论