0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

学习使用FFmpeg进行HLS打包

LiveVideoStack 来源:OTTVerse 作者:Krishna Rao Vijayanag 2022-05-09 10:27 次阅读

在本文中,我们将学习使用FFmpeg进行HLS打包。使用FFmpeg的好处在于:你可以在不离开命令行的情况下,执行提取视频、调整视频尺寸、转码、打包以及传输视频的所有操作。

我们首先看一下为VOD(点播)创建HLS打包的所有步骤,然后再来了解HLS实时流的打包。

如果你想了解HLS播放列表的更多信息,可以访问我们的m3u8文件合集:https://ottverse.com/free-hls-m3u8-test-urls/,查看使用不同用例的不同厂商的示例。如果你刚刚接触HLS,请阅读我们之前的文章:什么是HLS(HTTP Live Streaming)?理解ABR及其工作原理

事不宜迟,让我们开始吧!

使用FFmpeg进行HLS打包的基础步骤

好,现在让我们看下使用HLS打包点播文件的基础步骤:

  1. 从磁盘读取输入视频

  2. 将视频缩放/调整(scale/resize)为所需的多种分辨率版本

  3. 将每个缩放后的视频转码到所需码率

  4. 音频转码到所需码率

  5. 将视频与音频组合,然后打包每一个音、视频组合,再创建各TS视频切片和播放列表(playlist)

  6. 创建一个主播放列表(master playlist),用于指向每个变体(variant)

现在,让我们一步一步来解决。

FFmpeg将视频调整为多种分辨率版本

第一步和第二步包括从磁盘中读取视频,然后将其调整为多种分辨率。上述操作仅需一个命令,如下所示:

ffmpeg -i brooklynsfinest_clip_1080p.mp4 -filter_complex "[0:v]split=3[v1][v2][v3];[v1]copy[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=640:h=360[v3out]"

[0:v]指输入文件的第一个视频流。在我们的例子中,只有一个视频流,它被分成3个输出[v1][v2][v3]。它们每一个都作为FFmpeg缩放函数的输入,该缩放函数接受一个高度和宽度数值用于执行缩放。

这里,我们将输入视频调整为1080p、720p和360p。

这里的[v1out][v2out][v3out]是包含缩放过程的输出变量。注意,这里我们假设缩放过程会保留长宽比(aspect ratio)。当然,你可以在必要时使用letterboxing来处理。

审校者注:letterboxing是指将以宽银幕比例拍摄的电影转换到标准宽度的视频格式时,同时保留电影的原始宽高比,由此产生的视频图像上下都有黑条的这个过程;这些黑条是图像的一部分(即视频信号的每一帧)。LTBX是其缩写,标识如此格式化的电影和图像。这个术语来自于信箱的形状,信箱是墙壁或门上的一个槽,邮件通过它来传递,它是长方形的,宽于它的高度。下图是一个 2.35:1比例的 widescreen 图像经过letterboxing 处理之后,放在 1.33:1 屏幕上的一个例子。如下:

fc51e34e-cf2b-11ec-bce3-dac502259ad0.png

除此之外,还有pillarboxing和windowboxing等常见转换模式。

将视频转码为多种码率用于HLS打包

接着,我们进入第三步和第四步:我们必须将视频转码为多种码率,正如ABR技术常做的那样。

记住,我们已经将视频调整为所需的分辨率并存储进 [v1out][v2out][v3out]的输出。我们将直接使用它们作为转码步骤的输入。

-map [v1out] -c0 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b0 5M -maxrate0 5M -minrate0 5M -bufsize0 10M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map [v2out] -c1 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b1 3M -maxrate1 3M -minrate1 3M -bufsize1 3M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map [v3out] -c2 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b2 1M -maxrate2 1M -minrate2 1M -bufsize2 1M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map a:0 -c0 aac -b0 96k -ac 2 -map a:0 -c1 aac -b1 96k -ac 2 -map a:0 -c2 aac -b2 48k -ac 2 

你能发现这里发生了什么吗?我们已将三个变量[v1out][v2out][v3out]作为输入,并使用libx264的slow预设置转码每个输入到所需码率。

注意:你也可以选择你自己的编码参数,并根据自己的喜好和要求进行修改。在这个示例中,我使用一些简单的参数模拟CBR编码。使用FFmpeg有无数方法可以转码你的视频,你可以在预设置、crf值和CBR设置等不同参数组合之间任意选择。

重要的是,我们已经将-keyint_min设置为48,它会强制设置关键帧出现的周期,这在ABR转码技术中非常重要。

现在,我们进行到下一个阶段:为每一个码率版本/变体(rendition/variant)创建HLS m3u8播放清单。

