1,HLS简介

HLS,Http Live Streaming 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。

ts 文件_ts文件音频_ts视频文件

1.1,m3u8描述文件

M3U8文件是指UTF-8编码格式的M3U文件。M3U文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。

M3U8是一种常见的流媒体格式,主要以文件列表的形式存在,既支持直播又支持点播,尤其在Android、iOS等平台最为常用。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:3
#EXTINF:1.969
test0.ts
#EXTINF:1.972
test1.ts
#EXTINF:1.109
test2.ts
#EXT-X-DISCONTINUITY
#EXTINF:2.969
test3.ts
#EXT-X-ENDLIST

最常见的参数有:

参数说明:

1:BANDWIDTH:BANDWIDTH的值为最高码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的最大码率(必要参数)。

2:AVERAGE-BANDWIDTH:AVERAGE-BANDWIDTH的值为平均码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的平均码率。(可选参数)。

3:CODECS:CODECS的值用于声明EXT-X-STREAM-INF下面对应M3U8里面的音视频编码、视频编码的信息(可选参数)。

4:RESOLUTION:M3U8中视频的宽高信息描述(可选参数)。

5:FRAME-RATE:子M3U8中的视频帧率(可选参数)。

对于AES-128的情况,keytag和URI属性共同表示了一个key文件,通过URI可以获得这个key,如果没有 IV(Initialization Vector),则使用序列号作为IV进行编解码,将序列号的高位赋到16个字节的buffer中,左边补0;如果 有IV,则将改值当成16个字节的16进制数。

For example:

EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00

服务器不能改变或是删除PlayList文件中的任何部分,但是可以向该文件中增加新的一行内容。

1.2,ts媒体文件

HLS的优势为:自适应码率流播(adaptive streaming)。效果就是客户端会根据网络状况自动选择不同码率的视频流,条件允许的情况下使用高码率,网络繁忙的时候使用低码率,并且能够自动在二者之间随意切换。这对移动设备网络状况不稳定的情况下保障流畅播放非常有帮助。实现方法是服务器端提供多码率视频流,并且在列表文件中注明,播放器根据播放进度和下载速度进行自动调整。

为什么要用 TS 而不是 MP4?这是因为两个 TS 片段可以无缝拼接独立解码,播放器能连续播放,而 MP4 文件由于编码方式的原因,两段 MP4 不能无缝拼接,播放器连续播放两个 MP4 文件会出现破音和画面间断,影响用户体验。

2,ffmpeg简介

官方网站:

FFMPEG堪称自由软件中最完备的一套多媒体支持库,它几乎实现了所有当下常见的数据封装格式、多媒体传输协议以及音视频编解码器,堪称多媒体业界的瑞士军刀。因此,对于从事多媒体技术开发的工程师来说,深入研究FFMPEG成为一门必不可少的工作。

2.1,FFMPEG命令

这里指FFMPEG提供的命令行(CLI)工具ffmpeg,其使用方法如下(方括号表示可选项,花括号表示必选项目):

ts视频文件_ts文件音频_ts 文件

ffmpeg [global options] {[infile options]['-i' 'infile'] ...} {[outfile options] 'outfile' ...}

参数选项由三部分组成:可选的一组全局参数、一组或多组输入文件参数、一组或多组输出文件参数,其中,每组输入文件参数以‘-i’为结束标记;每组输出文件参数以输出文件名为结束标记。

2.2,基本参数

能力集列表

常用输入选项

对于输入,以下选项通常是自动识别的,但也可以强制设定。

常用输出选项

3,使用ffmpeg进行mp4与m3u8之间转换变切片

切片会将MP4切成一个m3u8文件和无数个ts文件。

ts 文件_ts文件音频_ts视频文件

3.1,安装ffmpeg

首先是给服务器安装ffmpeg,我这里是ubuntu,ubuntu上安装非常简单,执行如下代码就行:

sudo apt install ffmpeg
ffmpeg -version

第一行是安装ffmpeg,第二行是查看ffmpeg版本,来确认是否安装好了;

3.2,转码切片m3u8

然后MP4转码并切片,基本命令:

ffmpeg -i movie.mp4 -profile:v baseline -level 3.0 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls movie.m3u8

这个命令,大概15分钟左右一部片子。其中movie.mp4和movie.m3u8就是原文件和需要转换成的m3u8文件;

转码速度有点慢,但是可以多线程跑,加上参数,-threads 10和 -preset ultrafast

ffmpeg -i movie.mp4 -threads 10 -preset ultrafast -profile:v baseline -level 3.0 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls movie.m3u8

以上速度虽然提升了,但是画质可能会降低,有时候会模糊。命令大概5分钟一部片子。

有没有速度快,而且画质不影响的命令?

有的ts视频文件,这也是我最常用的,最简单的命令。

重要参数

所以最终的命令为:(正常片子10秒一部片)

