FFmpeg命令行转封装

本文主要记录通过FFmpeg对MP4,FLV,M3U8格式的封装和文件分析以及对这些格式的一些了解。后面还对音视频的抽取做了简单的介绍。

MP4格式

在互联网常见的格式中,跨平台最好的就是MP4,它可以在PC的Flashplayer中播放,又可以在Android和iOS中播放

简介

MP4的官方术语介绍我们就不看了,对于MP4文件要了解如下几个重要的概念:

  • MP4文件由多个Box与FullBox组成
  • 每个Box由Header和Data两部分组成
  • FullBox是Box的扩展,在Box的基础上,在Header中增加了8位version标志和24位flags标志
  • Header包含了整个Box的长度和大小和类型,当size等于0时,表示这个Box是文件的最后一个Box。当size为1时,说明Box长度需要更多位来描述,在后面会定义一个64位的largesize来描述Box的长度。当Type为uuid时,说明这个Box中的数据是用户自定义扩展类型
  • Data为Box的实际数据,可以是纯数据,也可以是更多的子Box
  • 当一个Box的Data是一些列的子Box时,这个Box也可以称为Container Box

    对于各种Box类型的分析我们就不在这里记录,因为太多了。具体参考书籍《FFmpeg从入门到精通》

MP4分析工具

MP4文件的分析工具除了FFmpeg外,还有很多可视化的工具,例如Elecard StreamEye,mp4box,mp4info,mediainfo等 这些工具我看了在Mac上面感觉都不咋行,于是在Windows上面玩了一下。

使用FFmpeg查看MP4文件

查看MP4文件解封装Demuxer

ffmpeg -h demuxer=mp4

查看MP4文件封装Muxer

ffmpeg -h muxer=mp4

上面两个命令可以查看FFmpeg的解封装和封装的参数,下面列举一些参数使用的示例

faststart参数使用

使用mp4info查看一个mp4文件的Box信息通常如下所示:




moov在madt写完以后再写入,所以它出现在容器的最后面。通过faststart可以把moov移到mdat的前面:注意要从一个flv文件转换为mp4文件让它重新生成Box数据
由于我只准备了一个mp4文件,所以先通过下面的命令把我的mp4文件转换为flv文件再来验证这个参数:

ffmpeg -i ~/Movies/i_am_you.mp4 -vcodec libx264 -preset fast -profile baseline -x264opts bitrate=300 -s 320x240 -r 12 -g 12 -f flv ~/Movies/output.flv

下面可以验证我们的faststart参数的效果了

ffmpeg -i output.flv -c copy -f mp4 -movflags faststart output.mp4

转换完成以后通过mp4info来查看MP4文件的Box信息



dash参数使用示例

使用DASH格式的时候,生成的MP4文件的Box信息和之前的不同,它主要包含的容器为sidx,moof和mdat这三个Box
FFmpeg命令生成DASH格式的MP4文件:

ffmpeg -i input.flv -c copy -f mp4 -movflags dash output.mp4

查看生成的MP4文件的Box组成



FLV格式

在网络直播和点播场景中,FLV是一种常见的格式。它的封装格式很简单,均以FLVTAG的形式存在,并且每一个TAG都是独立存在的。
FLV格式的分析我就不记录了。有点儿复杂

FLV文件格式分析工具

可视化工具可以使用flvparse或者FlvAnalyzer来分析FLV文件格式的信息。我使用FlvAnalyzer工具来查看了一个flv文件的内容如下:




使用ffmpeg也可以分析flv文件的格式命令行如下:

ffprobe -v trace -i ~/Movies/output.flv

输出如下:



使用FFmpeg操作转换FLV

主要介绍MP4转换为FLV格式 ,上面我们没有FLV格式的素材的时候转换了一下,并没有了解其中的参数的具体含义。下面我们着重了解一下。
如果封装FLV的时候,内部的音频或者视频不符合标准时,那么它们就无法封装进去。因为FLV的音视频的编码支持如下
支持视频编码:

  • Sorenson H.263
  • Screen Video
  • On2 VP6
  • 带Alpha通道的On2 VP6
  • Screen Video2
  • H.264(AVC)
    支持音频编码:
  • 限行PCM 大小端取决于平台
  • ADPCM音频格式
  • MP3
  • 线性PCM 小端
  • Nellymoser 16kHz Mono
  • Nellymoser 8kHz Mono
  • Nellymoser