使用FFmpeg创建HLS播放清单(m3u8)

现在我们已经有了将视频转码为不同码率变体的命令,让我们来使用FFmpeg创建HLS点播播放列表。

下面是进行HLS打包所需的重要设置:

  • hls_playlist_type=vod: 通过设置该值,FFmpeg创建了一个点播播放列表,将#EXT-X-PLAYLIST-TYPE:VOD插入到m3u8头部中,并强制hls_list_size为0。

  • hls_time seconds:我们需要使用它设置目标切片长度(以秒为单位)。

  • 默认值为2秒,当2秒过去,切片将在下一个关键帧处被切片。

  • 之所以要求确保每个比特流变体在每N秒结束的时候都有一个关键帧(这点非常重要),因为ABR要求切片时候的关键帧要对齐,这样才能无缝切换。

  • hls_segment_type:这里有两个值:mpegts或fmp4,用于指定创建TS片段或fmp4(CMAF)片段,这对创建HLS和DASH的单一数据流很有用。

  • -hls_flags independent_segments:当确保播放列表中所有切片都以一个关键帧开始时,将#EXT-X-INDEPENDENT-SEGMENTS添加到播放列表中。

  • hls_segment_filename filename 用于在打包过程中为所创建的视频切片命名。

下面是为单一视频文件创建播放列表的示例:

-f hls -hls_time 2 -hls_playlist_type vod -hls_flags independent_segments -hls_segment_type mpegts -hls_segment_filename stream_%v/data%02d.ts -var_stream_map “v:0,a:0 v:1,a:1 v:2,a:2” stream_%v/stream.m3u8

如果你看到最后一行,你会注意到一个名为var_stream_map的功能选项。它是做什么的?

var_stream_map是一个FFmpeg功能选项,它帮助我们将各种视频和音频转码组合起来,以创建不同的HLS播放列表。如果你有两个使用相同视频但不同音频的码率版本,那么你可以选择不同的视频和音频版本并将它们连接起来,而不是为了创建不同的播放列表而创建多个编码。

比如,-var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0"是指由a:0表示的音频流被用于三种视频码率版本(rendition)。

FFmpeg获取这些音频和视频的组合后,创建出名为stream_%v.m3u8的各变体的.m3u8 文件,其中%v 是一个迭代器,它从被打包的视频流编号获取对应的值。

使用FFmpeg创建主播放列表(m3u8)

如果你已经理解了如何使用FFmpeg创建HLS播放列表,那么使用FFmpeg创建主播放列表对你而言就很简单了。如果你不知道什么是主播放列表的话,我可以告诉你:主播放列表就是一个文件,它列出了已由HLS打包的各个变体的播放列表。

为了使用FFmpeg创建主播放列表,只需将关键词master_pl_name 添加到你的FFmpeg命令中,并提供你为主播放列表准备的名称。比如,如果你想称“主播放列表”为“master.m3u8”,只需写下如下命令:

-master_pl_name master.m3u8

这就可以了。在FFmpeg执行该命令行之后,你将拥有一个HLS主播放列表,其中列出了其他播放列表的名称。

使用FFmpeg-VOD进行HLS打包的最终脚本

ffmpeg -i brooklynsfinest_clip_1080p.mp4 -filter_complex "[0:v]split=3[v1][v2][v3]; [v1]copy[v1out]; [v2]scale=w=1280:h=720[v2out]; [v3]scale=w=640:h=360[v3out]" -map [v1out] -c0 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b0 5M -maxrate0 5M -minrate0 5M -bufsize0 10M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map [v2out] -c1 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b1 3M -maxrate1 3M -minrate1 3M -bufsize1 3M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map [v3out] -c2 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b2 1M -maxrate2 1M -minrate2 1M -bufsize2 1M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 -map a:0 -c0 aac -b0 96k -ac 2 -map a:0 -c1 aac -b1 96k -ac 2 -map a:0 -c2 aac -b2 48k -ac 2 -f hls -hls_time 2 -hls_playlist_type vod -hls_flags independent_segments -hls_segment_type mpegts -hls_segment_filename stream_%v/data%02d.ts -master_pl_name master.m3u8 -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" stream_%v.m3u8

让我们看下该脚本的输出。

它首先生成一个主播放列表,三个文件夹包含独立的切片,以及三个变体的播放列表。

fc86401c-cf2b-11ec-bce3-dac502259ad0.png

下面是master.m3u8文件:

#EXTM3U#EXT-X-VERSION:6#EXT-X-STREAM-INF:BANDWIDTH=5605600,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2"stream_0.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3405600,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2"stream_1.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1205600,RESOLUTION=640x360,CODECS="avc1.64001e,mp4a.40.2"stream_2.m3u8

