小插曲
小编平时也喜欢拍摄和剪辑,最近换了一台主打电竞的vivo iqoo13的手机,但拍照和摄影效果也不错,额······偏题了,说正事。最近用手机拍了一些视频,想传到电脑上剪辑,一般我喜欢用windows自带的Media Player媒体播放器预览视频,但是发现Media Player播放不了这些视频,只有声音,类似下面这样。
我开始以为是传输出错了,但是删了重新传还是没解决。后面我换了一个第三方的媒体播放器打开,提示我需要下载HEVC视频的编解码器。
此时我终于明白为什么windows自带的媒体播放器播放不了这些视频了,原来iqoo13手机拍的视频是采用HEVC编码格式存储的,而windows自带的传统播放器不支持HEVC编码的视频播放,具体说就是windows自带的播放器不支持对HEVC编码的解码。其实现在主流的播放器都支持HEVC编码格式的视频的,换其他播放器就可以了,例如腾讯、爱奇艺等自带的播放器。
为了跟我同是天涯沦落人的小伙伴的问题得到解决,下面我先说明一下如何使用FFmpeg工具查看视频编码信息和转换编码格式,主要是因为FFmpeg是开源免费的哟,这下就不用再花钱去用那些视频格式转换软件了。视频编码的简述放后面,有兴趣的小伙伴可以了解一下,具体的编码原理太深奥,大家可以自己去查阅资料了解。
1 FFmpeg工具使用
FFmpeg是一套可以用来记录、转换数字音频、视频的多媒体处理程序,是一个开源的框架。它几乎支持市面上已知的音频和视频格式,包括容器格式和编码格式等,并提供了丰富的命令行工具等来处理多媒体文件。下面主要以windows系统为例,介绍FFmpeg的使用。
1.1 FFmpeg下载与安装
打开FFmpeg的官网,FFmpeg的官网链接:https://ffmpeg.org/。按下面步骤下载安装包
上面的release-full版本是最新预发布的稳定版本,下面full-build是已发布版本,都可以下载。可以看到同一个版本有带shared后缀和不带的,带shared的是带共享库的,初学者无需深入了解,只需要知道带shared和不带shared的安装包在功能上都一样,只不过带shared的安装包多了include和lib两个目录,include目录放的是引用的.h头文件,lib目录放的是FFmpeg依赖的模块包,当bin目录下ffmpeg.exe、ffplay.exe和ffprobe.exe可执行文件运行时,可以调用lib中相关模块的功能。
下载后的安装包直接解压就可以使用,解压后在根目录的bin目录下有ffmpeg.exe、ffplay.exe和ffprobe.exe三个可执行程序,是可以直接调用的入口程序,它们的功能分别如下:
ffmpeg.exe :功能强大的处理音视频文件的软件,可以实现音视频的录制、转码、剪辑、合成等功能。
ffplay.exe:FFmpeg自带的播放器工具,基于 SDL 与 ffmpeg 库实现,提供了音视频显示和播放相关的图像信息和音频波形信息等,可以播放本地文件或者网络流媒体。
ffprobe.exe:FFmpeg自带的多媒体信息检测工具,可以获取多媒体文件的音频视频容器参数的详细信息,如分辨率、编码格式、时长等。
为了可以全局调用这三个程序,而不是要慢慢转到bin目录下调用,我们可以给FFmpeg的bin目录添加到系统环境变量:
只需命令行运行“ffmpeg -version”,若打印类似如下的信息,则环境变量设置成功。
添加了环境变量后,可以直接在任意路径下运行ffmpeg、ffplay和ffprobe命令了。
1.2 FFmpeg视频处理
这里简单说一下,我们平时常见的mp4、avi、flv、mov等文件后缀名,是封装音视频数据的容器格式,本文开头提到的HEVC是一种高效视频压缩编码标准,也称H.265,是H.264的升级版。常见的视频编码格式有VAC(H.264)、HEVC(H.265)、VVC(H.266)、MPEG系列等。下面是FFmpeg常见的一些视频转码和剪辑的简单操作。
(1)视频信息查看
ffmpeg -i input.mp4
上面参数-i指定输入文件,输入文件是input.mp4。使用上面命令可以查看视频的编码格式、分辨率、码率和帧率等信息。
使用这个命令查看我上传到电脑的视频的相关信息如下(我下面都是在视频所在路径下运行的,所以就没带路径了)
可以看到我的视频格式确实是HEVC格式,所以windows自带的媒体播放器播放不了。还可以看到视频的分辨率是1920×1080,码率是4132kb/s,帧率是29.62fps等。
(2)容器格式转换
将AVI格式文件文件转换为MP4文件,并指定视频编码格式为H.264(libx264)和音频编码为AAC,如下
ffmpeg -i input.avi -c:v libx264 -c:a aac output.mp4
其参数解释如下:
-i input.avi:指定输入文件为input.avi
-c:v lib指定视频编码器为libx264,即使用H.264编码,":"后的"v"是video(视频)的首字母
-c:a aac:指定音频编码器为AAC,":"后的"a"是audio(音频)的首字母
这里的-c:后的v和a是用来区分是视频编码还是音频编码的。
当然,如果这里不指定编码格式的话,将以原编码格式输出。
(3)编码格式转换
如果要在保持容器格式不变的情况下改变编码格式,只需要输出文件的容器格式跟原输入文件的容器格式一样就可以。例如将inpu.mp4的视频编码格式转换为H.264如下
ffmpeg -i input.mp4 -c:v libx264 output.mp4
所以我尝试将我的视频编码格式转换为H.264格式,看看windows自带的媒体播放器能不能播放,命令运行如下
可以看到我文件夹里的video_20250413_080559.mp4文件对应的输出文件是video_20250413_080559_bak.mp4,转换编码格式后的视频文件也可以正常显示封面了。(由于视频文件的默认打开方式我设置成了windows自带的媒体播放器,所以其他没转码的视频是不能正常显示封面的)
然后我试了,windows自带的媒体播放器也能正常播放了。
(4)时间剪辑
时间剪辑本质上是视频帧的操作,时间剪辑的部分命令示例如下:
将一个FLV视频从3分14秒159毫秒开始,持续10秒,并输出转封装至MP4格式,持续10秒即剪切10秒
ffmpeg -ss 3:14.159 -t 10 -i input.flv -c copy output.mp4
-ss:设置媒体文件的起始时间
-t:设置媒体文件的持续时间
将一个MP4文件从3分14秒159毫秒剪切到第10秒
ffmpeg -ss 3:14.159 -to 10 -i input.mp4 -c copy output.mp4
-to:设置媒体文件的截止时间
注意上面的-to和-t选项是互斥的,所有不能同时使用,若同时使用,-t的优先级大于-to,即同时出现时只有-t生效,并且使用-to时一定要写在-i前面。通常将-ss、-t和-to都放在-i之前,以防混乱。
FFmpeg的功能很多,这里只是列举了部分常用命令,本文旨在引导大家获取FFmpeg工具和了解学习FFmpeg,更多关于FFmpeg的使用可以上官网了解或查阅更详细的介绍资料。
1.3 ffmpeg-python简介
python社区也提供了一个处理多媒体文件的强大的库ffmpeg-python,对于FFmpeg命令行的功能,我们都可以通过ffmpeg-python的提供的函数来实现。先安装ffmpeg-python
pip install ffmpeg-python
下面简单列举几个场景的使用:
(1)查看视频文件信息
import ffmpeg
info = ffmpeg.get_media_info("video.mp4")
print(info)
(2)转换视频容器格式
import ffmpeg
input_file = "video.mp4"
output_file = "video.avi"
ffmpeg.input(input_file).output(output_file).run()
(3)转换视频编码格式
import ffmpeg
input_file = 'input.mp4'
output_file = 'output.mp4'
ffmpeg.input(input_file).output(output_file, vcodec='hevc').run()
(4)合并多个视频
import ffmpeg
input_files = ["video1.mp4", "video2.mp4", "video3.mp4"]
output_file = "output.mp4"
ffmpeg.concat(*input_files).output(output_file).run()
2 视频编码简述
2.1 为什么要编码?
视频为什么要编码呢?先不说视频编码,举个简单的例子,计算机在存储一个浮点数时,如果每一位数字我们都去记录它, 那么存储一个浮点数的内存可能会相当大,例如浮点数-0.0...0125(125前面有很多0并且都是0),转换为二进制后是一段相当长的数字,而每一位二进制数就是一个存储单元,这样内存消耗就相当大。但是我们把-0.0...0125用科学计数法表示成-1.25*10^n,n是指数,我们发现只需关注符号、有效数字1.25和指数n这三个标准就可以表示-0.0...0125了,也就是说只需要存储这三个数据就可以存储一个很大或者很小的数了。把这个数值转换为以这三个标准存储的方式的这个过程称为编码,然后我们读取这个数的时候,只需要按照对应规则计算出来就可以了,这个过程称为解码。
编码是将信息从一种形式转换为另一种形式的过程,是计算机科学中一个重要的概念,简单可以概括为将信息转换为机器可以处理的格式。编码是一种让数据更容易存储、传输和处理的方式,其根本目的是为了更有效的保存和传输信息。编码的种类也分很多,根据不同的应用场景,以及数据的特性,可以分为压缩编码、数据编码、网络编码、缓冲区编码、加密和解密等。上面提到的浮点数的存储属于数据编码,现在计算机对浮点数的存储主要遵循IEEE 754标准的编码规则,而前面提到的HEVC视频编码属于压缩编码的一种。
我们知道,视频也是由一张张图像组成的,一张图像称为1帧。例如一张1920×1080分辨率的高清图片,也就是由1920×1080个像素组成的图片,而存储这样一张图片,我们一共需要1920×1080×8×3bit的存储空间(1bit就是一个存储空间)。这里的3表示的是RGB色彩空间的三个值R(红)、G(绿)、B(蓝),8是这3个值中每个存储占用的空间大小(也就是8bit,从00000000~11111111,十进制下就是0~255)。这样一张图片,算下来大约是47Mb(兆比特),现在视频的播放速度一般是30fps(帧每秒),按刚刚的图片大小计算,也需要大约1.4Gb的带宽。而普遍的网络带宽在几百M,最高可到1000M左右,其中1M就是1Mbps(兆比特每秒),这样的带宽的传输这样大内存的视频是远远不够的,也就是传输1秒的视频内容也需要很长的时间。可以看出,这样的视频所包含的信息量是很大的,显然现在的网络情况是无法正常满足这样的视频传输的,所以必须对视频进行压缩编码,这样可以让视频在网络传输时节省传送宽带和加快视频传输速度,也能节省视频在本地的存储空间。
2.2 视频编码标准
现在的视频编码标准主要来源于由国际标准组织机构ISO下属的运动图象专家组MPEG,和国际电传视讯联盟ITU,分别推出了MPEG系列和H.26X系列的视频压缩标准。
下面是列举的一些视频编码标准
主流国际标准
H.264/VAC:2003年发布,ITU-T与ISO/IEC联合制定,目前还在被广泛应用。
H.265/HEVC:2013年发布,比H.264标准更有效的压缩编码技术,压缩效率较H.264提升50%,支持4K/8K超高清视频和HDR(高动态范围),但硬件性能要求更高且专利费用较高。
H.266/VVC:2020年发布,这是H.26x系列目前最新的标准,压缩效率较H.265再提升50%,支持更广泛的分辨率和动态范围,未来将应用于8K视频和高动态范围场景。
中国自主标准
AVS系列:由中国AVS工作组制定,AVS3(2021年完成)被纳入国际DVB规范,支持高动态和神经网络编码扩展,压缩效率接近H.266。但编码复杂度高,硬件支持尚未普及。
其他标准
MPEG系列:如MPEG-2(DVD)和MPEG-4 Part 2(早期网络视频),兼容性高但效率较低。
VP9/AV2:谷歌主导的开放标准,面向流媒体优化,但生态支持有限。
2.3 视频编码过程简述
视频从采集(拍摄)到显示(播放)大致可以分为下面几个步骤:
视频编码主要用于两个主要方向:
实时传输。视频编码在实时传输中的应用包括网络推流、视频通话和在线直播等。在这些场景中,视频编码器需要将视频数据实时传输到接收端,因此需要低延迟和高稳定性。实时传输通常要求编码器能够快速处理视频数据,并适应网络波动,确保视频流的连续性和稳定性。
本地视频文件。在本地视频文件的制作和存储中,视频编码主要用于生成高质量的视频文件,如MP4、AVI等格式的文件。这些文件通常需要在本地存储和播放,因此更注重文件的压缩效率和存储空间的使用。本地视频文件编码需要更高的压缩比和更好的图像质量,以满足用户对视频质量的需求。
视频编码本质上是对每帧画面里的像素信息进行编码,而像素信息就是像素的颜色信息,一个像素信息可以用RGB值来表示,这是最常见的表示颜色的方式,但在数字图像处理上,颜色还可以用YUV色彩空间来表示,其中,Y是明亮度,用来表示像素的灰度值,U、V分别是影像色彩与饱和度,用来表示像素的颜色。RGB和YUV的转换公式如下
RGB每个像素需存储完整的R、G、B值,共占8*3=24bit的空间,数据量大。分辨率为1920×1080的一帧大约需要5.96MB的空间。 而YUV支持采样压缩(如4:2:0),每4个像素共享一组UV,单像素数据量降至12bit,相同分辨率为1920×1080的帧仅需2.98MB,压缩率提升50%。
所以,在视频压缩编码中,不直接采用RGB值作为输入,而是采用YUV值作为输入。
综上所述,大致的视频编码流程如下:
值得注意的是,封装成MP4等格式的视频文件时,是结合音频一起封装的。