FFmpeg名称中的mpeg来自视频编码标准MPEG,而前缀FF是Fast Forward的首字母缩写。
目录
默认的编译会生成 4 个可执行文件和 8 个静态库。可执行文件包括用于 转码 、 推流 、Dump媒体文件的 ffmpeg 、用于播放媒体文件的 ffplay 、 用于获取媒体文件信息的 ffprobe ,以及作为简单流媒体服务器的 ffserver 。
8个静态库其实就是FFmpeg的8个模块,具体包括如下内容。
比如AAC编码,常见的有两种封装格式
AAC 的 bit stream filter 常常应用在 编码 的过程中。
与音频的AAC编码格式相对应的是视频中的 H264编码 ,它也有两种封装格式
FFmpeg中也提供了对应的 bit stream filter ,称 H264_mp4toannexb ,可以将MP4封装格式的H264数据包转换为annexb封装格式的H264数据 (其实就是裸的H264的数据)包。
H264 的 bit stream filter 常常应用于视频解码过程中。
ffmpeg 是进行媒体文件转码的命令行工具
ffprobe 是用于查看媒体 文件头信息的工具
ffplay 则是用于播放媒体文件的工具
1首先用ffprobe查看一个音频的文件
2输出格式信息format_name、时间长度duration、文件 大小size、比特率bit_rate、流的数目nb_streams等。
3以JSON格式的形式输出具体每一个流 最详细 的信息
4显示帧信息的命令如下:
5查看包信息的命令如下:
ffplay是以FFmpeg框架为基础,外加渲染音视频 的库libSDL来构建的媒体文件播放器。
业界内开源的 ijkPlayer 其实就是基于 ffplay 进行改造的播放器,当然其做了硬件解码以及很多兼容性的工作。
在 ffplay中音画同步的实现方式其实有三种。分别是
并且在 ffplay 中默认的对齐方式也是以 音频 为基准进行对齐的。
首先要声明的是,播放器接收到的视频帧或者音频帧,内部都会有 时间戳(PTS时钟) 来标识它实际应该在什么时刻进行展示。
实际的对齐策略如下:比较视频当前的播放时间和音频当前的播放时间
关键就在于音视频时间的比较以及延迟的计算,当然在比较的过程中会设 置一个 阈值(Threshold) ,若超过预设的阈值就应该做调整(丢帧渲染 或者重复渲染),这就是整个对齐策略。
ffmpeg 就是强大的媒体文件转换工具。它可以转换任何格式的媒体文件,并且还可以用自己的 AudioFilter 以及 VideoFilter 进行处理和编辑。
接下来介绍一个解码的实例,该实例实现的功能非常单一,就是把一个视频文件解码成单独的音频PCM文件和视频YUV文件。
AVFormatContext是API层直接接触到的结构体,它会进行格式的封 装与解封装。
该结构体包含的就是与实际的 编解码 有关的部分。
331 av_register_all
所以该函数的内部实现会先调用 avcodec_register_all 来注册所有configh里面开放的编解码器,然后会注册所有的 Muxer 和 Demuxer (也就是封装格式),最后注册所有的 Protocol (即协议层的东西)。
332 av_find_codec
这里面其实包含了两部分的内容:一部分是寻找 解码器 ,一部分是寻找 编码器 。
333 avcodec_open2
该函数是打开编解码器(Codec)的函数,无论是编码过程还是解码过程,都会用到该函数。
avformat_open_input
根据所提供的文件路径判断文件的格 式,其实就是通过这一步来决定使用的到底是哪一个 Demuxer 。
avformat_find_stream_info
该方法的作用就是把所有 Stream 的 MetaData 信息填充好。
av_read_frame
使用该方法读取出来的数据是 AVPacket 。
对于 音频流 ,一个 AVPacket 可能包含 多 个 AVFrame ,但是对于 视频流 ,一个 AVPacket 只包含 一 个 AVFrame ,该函数最终只会返回一个 AVPacket 结构体。
avcodec_decode
该方法包含了两部分内容:一部分是 解码视频 ,一部分是 解码音频 , 解码 是会委托给对应的解码器来实施的。
avformat_close_input
该函数负责释放对应的资源。
avformat_alloc_output_context2
该函数内部需要调用方法avformat_alloc_context来分配一个 AVFormatContext 结构体。
avio_open2
编码的阶段了,开发者需要将手动封装好的 AVFrame 结构体,作为 avcodec_encode_video 方法的输入,将其编码成为 AVPacket ,然后调用 av_write_frame 方法输出到媒体文件中。
本文参考 音视频开发进阶指南
项目源码地址 - FFmpegDecoder
使用C++读取视频文件的拍摄时间可以通过使用FFmpeg库来实现。FFmpeg库提供了一个av_read_frame函数,可以从视频文件中读取帧,并且可以获取每一帧的拍摄时间。此外,还可以使用OpenCV库中的VideoCapture类来读取视频文件,并获取拍摄时间。
最近项目有个需求——给录制的视频按照基准时间添加动态时间戳。
看到这个需求,第一个想到的就是用ffmpeg去转换,百度了一番,基本上都是类似与下面这条命令:
ffmpeg -i 20201124023926196mp4 -vf "drawtext=expansion=strftime:basetime=$(date +%s -d '2020-11-24 16:27:50')000000 :text='%Y-%m-%d %H\\:%M\\:%S':fontsize=18:fontcolor=white:box=1:x=100:y=100:boxcolor=black@05:" -strict -2 -y outmp4
执行后,可以发现时间戳并不是从指定的"2020-11-24 16:27:50"基准时间开始的,这是什么原因呢?于是又从git上查找相关的资料,发现是basetime格式的问题, basetime是int(64)类型的,精确到微秒, 一定要注意这一点。
其它参数说明:
-i: 指定输入文件,这里使用的视频编码是H264, 音频编码是AAC
-vf: 视频滤镜,使用了drawtext滤镜,basetime是视频时间戳的初始值,text是显示时间的格式,fontsize后面一串是关于水印的颜色、字体、背景等设置
-strict -2:AAC的解码在2x版本是试验性功能,需要加这个参数
-y: 覆盖已经存在的输出文件
上篇文章已经配置好FFmpeg的环境变量了
每一帧画面都带有数字标记,非常便于作为原视频调试编解码或者视频处理的帧顺序,可验证转码后的视频帧时间戳是否正常
duration = 视频长度单位秒
最近在看英文字幕的**,听力水平一般,有些字幕对话想多回放几遍。这个是一个比较小众的需求,发现目前的播放器都不支持。于是就想自己实现个有字幕回放功能的播放器。跨平台的开源播放器,比如VLC、MPV,开发的门槛都挺高的。如果能用Electron做播放器的话,添加一些个性的功能,应该会比较简单,写一些html、js就可以。使用Electron制作播放器碰到的最大问题是,H5 <video>标签只支持部分的视频格式。经过一段时间的研究,这个问题已经解决。目前基于Electron的跨平台全能播放器已经实现,并加上了我最想要的字幕对话回放功能。
在Electron应用里,H5 <video>标签支持视频的本地路径。
H5 <video>标签只支持部分的视频格式(mp4、webm和ogg)。需要使用 ffmpeg 支持其他格式的视频文件(mkv、rmvb、flv)。这里可以使用 ffmpeg 的nodejs封装库 fluentffmpeg 。
先使用 ffmpeg 检查视频文件是否可以直接用H5 <video>标签直接播放。
对于H5 <video>标签不支持的格式,需要 ffmpeg 转码。
Electron应用进程分为浏览器渲染进程,和nodejs主进程。nodejs可以启动>
以上就是关于第三章 FFmpeg的介绍与使用全部的内容,包括:第三章 FFmpeg的介绍与使用、c++读视频文件拍摄时间、ffmpeg添加动态时间戳的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)