你可以看到,主播放列表引用了分别用于1080p、720p和360p的HLS变体播放列表。

现在,我们来看看1080p HLS变体。它很明确地表明它是一个VOD播放列表,视频切片都是独立的,每个切片长度是2秒(按照我们的设置)。

#EXTM3U#EXT-X-VERSION:6#EXT-X-TARGETDURATION:2#EXT-X-MEDIA-SEQUENCE:0#EXT-X-PLAYLIST-TYPE:VOD#EXT-X-INDEPENDENT-SEGMENTS#EXTINF:2.002000,data00.ts#EXTINF:2.002000,data01.ts#EXTINF:2.002011,data02.ts#EXTINF:2.002000,data03.ts#EXTINF:2.002000,data04.ts#EXTINF:2.002000,data05.ts#EXTINF:2.002000,data06.ts#EXTINF:2.002000,data07.ts#EXTINF:2.002011,data08.ts#EXTINF:2.002000,data09.ts#EXTINF:0.041711,data10.ts#EXT-X-ENDLIST

使用FFmpeg进行HLS直播打包

如果你想通过FFmpeg创建一个直播HLS播放列表,这个过程和我们刚刚讲过的VOD步骤区别不是很大。下面是你需要做出的更改:

  1. 删除-hls_playlist_type vod

  2. 添加-hls_list_size ,并将其设置为一个数字,该数字表示各个变体播放列表中的切片数(你希望设置的数字)。

比如,如果我们将-hls_list_size 设置为2,那么整个播放列表将只包含两个切片,FFmpeg将通过添加新的切片及删除旧切片来重写这个播放列表。

下面是一个示例:

#EXTM3U#EXT-X-VERSION:6#EXT-X-TARGETDURATION:2#EXT-X-MEDIA-SEQUENCE:1#EXT-X-INDEPENDENT-SEGMENTS#EXTINF:2.002000,data01.ts#EXTINF:2.002011,data02.ts

几秒之后,切片data01.ts被删除,并被切片data03.ts所取代。

#EXTM3U#EXT-X-VERSION:6#EXT-X-TARGETDURATION:2#EXT-X-MEDIA-SEQUENCE:2#EXT-X-INDEPENDENT-SEGMENTS#EXTINF:2.002011,data02.ts#EXTINF:2.002000,data03.ts

FFmepg中其他有用的HLS打包选项

最后,让我们来快速浏览一些FFmpeg为点播和直播HLS打包所提供的一些其他有趣选项:

  1. hls_base_url baseurl:可用于将baseurl表示的值追加到播放列表的每个条目。

  2. hls_fmp4_init_filename filename : 设置文件名为分片文件头文件,默认文件名为init.mp4。当你把片段类型设置为fmp4而非mpegts时,就会用到这个文件。

  3. hls_fmp4_init_resend:在m3u8文件每次刷新时,重新发送init文件,默认为0。


    审校者注:当var_stream_map设置为两个或多个变体流时,文件名模式必须包含字符串"%v",这个字符串指定变体流索引在生成的init文件名中的位置。这时候可以结合上面的 hls_fmp4_init_resend 重新发送init文件。

  4. iframes_only : 将#EXT-X-I-FRAMES-ONLY添加到包含视频切片并只能在 #EXT-X-BYTERANGE 模式下播放I帧的播放列表中。

结语

现在,我希望你已经很好地理解了如何通过FFmpeg来执行HLS流媒体协议转码和打包。有关使用 FFmpeg 进行 HLS 打包的完整选项列表,请查看 FFmpeg文档:

https://ffmpeg.org/ffmpeg-formats.html#hls-2

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 磁盘
    +关注

    关注

    1

    文章

    372

    浏览量

    25200
  • HLS
    HLS
    +关注

    关注

    1

    文章

    128

    浏览量

    24078
  • ffmpeg
    +关注

    关注

    0

    文章

    46

    浏览量

    7393

原文标题:使用FFmpeg进行HLS打包——FFmpeg简单学