MP4封装为FLV

如果源视频的音视频编码是FLV所支持的,那就可以顺利的封装
上面的封装命令是从网上copy的其实如果我的源视频支持FLV的封装格式只要如下命令:

ffmpeg -i ~/Movies/i_am_you.mp4 -c copy -f flv ~/Movies/output.flv

就可以完成转换

ffmpeg -i ~/Movies/i_am_you.mp4 -vcodec libx264 -preset fast -profile baseline -x264opts bitrate=300 -s 320x240 -r 12 -g 12 -f flv ~/Movies/output.flv

这个命令就是在其中添加了很多封装的参数。到后面详细了解每个参数的含义。

生成带关键索引的FLV

在网络视频点播文件为FLV格式时,人们常用yamdi工具对FLV文件进行一次转换,主要是将FLV文件中的关键帧建立一个索引,并将索引写入Metadata中,使用FFmpeg也可以实现

ffmpeg -i input.mp4 -c copy -f flv -flvflags add_keyframe_index output.flv

M3U8格式

M3U8是一种常见的流媒体格式,主要以文件列表的形式存在,即支持直播也支持点播,尤其在Android和IOS最为常用

MP4文件转HLS切片

FFmpeg中自带HLS的封装参数,使用HLS格式即可进行HLS的封装,但是生成HLS的时候有很多参数可以参考具体的参数使用的时候查看文档
转换文件命令:

ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8

其中多了一个参数命令 -bsf:v h264_mp4toannexb 这个参数的作用是将MP4中的H.264数据转换为H.264 AnnexB标准的编码,AnnexB标准的编码常用于实时传输流中。如果源文件为FLV,TS等可以作为直播传输流的视频,就不要这个设置。

执行完这个命令之后 看到目录下面有一大片ts切片文件我上面的命令默认的每一个切片的时间是5秒,这个时间可以通过 -hls_time这个参数来设置

ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_time 40 output.m3u8

它还有很多参数可以设置 使用的时候查看具体的需求和文档操作

视频文件切片

视频文件切片和HLS基本类似,但是HLS切片在标准中只支持TS格式的切片,并且是直播与点播切片。我们可以把一个mp4文件来切成多个mp4文件,可以使用segment 方式来进行切片,也可以使用ss加上t参数进行切片。

使用segment参数切片

这里指定一个切片命令的参数-segment_format

ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 test_output-%d.mp4

segment还有很多其余的参数,用的时候了解要使用的参数。

使用ss与t参数进行切片

ss进行视频文件的seek定位,ss传递的参数为时间值,t传递的参数也是时间值

  • 使用ss指定剪切开头部分
ffmpeg -ss 10 -i input.mp4 -c copy output.ts

命令执行后生成的ouput.ts会比input.mp4视频少大概8秒,因为output.ts是从input.mp4的第八秒开始截取的。使用如下命令看duration信息

ffprobe -v quiet -show_format input.mp4 |grep duration;ffmpeg -v quiet -show_format output.ts |grep duration
  • 使用t指定视频总长度
    使用FFmpeg除了可以指定开始截取位置,还可以指定截取数据的长度,FFmepg的t参数可以指定截取的视频长度,例如截取input.mp4文件的前十秒的数据
ffmpeg -i input.mp4 -c copy -t 10 -copyts output.mp4
  • 使用output_ts_offset指定输出start_time
    FFmpeg支持ss与t参数一同使用以达到切割视频的某一段的效果,但其不能指定输出文件的start_time,而且也不希望时间戳归0,可以使用output_ts_offset来达到指定输出文件的start_time的目的
ffmpeg -i input.mp4 -c copy -t 10 -output_ts_offset 120 output.mp4

音视频文件抽取音视频流

抽取音视频文件中的AAC音频流

ffmpeg -i input.mp4 -vn -acodec copy output.acc

抽取音视频文件中的H.264视频流

ffmpeg -i input.mp4 -vcodec copy -an output.h.264

抽取音视频文件中的H.265视频流

ffmpeg -i input.mp4 -vcodec copy -an -bsf hevc_mp4toannexb -f hevc output.hevc

猜你喜欢

转载自blog.csdn.net/lyman_ye/article/details/80261312