前言

简单音视频处理。

学习自:

小破站FFmpeg最强教学丨入门FFmpeg看这一篇就够了丨从入门到放弃系列_哔哩哔哩_bilibili

01 下载、配置_哔哩哔哩_bilibili

基础知识

音视频处理基本都是:采样-处理得到帧队列-编码得到包队列-封装得到文件。

视频

一帧视频

RGB:各占8位,因此一个像素点是24位=3B。比如一个1280*720像素的图像,其大小为1280*720*3 B.

YUV:Y 是亮度,UV 指代颜色。存储格式主要有 444 422 420 三种:

音视频开发(一)ffmpeg 简单学习-LMLPHP

YUV422 每两个 Y 共用一个 UV 分量。YUV420 每4个 Y 共用一个 UV 分量:

音视频开发(一)ffmpeg 简单学习-LMLPHP

YUV444:8:8:8=3B。

YUV422:8:4:4=2B。

YUV420:8:2:2=1.5B。

传输会通过一些压缩方式处理:

音视频开发(一)ffmpeg 简单学习-LMLPHP

基本概念

码率:kb/s,单位时间内数据流量,和采样率挂钩。

帧率:fps,一秒多少帧。

分辨率:一幅图像包含像素数。

IPB:视频压缩中的压缩算法。I帧体积最大,解压缩的时候不需要参考其他帧仅靠自己就能重构完整图像,可以由编码器选择决定I帧数量;P帧需要向前寻找可以参考的I/P帧来解压缩;B帧则可以向前或向后寻找预测。

音频

计算机用数字信号模拟现实中连续的声音。

基本概念

采样率:采样频率,每秒采样点个数,如 22KHz。

采样精度:y轴能取到的值数量,精度以位数为单位,如16 bit。

通道:声道。

一定时间长度的音频大小:时长*采样率*采样深度*通道。

比特率:每秒传输数据数,= 采样频率 * 采样精度 * 通道数。

码率: 压缩后的音频数据的比特率。= 音频文件大小/时长。数据越大说明压缩率越低,音质越好。

帧长:1帧的播放时间/压缩后一帧的数据长度。

压缩方式:交错方式,如左右声道 LRLRLR…… 非交错模式,如 LLLL RRRR

压缩技术就是去掉音频中的一些冗余部分,人耳无法识别的来降低数据大小。一方面是人耳真的听不到的,20Hz~20kHz 以外的;另一方面有一些效应影响,比如一个强声音和一个弱声音同时出现,弱声音通常不会被我们听到。这就是掩蔽效应,主要表现为频谱掩蔽效应和时域掩蔽效应。

频谱掩蔽效应:某一个频率上出现了强度很大的声音信号,其周围一定范围频率内的信号如果强度相对小一些,则不容易被听到。

音视频开发(一)ffmpeg 简单学习-LMLPHP

时域掩蔽效应:前掩蔽是出现强信号前的一小段时间内弱信号会被掩蔽;同时掩蔽是强弱信号同时出现的时候弱信号被掩蔽;后掩蔽是强信号小时一段时间内弱信号会被掩蔽.

音视频开发(一)ffmpeg 简单学习-LMLPHP

编码:根据心理声学模型来设置阈值、量化、编码。

封装

视频音频按一定格式算法压缩封装便于播放器播放。比如 MP4 MKV。类似拿着肉馅和皮,包饺子还是包包子。

同步

同步包括:

  • DTS:什么时候解码这一帧。
  • PTS:什么时候显示这一帧。

一般出现B帧的时候两者顺序会不相同。

同步方式:AM 视频同步到音频,VM 音频同步到视频,ECM 两者同步到外部时钟,一般 AM 最多,VM 最不常见。

ffmpeg

基于 MPEG 编码标准的 “Fast Forward” 开源多媒体处理程序。

基本概念

ffmpeg:编码器。

ffplay:播放器。

ffprobe:分析器。

首先,播放器是如何处理音视频数据的?

音视频开发(一)ffmpeg 简单学习-LMLPHP

容器:多媒体文件。

媒体流:时间轴上一段连续数据。

数据帧:编解码的最小单元。

复用器:把视频,音频,字幕流组合起来。

解复用器:按一定规则解开。

封装

音视频开发(一)ffmpeg 简单学习-LMLPHP

avformat_alloc_context() 申请一个AVFormatContext 结构的内存,并进行简单初始化

开始学习

基本使用
$ ffmpeg -h # 查看所有提示信息。还可以后跟 full 等。
$ ffplay 视频/音频文件 # 使用 ffplay 开始播放视频/音频。播放时按下 w 键切换播放窗口的显示
$ ffprobe 视频/音频文件 # 使用 ffprobe 分析查看视频/音频具体信息

$ ffmpeg -i 输入文件 预期输出文件 # 转换格式。比如输入文件是 .mp4,期望输出文件是 .mov
编码

改变编码基本是为了调整存储方式节约存储空间;或者牺牲存储空间获得更好的音质画质。

$ ffmpeg -codecs # 查看所有编码方式

