leandromoreira /ffmpeg-libav-tutorial
FFmpeg libav tutorial - learn how media works from basic to transmuxing, transcoding and more. Translations: 🇺🇸 🇨🇳 🇰🇷 🇪🇸 🇻🇳 🇧🇷 🇷🇺
★ 11,063⑂ 1,010👁 267⑃ 58● 88▤ 1
11,063
stars
+0+1+13
1,010
forks
267
watchers
58
prs
88
issues
1
releases
–
discussions
README
起初我在寻找可以学习使用FFmpeg库(又名 libav)的教程或书籍,然后找到了名为"如何在1k行代码内实现视频播放器"的指南。但该项目已经停止维护,因此我决定撰写此教程。
此项目主要使用C语言开发,但请不用担心:项目内容非常通俗易懂。FFmpeg libav具有许多其他语言的实现,例如python,go。即使其中没有你熟悉的编程语言,仍然可以通过 ffi 为它提供支持(这是一个 Lua 的示例)。
下文将会简单介绍什么是视频、音频、编解码和容器,然后我们将尝试使用 FFmpeg 命令行工具,最终使用代码实现一些功能。如果你拥有一些经验,可以随时跳过这些内容,直接阅读 笨办法学 FFmpeg libav 章节。
许多人认为网络视频流媒体是传统 TV 的未来。无论如何,FFmpeg 值得我们深入学习。
__目录__
介绍
视频 - 目光所见
音频 - 耳朵所听
编解码 - 压缩数据
容器 - 整合音频和视频
FFmpeg - 命令行
FFmpeg 命令行工具 101
通用视频操作
转码
转封装
转码率
转分辨率
自适应流
更多
笨办法学 FFmpeg libav
章节0 - 臭名昭著的 hello world
FFmpeg libav 架构
章节1 - 音视频同步
章节2 - 重新封装
章节3 - 转码
介绍
视频 - 目光所见
如果以一定的频率播放一组图片(比如每秒24张图片),人将会产生视觉暂留现象。
概括来讲,视频的本质就是: 以给定频率播放的一系列图片/帧.
当代插画 (1886)
音频 - 耳朵所听
尽管一个没有声音的视频也可以表达很多感受和情绪,但加入音频会带来更多的体验乐趣。
声音是指以压力波形式通过空气或其他介质(例如气体、液体或者固体)传播的振动。
在数字音频系统中,麦克风将声音转换为模拟电信号,然后通常使用脉冲编码调制(PCM)的模数转换器(ADC)将模拟信号转换为数字信号。
!audio analog to digital
图片来源
编解码 - 压缩数据
CODEC是用于压缩或解压缩数字音频/视频的硬件或软件。 它提供将原始(未压缩的)数字音频/视频与压缩格式相互转换的能力。
https://en.wikipedia.org/wiki/Video_codec
如果我们选择打包数百万张图片来生成一个视频文件,那么该文件的大小将会非常惊人。让我们来计算一下:
假如我们创建一个 1080x1920 (高x宽)的视频,每个像素占用 3 bytes 对颜色进行编码(或使用 24 bit 真色彩, 这可以提供 16,777,216 种不同的颜色),每秒 24 帧,视频时长为 30 分钟。
c
toppf = 1080 1920 // 每帧所有的像素点
cpp = 3 // 每个像素的大小(bytes)
tis = 30 60 // 时长(秒)
fps = 24 // 每秒帧数
required_storage = tis fps toppf cpp
计算结果显示,此视频需要大约 250.28G 的存储空间或 1.19Gbps 的带宽。这就是我们为什么需要使用 CODEC 的原因。
容器 - 整合音视频
容器或者封装格式描述了不同的数据元素和元数据是如何在计算机文件中共存的。
https://en.wikipedia.org/wiki/Digital_container_format
单个这样的文件包含所有的流(主要是音频和视频),并提供同步和通用元数据,比如标题、分辨率等等。
一般我们可以通过文件的后缀来判断文件格式:比如 video.webm 通常是一个使用 webm 容器格式的视频。
!container
FFmpeg - 命令行
这是一个完整的跨平台解决方案,可用于音视频的录制、转换和流式传输等。
我们使用非常优秀的工具/库 FFmpeg 来处理多媒体文件。你可能对它有些了解,也可能已经直接或者间接的在使用它了(你用过 Chrome 吗?)
ffmpeg 是该方案中简单而强大的命令行工具。例如,可以通过以下命令将一个 mp4 文件转换成 avi 格式:
bash
$ ffmpeg -i input.mp4 output.avi
通过上述步骤,我们做了一次重新封装,从一个容器转换为另外一个容器。FFmpeg 也可以用于转码,我们稍后再针对它进行讨论。
FFmpeg 命令行工具 101
FFmpeg 有一个非常完善的文档来介绍它是如何工作的。
简单来说,FFmpeg 命令行程序需要以下参数格式来执行操作: ffmpeg {1} {2} -i {3} {4} {5},分别是:
1. 全局参数
2. 输入文件参数
3. 输入文件
4. 输出文件参数
5. 输出文件
选项 2、3、4、5 可以可以根据自己的需求进行添加。以下是一个易于理解的示例:
bash
警告:这个文件大约 300MB
$ wget -O bunny_1080p_60fps.mp4 http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_60fps_normal.mp4
$ ffmpeg \
-y \ 全局参数
-c:a libfdk_aac \ 输入文件参数
-i bunny_1080p_60fps.mp4 \ 输入文件
-c:v libvpx-vp9 -c:a libvorbis \ 输出文件参数
bunny_1080p_60fps_vp9.webm 输出文件
这个命令行作用是将一个 mp4 文件(包含了 aac 格式的音频流,h264 编码格式的视频流)转换为 webm,同时改变了音视频的编码格式。
我们可以简化上述命令行,但请注意 FFmpeg 会猜测或采用默认值。例如我们仅输入 ffmpeg -i input.avi output.mp4 时,FFmpeg 会使用哪种音频/视频编码来生成 output.mp4 呢?
Werner Robitza 写了一篇 关于 ffmpeg 编码和编辑的教程。
通用视频操作
在处理音频/视频时,我们通常会执行一系列操作。
转码
!transcoding
是什么? 将其中一个流(视频流或音频流)从一种编码格式转换成另一种
为什么? 有时候有些设备(TV,智能手机等等)不支持 X ,但是支持 Y 和一些更新的编码方式,这些方式能提供更好的压缩比
如何做? 转换 H264(AVC)视频为 H265(HEVC)
bash
$ ffmpeg \
-i bunny_1080p_60fps.mp4 \
-c:v libx265 \
bunny_1080p_60fps_h265.mp4
转封装
!transmuxing
是什么? 将视频/音频从某一种格式(容器)转换成另一种
为什么? 有时候有些设备(TV,智能