ffmpeg -i movie.mp4 -codec: copy -start_number 0 -hls_time 10 -hls_list_size 0 -f hls movie.m3u8

ts文件音频_ts 文件_ts视频文件

3.3,hls_time不生效的问题

这个命令,虽然速度快,但是遇到一个问题。我改切片时间hls_time不生效,如我改成4秒。

ffmpeg -i movie.mp4 -codec: copy -start_number 0 -hls_time 4 -hls_list_size 0 -f hls movie.m3u8

但在 m3u8 文件中始终是#EXTINF:8.341667。hls_time不管改成多少ts视频文件,都是这个数。在GitHub问大神,得到答案。大神原话参考:

-c copy is fast and (oftentimes) lossless because you aren't remuxing. That's pretty much the entire point. To quote

The video streams can be encoded in the MPEG-1, MPEG-2, MPEG-4 and H. 264/AVC standards. The audio streams can be (HE)-AAC, MPEG-1 Audio Layer 1-2-3, CELP, TwinVQ, Vorbis or Apple Lossless.

Note: it's missing H.265/HEVC. On first glance. Some codecs actually are segmented already. Hence you'd have to remux if you want to change the segmentation time.

大概意思, -codec: copy所支持的视频流MPEG-1, MPEG-2, MPEG-4 and H. 264/AVC 标准流,和音频流(HE)-AAC, MPEG-1 Audio Layer 1-2-3, CELP, TwinVQ, Vorbis,Apple Lossless。

注:H.265/HEVC是不支持的。有些转码器已经内置切片时长,如果需要改切片时长,需要重新编码。

所以我片子是通过格式工厂默认编码,查询得知,格式工厂默认内置为8秒或者10秒。所以hls_time自定义切片时间不生效。

解决方法,格式工厂重新编码即可。格式工厂编码输出设置,改两个选项。

1:二次编码,是

2:关键帧间,选择2或者更小。2代表可以切2秒的倍数,如可切2秒,4秒,6秒。默认应该为8,所以只能切8秒。

ts文件音频_ts 文件_ts视频文件

重新编码的影片,可以重新切片2秒或者4秒。

4,编写脚本批量自动检测切片

服务器影片目录为TV,子目录分别由m3u8,mp4,upload三个文件夹。

ubuntu@ubuntu:/TV$ tree
.
├── m3u8
├── mp4
└── upload

脚本逻辑,电影上传至upload,脚本检测到后,将影片移动至mp4文件夹作为原片保存,然后切片文件保存在m3u8文件夹。upload可自行创建文件夹,脚本自动在mp4和m3u8自动生成对应文件夹。

切片完成,保存相关观看链接至指定txt文档,作为日志保存。

脚本内容:

#! /bin/bash
#調試模式
#set -x
#上传目录
path_tv=/TV/upload
cut_m3u8(){
	mv $path_upload/$filemp4 $path_mp4 &&
	ffmpeg -i $path_mp4/$filemp4 -codec: copy -start_number 0 -hls_time 4 -hls_list_size 0 -f hls $path_m3u8/$filem3u8 &&
	echo "$name.m3u8 切片完成,时间:`date +%F_%R`" >> /var/www/tv_link/link.txt && 
	echo "$name网站链接为:https://ywbj.cc/$path/$name.m3u8" >> /var/www/tv_link/link.txt &&
	echo >> /var/www/tv_link/link.txt
}
#循环在upload查找所有的MP4格式文件
for file in `find $path_tv $1 | grep 'mp4'`
do 
	#截取影片名称
	name1=${file%*.mp4}
	name=${name1##*/}
	#合并MP4文件名,和m3u8文件名。
	filem3u8=`eval echo $name.m3u8`
	filemp4=`eval echo $name.mp4`
	#截取upload下影片文件夹名称
	path1=${file%/*}
	path=${path1##*/}
	path_upload=/TV/upload/$path
	path_mp4=/TV/mp4/$path
	path_m3u8=/TV/m3u8/$path
	#检测是否由对应文件夹,没有则创建
	if [ ! -d $path_mp4 ]; then
#       	 echo "创建文件夹"
        	mkdir -p $path_mp4
	fi
	if [ ! -d $path_m3u8 ]; then
	#        echo "创建文件夹"
        	mkdir -p $path_m3u8
	fi
	if [ -f $path_m3u8/$filem3u8 ]; then
		echo "$filem3u8已存在,删除旧文件,重新切片..." >> /var/www/tv_link/link.txt &&
		rm -f $path_m3u8/$name* &&
		cut_m3u8
	else
		cut_m3u8
	fi
done

5,定时任务,自动运行脚本

定时任务,脚本每5分钟,检测一次upload文件夹,是否有mp4文件。

crontab -e

添加定时任务,脚本保存在/shell/m3u8_auto.sh路径。

#切片脚本,5分钟检查一次
*/5 * * * * bash /shell/m3u8_auto.sh

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击网站首页每天更新
站 长 微 信: aiwo51889