几种不同的封装推荐的编码方式(以下几种是 1080p 及以下质量的封装方案):

mp4:h264 + aac。

webm:vp8 + vorbis(youtube 的方案,软硬件支持程度不高但是为了避开专利问题)。

ogg:theora + vorbis(开源)

$ ffmpeg -i in.flac -acodec libmp3lame -ar 44100 -ab 320k -ac 2 out.mp3
# libmp3lame: mp3 的编码器。或者后跟输出文件是.mp3 格式也是一样的效果、
# -ar: 采样率,如果不设置和默认是一样的。一般常用 4800 和 44100
# -ab: 比特率,默认 128k
# -ac: 通道数
$ ffmpeg -i in.webm -s 1920x1080 -pix_fmt yuv420p -vcodec libx264 -preset medium -profile:v high -level:v 4.1 -crf 23 -acodec aac -ar 44100 -ac 2 -b:a 128k out.mp4
# -s: 分辨率大小
# -pix_fmt: 颜色像素空间,可以通过 ffmpeg -pix_fmts 查询。yuv420p 是网络视频常用
# libx264: h264 的软件编码器
# -preset: 编码器预设。精度越高速度越慢体积越小。默认 medium,录制视频一般 veryfast 存储空间换速度,压制视频一般 veryslow
# -profile:v : 画质级别。实时传输常用 baseline,流媒体常用 main,高清视频常用 high。
# -level:v : 压缩视频级别。
# -crf: 恒定速率模式,控制视频质量(不过无法控制具体文件大小)范围0~51,数值越小质量越高。
# -r: 设置帧率。
# 其他和音频的类似, -b:a 和 -ab 一样

转换完成了可以 ffprobe 测一下看看具体数值。

码率控制:有以下三种。-qbp -crf -b`.

-qp:恒定量化器,把画质转化为参数。参数范围也是0~51,0 是无损,体积很大。

能有多大?我作死试试。

试完回来了。7.60MB 变成 23MB了。

音视频开发(一)ffmpeg 简单学习-LMLPHP

-crf:降低一些码率,来保证画质变化不大。

-b:固定码率模式,这样固定码率和文件大小。一般对文件大小有严格要求时才使用。

以上三种都是单遍编码,好像就是扫描一遍完成编码。因此 qp crf 最好搭配 veryslow 预设,使得参数控制更精准。

比特率编码方式:

  • vbr 可变比特率,比如 -preset。
  • abr 平均比特率,-b:v。不过 abr 码率变化过大,以及用户设备/网络不太好的时候容易造成花屏/黑屏。
  • cbr 恒定比特率,在 abr 基础上加一些限定比如 minrate maxrate 来使得比特率相对恒定。
音视频分离合并
$ ffmpeg -i in.mp4 -vcodec copy -an out.mp4
# vcodec 复制原来的。
# -an 静音,也就是把音频分离出来。
# 同理,-vn 是得到音频。
# 如果有多个音频流,需要选定,比如 -map 0:3 选定 0:3 音频流。
$ ffmpeg -i in.mp4 -i in.m4a copy -c out.mp4
# 如此来合并音视频
音视频截取拼接
$ ffmpeg -i in.mp4 -ss 00:01:00 -to 00:05:00 -vcodec copy out.mp4
$ ffmpeg -i in.mp4 -ss 00:01:00 -t 4 -vcodec copy out.mp4 # 持续时长4s
$ ffmpeg -i in.mp4 -sseof -10 -vcodec copy out.mp4 # 末尾截取10s
$ ffmpeg -ss 00:01:00 -i in.mp4 -to 00:05:00 -vcodec copy out.mp4 # 调换数据,关键帧技术加速处理。但是得到的视频时间不一定准确
$ ffmpeg -ss 00:01:00 -i in.mp4 -to 00:05:00 -vcodec copy -copyts out.mp4 # 保留时间戳,更准确
$ ffmpeg -i "concat:01.mp4|02.mp4|03.mp4" -c copy out.mp4 # 合并视频。不建议合并不同类型数据!
# 可以试试 avidemux,基于 ffmpeg 的另一个开源工具,专用与裁剪合并的。ffmpeg 万能但是底层(就像c语言hh),应用的时候可以多尝试上层技术。
视频截图,添加水印,导出 gif
$ ffmpeg -i in.mp4 -ss 00:05:00 -vframes 1 img.jpg # 5s 处截一张图
$ ffmpeg -i in.mp4 -i logo.png -filter_complex "overlay=20:20" out.mp4 # 距离左上角坐标:20 20 的位置添加此图片水印
$ ffmpeg -i in.mp4 -ss 00:01:00 -to 00:05:00 -s 640x320 -r 15 -out.gif # 导出 gif
屏幕录制
$ ffmpeg -f gdigrab -i desktop rec.mp4
# gdigrab 是 windows 下的录屏工具。不过显示比较多,我 win11 录制失败了。
# 录屏以及录制摄像头推荐工具: obs studio
# 推流:
ffmpeg -re -i rec.mp4 按照网站要求编码 -f flv "my rtmp address/my live stream code"
10-27 22:49