首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

FFmpeg连载2-分离视频和音频

前言

前面我们搭建好了FFmpeg的开发环境,今天我们就来小试牛刀,使用FFmpeg库对mp4文件进行解封装,提取mp4中的视频流和音频流输出到单独的输出文件中。关于FFmpeg开发环境搭建可以看我之前的文章:

所谓的分离视频和音频是我们通俗的说法,官方的说法叫解封装。与解封装对应的叫封装或复用器,也就是将多个视频流或音频流合并成一个多媒体文件就叫封装。

API及数据结构介绍

在FFmpeg中解封装的大致流程如下图所示:

ffmpeg解封装流程图

在这里需要注意的一个点是不一定能获取到你想要的流,比如你想通过获取音频流的索引,笔者开发中发现对于某些格式是无法获取成功的,此时需要遍历一下解封装上下文的流,通过流的解码器类型来进行获取,例如你想要获取音频流,则可以判断解码器的类型是否是音频解码器即可。

下面介绍一下实现分离视频和音频数据所需要使用到的主要API以及相关的数据结构。

1、libavformat

libavformat库,是FFmpeg中用于处理各种媒体容器格式的库,它描述了一个媒体文件或媒体流的构成和基本信息,它的两个主要功能就是封装和解封装,可以说它是贯穿整个FFmpeg的根。

在解封装时,我们主要用到avformat中的几个函数、和,其中和是一对搭配使用的函数,一个打开一个关闭,千万不要忘记,否则会发生内存泄漏。

2、AVPacket

AVPacket类,用于存储编码后的帧数据。它一般由解封装导出,然后传递给解码器作为输入;又或者,从编码器作为输出,然后传递给封装去进行写入。

AVPacket可以表示一个视频包或者一个音频包,内部包含了这个视频包或音频包的播放时长,播放时间戳、二进制数据等相关信息。对于音视频等二进制数据,AVPacket内部使用了引用计数的方式进行数据共享。

对于AVPacket的那个字段,我们点进去头文件可以看到每个字段都有清晰的注释解析,这里就不细说了,例如:

下面是使用FFmpeg进行解封装的主要API调用:

提取视频

在FFMpeg中一般mp4解封装提取到的H264裸流是不带start code的,也就是提取到的这种H264裸流不能使用ffplay直接播放,还好FFmpeg很贴心地给我们提供了一个过滤器,通过这个过滤器我们可以很方便地给提取到的H264加上start code,从而能让ffplay直接播放。

废话少说,直接上代码:

提取音频

对于FFmpeg中解封装的音频AAC文件来说,mp4文件解封装出来的音频不附带adts头信息的,但是笔者看到有资料说对于ts格式的话好像解封装出来又是带有adts头的(笔者这个没有验证过)。对于这些没有附带adts头信息的aac音频文件,ffplay也是无法直接播放的,因此我们在提取音频信息时需要手动加上adts头信息。

针对添加adts头信息的话我们有两种方式,一种是对对adts比较熟悉的,可以在每个音频包的前面增加7个或者9个字节即可。还有一种就是使用FFmpeg的复用器封装功能,让其自动加上adts头信息。

其中使用FFmpeg内部复用器封装的步骤如下:

1、调用 av_guess_format 让ffmpeg帮你找到一个合适的文件格式。

2、调用 avformat_new_stream 为输出文件创建一个新流。3、调用 avio_open 打开新创建的文件。4、调用 avformat_write_header 写文件头。5、调用 av_interleaved_write_frame 写文件内容。6、调用 av_write_trailer 写文件尾。7、调用 avio_close 关闭文件

后面的代码笔者两种方式都简单测试了一下,提取到的aac音频文件都可以正常播放。

下面贴一下全部代码:

代码写的比较粗,而且很多异常也没有做处理,相关资源也没有进行释放,大家将就这看下。。。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20220416A03O2Z00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com