前言
本篇博客记录了学习HLS流媒体协议的原理、工作流程以及搭建最简单的HLS服务器的过程。通过学习HLS协议,将能够理解流媒体技术的核心概念,并具备搭建自己的流媒体服务的基础知识。
一、HLS协议是什么?
HLS协议一般只用作拉流观看,但是严格意义上讲,HLS并不是流式协议,工作原理就是通过HTTP协议下载静态文件。不同的是,HLS协议的文件由两部分组成,一是多个只有几秒长度的ts碎片视频文件,另一个是记录这些视频文件地址的m3u8索引文件,且这些静态文件都是直接写入磁盘的。
HLS协议可以用于点播和直播观看,其适配多种播放场景,一般加入插件就可以播放了,如网页加入HLS的js插件就可以播放了,苹果设备是原生支持HLS协议的。
点播的场景下,也即普通网络视频观看的场景下,m3u8索引文件会记录所有的碎片视频文件地址,HLS在点播场景下优势是更加明显的,由于HLS的相关文件是无状态的静态文件且每个文件的大小是有限的,所以负载均衡、CDN加速的效果更加明显。HLS协议的点播视频会比mp4、flv的视频更快地播放出来,且在加载中跳转视频也会更加顺滑。
直播场景下的HLS相关文件与点播是有些不同的,视频流数据每几秒会打包成一个以ts为后缀的碎片视频文件,每生成一个新的视频文件都会同步更新m3u8索引文件,且碎片视频文件的个数是有上限的,当达到上限后,默认会将最旧的视频文件删除且更新m3u8索引文件,所以在直播的场景下,客户端也需要不断定时重新获取m3u8索引文件。
HLS协议优缺点。
二、实现一个最简单的HLS服务器
1.ffmpeg命令行生成m3u8切片
如下(示例):
ffmpeg -i input.mp4 -c:v libx264 -c:a copy -f hls -hls_time 10 -hls_list_size 0 -hls_start_number 0 input/index.m3u8
备注:-hls_time n: 设置每片的长度,默认值为2,单位为秒
-hls_list_size n:设置播放列表保存的最多条目,设置为0会保存有所片信息,默认值为5
-hls_start_number n:设置播放列表中sequence number的值为number,默认值为0
-hls_wrap n:设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0
这个选项能够避免在磁盘上存储过多的片,而且能够限制写入磁盘的最多的片的数量
test目录:
第一个是m3u8索引文件,之后都是序号从0开始的ts文件
2.实现
HLS主要就是将流媒体数据分成一个一个小的ts分片,通过m3u8索引文件维持的分片序号实现播放。
现在文件已经生成了,现在只需要实现服务即可。
以下是main函数的具体实现流程:
#include <stdint.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include "Utils/Log.h"
#pragma comment(lib, "ws2_32.lib")
#include "Connection.h"
#include <thread>
int main() {
//ffplay -i http://127.0.0.1:8080/index.m3u8
int port = 8080;
LOGI("1-hlsServer http://127.0.0.1:%d/index.m3u8", port);
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
LOGE("WSAStartup error"