ffmpeg -i "https://xushanxiang.com/demo/ffmpeg/hls265/output.m3u8" -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4
1、通过 copy 命令合并文件
# 合并成 ts 文件
copy /b F:\f\*.ts E:\f\new.ts
#合并成 MP4 文件
copy /b F:\f\*.ts E:\f\new.MP4
2. 通过 ffmpeg 命令如下:
# 未验证
ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,https,crypto,tcp" -i D:/01_doc/mp4/test/index.m3u8 -c copy D:/01_doc/mp4/test/out.mp4
#直接转
ffmpeg -i new.ts -c copy -map 0:v -map 0:a output.mp4
#指定音频流(一般用这个)
ffmpeg -i new.ts -c copy -map 0:v -map 0:a -bsf:a aac_adtstoasc output.mp4
#重编码视频
ffmpeg -y -i new.ts -c:v libx264 -c:a copy -bsf:a aac_adtstoasc output.mp4
M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码。”M3U” 和 “M3U8” 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。
简单来说,m3u8是一个视频格式,就是将一个视频分成很多的小部分,这样方便视频的加载。
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 2 -hls_time 15 output.m3u8
生成的效果是:
将 input.mp4 视频文件每 15 秒生成一个 ts 文件,最后生成一个 m3u8 文件,m3u8 文件是 ts 的索引文件。
我们直接用 VLC media player 等播放软件是可以直接打开 m3u8 文件,像播放 mp4 一样。
默认的每片长度为 2 秒,m3u8 文件中默认只保存最新的 5 条片的信息,导致最后播放的时候只能播最后的一小部分(直播的时候特别注意)。
-hls_time n 设置每片的长度,默认值为 2,单位为秒。
-hls_list_size n 设置播放列表保存的最多条目,设置为 0 会保存有所片信息,默认值为5。
-hls_wrap n 设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0。这个选项能够避免在磁盘上存储过多的 片,而且能够限制写入磁盘的最多的片的数量。
-hls_start_number n 设置播放列表中 sequence number 的值为 number,默认值为 0。
注意:播放列表的 sequence number 对每个 segment 来说都必须是唯一的,而且它不能和片的文件名(当使用 wrap 选项时,文件名有可能会重复使用)混淆。
TS 文件是一种媒体的扩展名,它是日本高清摄像机拍摄下进行的封装格式。MPEG2-TS(Transport Stream“传输流”;又称TS、TP、MPEG-TS 或 M2T)是用于音效、图像与数据的通信协定,最早应用于DVD的实时传送节目。MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。
# 视频整体转码ts
ffmpeg -y -i music.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb out\music.ts
# ts 文件切片
ffmpeg -i music.ts -c copy -map 0 -f segment -segment_list out\music.m3u8 -segment_time 10 out\15s_%3d.ts
播放 m3u8 的 ts 切片,必须要完整的下载一个 ts 切片,才能够播放,设置hls_time 的时间间隔越短越好( 根据实际情况来 ),实际过程中设置切片时间间隔为 2 秒,调用如下指令:
ffmpeg -i test.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_time 2 index.m3u8
但没有按照参数输入,进行切片。
原因:
ts 文件的切割,还跟原文件视频的 GOP 大小有关系(也就是两个 I 帧之间的时间间隔),因为任何一个 ts 分片第一帧必须是I帧,否则无法最快播放,并且第一帧不是 I 帧,对于播放器也是没有任何的意义,直接被播放器扔掉。任何一个视频流必须在获取到第一个I帧才能成功解码出图片。虽然指定了 1 秒切割一个 ts 文件,实际上,由于原视频流可能好几秒才有一个 I 帧,所以必须等到下一个 I 帧,才会重新开始切片。
解决:
既然知道要1秒产生一个ts分片,那就必须产生切片的过程中,强制一秒中产生一个关键帧。
设置关键帧间隔,设置间隔为 2 秒的参数如下:-force_key_frames "expr:gte(t,n_forced*2)
“
完整指令如:
ffmpeg -i test.mp4 -force_key_frames "expr:gte(t,n_forced*2)" -strict -2 -c:a aac -c:v libx264 -hls_time 2 -f hls index.m3u8
完整的 m3u8 文件有三部分:
具体内容解析:
#EXTM3U
,是文件开始#EXT-X-VERSION
,标识HLS的协议版本号;#EXT-X-TARGETDURATION
,表示每个视频分段最大的时长(单位秒);#EXT-X-MEDIA-SEQUENCE
,表示播放列表第一个 URL 片段文件的序列号;#EXT-X-PLAYLIST-TYPE
,表明流媒体类型;#EXT-X-KEY
,加密方式,这里加密方式为AES-128
,同时指定IV
,在解密时需要;#EXTINF
,表示其后 URL 指定的媒体片段时长(单位为秒)。