文章出处:【微信号:livevideostack,微信公众号:LiveVideoStack】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux文件压缩打包的各种姿势

    1.文件打包与压缩 1.什么是文件压缩? 将多个文件或目录合并成为一个特殊的文件。比如: 搬家…脑补画面 img. 2.为什么要对文件进行压缩? 当我们在传输大量的文件时,通常都会选择将该文件进行
    的头像 发表于 12-02 09:25 181次阅读

    使用TMS320C6000 MCBSP进行数据打包

    电子发烧友网站提供《使用TMS320C6000 MCBSP进行数据打包.pdf》资料免费下载
    发表于 10-26 10:54 0次下载
    使用TMS320C6000 MCBSP<b class='flag-5'>进行</b>数据<b class='flag-5'>打包</b>

    优化 FPGA HLS 设计

    优化 FPGA HLS 设计 用工具用 C 生成 RTL 的代码基本不可读。以下是如何在不更改任何 RTL 的情况下提高设计性能。 介绍 高级设计能够以简洁的方式捕获设计,从而
    发表于 08-16 19:56

    一种在HLS中插入HDL代码的方式

    很多人都比较反感用C/C++开发(HLS)FPGA,大家第一拒绝的理由就是耗费资源太多。但是HLS也有自己的优点,除了快速构建算法外,还有一个就是接口的生成,尤其对于AXI类接口,按照标准语法就可以很方便地生成相关接口。
    的头像 发表于 07-16 18:01 721次阅读
    一种在<b class='flag-5'>HLS</b>中插入HDL代码的方式

    如何移植FFmpeg

    的全方位解决方案,深入掌握FFmpeg已成为每一位多媒体开发工程师的必修课。今天就跟各位小伙伴分享一篇共创社的学习笔记,探讨一下如何移植FFmpeg。配置交叉编译环
    的头像 发表于 06-07 15:28 1652次阅读
    如何移植<b class='flag-5'>FFmpeg</b>

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-如何移植FFmpeg

    的全方位解决方案,深入掌握FFmpeg已成为每一位多媒体开发工程师的必修课。今天就跟各位小伙伴分享一篇共创社的学习笔记,探讨一下如何移植FFmpeg。 配置交叉编译环境ELFbord官方
    发表于 06-06 09:32

    飞凌嵌入式ElfBoard ELF 1板卡-如何移植FFmpeg

    的全方位解决方案,深入掌握FFmpeg已成为每一位多媒体开发工程师的必修课。今天就跟各位小伙伴分享一篇共创社的学习笔记,探讨一下如何移植FFmpeg。 配置交叉编译环境ELFbord官方
    发表于 06-06 09:17

    《深入理解FFmpeg阅读体验》FFmpeg摄像头测试

    零、前期工作 上文FFmpeg移植完成后,需要将x264/lib文件夹下的库文件拷贝到开发板的/lib/目录下,将ffmpeg_install/lib文件夹下的库文件全部拷贝到开发板的/lib/目录
    发表于 04-17 19:06

    《深入理解FFmpeg阅读体验》

    , not stripped pkgconfig:directory 二、编译FFmpeg 首先从FFmpeg官方网站http://ffmpeg.org/download.html上下载FF
    发表于 04-16 22:54

    【米尔-芯驰D9360商显板试用评测】FFmpeg移植

    ,介绍了FFmpeg封装、编解码和滤镜部分的API使用操作,相关操作均以实例方式进行说明,包括新旧API的操作方法和异同,并给出了大量的API使用、自定义功能模块、基于FFmpeg的API开发
    发表于 04-16 22:48

    【米尔-芯驰D9360商显板试用评测】使用ffmpeg实现远程视频监控

    】 通过ffmpeg实现采集视频,并推流给服务器,就可以实现远程的视频查看。也可以定义在服务器中对他进行传发、录像。
    发表于 04-11 13:07

    《深入理解FFmpeg阅读体验》ffmpeg安装

    书中讲了如何编译安装,我看了一下比较复杂,所以下载安装包进行安装,下载网址:Download FFmpeg 下载完后解压出来在bin目录下面有三个文件: 复制这个目录: C:\\\\Users
    发表于 01-25 21:35

    《深入理解FFmpeg阅读体验》初识有感

    言中《如何阅读本书》指出我们如何开始学习FFmpeg。老师建议从头开始,上篇为基础篇,下篇为API使用以及开发。 第三,书中还给我们指出如何从FFmpeg官方文档、wiki以及推荐雷霄骅博士的
    发表于 01-07 19:48

    《深入理解FFmpeg阅读体验》+ 书收到了,崭新的开篇

    今天收到了《深入理解FFmpeg》 崭新的书,一个在2022年较近距离接触过却尚未深入研究的领域图像处理。最近刚好在作这方面的研究,希望自己可以把握这次机会,好好学习FFMpeg,相信可以让自己
    发表于 01-07 18:57

    AMD-Xilinx的Vitis-HLS编译指示小结

    使用a=b,不允许使用 a=a+1,个人理解,合并过后的循环执行次数可能和原来不一样,HLS会自动进行优化) 包含 FIFO 读取的循环无法合并。合并会更改读取顺序。从 FIFO 或 FIFO接口执行读取
    发表于 12-31 21:20