Android中的音视频(1)|青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第7天
前言
关于音视频,我们需要先了解如下的知识
像素
如上的点阵图,每一幅图片都是由若干个不同颜色的点组成的,这其中的每一个点叫做一个像素。其颜色值一般由RGB表示
RGB
所谓RGB,是表示颜色值的的一种格式。其原理也是基于三原色,R G B 分别代表的是Red、Green、Blue,其数值表示对应颜色的强度。这三者每一个的取值范围为:0-255
我们可以在这个网站体验 RGB 的变化 Color Wheel - Color Calculator | Sessions College
其实我们在开发中多使用到的 HEX 值,这是 RGB 的十六进制表示。在上面的网站中,我们小范围拖动浮标,可以看到会有对应一个色域的值是不变的,这也验证了这是基于三原色来创造了RGB值。
分辨率
分辨率是指纵横方向的像素数量,一般是长*宽。如下图所示
较为高端的手机一般也都不会到达 2k,而是介于1080p-2k
,这是因为分辨率越高就意味着手机耗电越大。
若是视频文件的分辨率为 4k ,但是设备并未达到 4k,此时设备渲染该视频时候会将其降采样,所以观影效果是一样的。
码率
码率(比特率)=bit数目/时间(s) (单位:bps)
其表示单位时间内流媒体的bit数目,所以也可以称之为码流。事实上在网络传输中,我们也可以称之为网速
所以高比特率 => 需要高带宽(带宽不高会卡顿),低比特率 => 视频压缩模糊
FFmpeg
FFmpeg
是一个较为著名的视频处理开源工具,很多情况下,我们都会要使用到这个工具。到官网下载解压后配好环境变量,我们就可以使用cmd命令行来分析处理视频了。
ffmpeg :视频处理工具
ffplay:视频播放工具
ffprobe:视频分析工具
将视频压缩指定大小(会截短视频)
ffmpeg -i Desktop/input.mp4 -fs 10MB Desktop/output.mp4
-fs 10 : 表示文件大小最大值为10MB
设置视频的帧率为20fps
ffmpeg -i Desktop/input.mp4 -r 20 Desktop/output.mp4
-r 20:表示帧率设置为 20fps
设置视频的码率
ffmpeg -i Desktop/input.mp4 -b:v 1M Desktop/output.mp4
-b:v :指定视频的码率
-b:a : 指定音频的码率s
1M:码率的值 1M 表示 1Mb/s
设置视频的分辨率
ffmpeg -i Desktop/input.mp4 -s 1920x1080 Desktop/output.mp4
-s 1920x1080表示分辨率为1920x1080
可以结合上面的命令一起来使用
ffmpeg -i Desktop/input.mp4 -s 1920x1080 -b:v 1M -r 20 Desktop/output.mp4
上面的代码块,里面含有几种压缩视频的命令,大家可以尝试一下。
用 ffmpeg 压缩视频 - 知乎 (zhihu.com)
FFmpeg—-图片处理_ffmpeg压缩图片_mytzs123的博客-CSDN博客
帧率
帧:指的是视频或者动画中的每一张画面,视频或者动画就是由一张张画面所组成。(例如胶片)
帧率:每秒的帧数。帧数越高,画面越流畅
FPS:刷新率,当刷新率太低,会感到屏幕不连贯。
当然,刷新率要匹配上帧率才能看到对应的流畅效果
视频封装
当下的音视频都不是分离的,视频都会带有音频。事实上这两者在底层文件中是分离的,只是我们将其封装了起来,播放的时候就是同步播放的。
封装:简单来说,就是将已经编码压缩好的视频轨和音频轨按照一定的格式放到一个文件中。再通俗点,视频轨相当于饭,而音频轨相当于菜,封装格式就是一个饭盒,用来盛放饭菜的容器。
目前主要的视频容器有如下: MPG、VOB、MP4、3GP、ASF、RMVB、WMV、MOV、Divx、MKV、FLV、TS/PS等
那么他们不同的轨道是如何查看的呢?
下面我们用 ffprobe xxx.mkv
这个命令查看一下视频的信息
Input #0, matroska,webm, from 'D:\系统文件\下载\Video\Tar.mkv':
Metadata:
LANGUAGE : und
COMPATIBLE_BRANDS: isomiso2avc1mp41
MAJOR_BRAND : isom
MINOR_VERSION : 512
HANDLER_NAME : AudioHandler
ENCODER : Lavf59.27.100
Duration: 00:05:16.26, start: 0.000000, bitrate: 304 kb/s
Stream #0:0: Video: h264 (High), yuv420p(tv, bt709/unknown/unknown, progressive), 854x480 [SAR 1:1 DAR 427:240], 29.97 fps, 29.97 tbr, 1k tbn (default)
Metadata:
ENCODER : Lavc59.37.100 libx264
DURATION : 00:05:16.249000000·
Stream #0:1: Audio: vorbis, 48000 Hz, stereo, fltp (default)
Metadata:
ENCODER : Lavc59.37.100 libvorbis
DURATION : 00:05:16.261000000
上面得到的结果可以看到时长,比特率信息。以及两个流,一个是Video,一个是Audio;对应的流也可以看到其参数信息
较为简单的一类视频就是包含了一个视频轨,一个音频轨。但是在大型的电影类视频中,是有着多类型、多语言的音轨以及多种字幕流。
这个是电影原盘的数据,我们可以看到上面包含多种文件
一个视频流
多条音频流
多条字幕流
在网络直播或者网络播放的时候,我们可以选择把不必要的轨道去掉,可以节省流量。同时字幕流也可以全部去掉,字幕可以内嵌在视频上面或者作为外挂字幕同步播放。(其中,7.1或者5.1指的是几个喇叭的杜比音效)
音视频流是分一个个包的,接下来我们用 ffprobe -show_packet xxx.mkv
查看一下媒体的数据包的信息
[PACKET]
codec_type=audio
stream_index=1
pts=170169
pts_time=170.169000
dts=170169
dts_time=170.169000
duration=21
duration_time=0.021000
size=248
pos=6426569
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=170203
pts_time=170.203000
dts=170170
dts_time=170.170000
duration=33
duration_time=0.033000
size=64
pos=6426823
flags=__
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=170190
pts_time=170.190000
dts=170190
dts_time=170.190000
duration=21
duration_time=0.021000
size=230
pos=6426894
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=170370
pts_time=170.370000
dts=170203
dts_time=170.203000
duration=33
duration_time=0.033000
size=711
pos=6427131
flags=__
我们可以看到音轨和视频轨是交错排布的,是混流的。
选用混流存储而不是一前一后存储的原因是为了数据的同步。
音视频虽然是两个数据流独立存在的,但两个流封装之后的数据是按顺序下载的,为满足在线观看的效果,就需要数据交错排布。否则就会出现卡顿或者音画不同步。
视频压缩
若是视频未压缩,一个时长接近两个小时,分辨率为4k的视频,其大小会超过400GB。所以视频的压缩是尤为重要的。
颜色空间
YUV色彩空间不同于RGB,是另一种颜色数字化的表达方式,由于RGB不利于压缩,所以在视频系统中多会采用的是YUV。YUV体系中,不同于RGB的是,其有一个亮度的概念,其中Y表示色度,U和V表示亮度。由于人对亮度的敏感程度要大于色度,所以我们可以通过着重于提升亮度,减低色度,从而达到不降低分辨率的同时压缩视频的效果。
YUV 其实目前有 三种分类:
1,YIQ 适用于NTSC彩色电视制式
2,YUV 适用于PAL和SECAM彩色电视制式
3,YCrCb 适用于计算机用的显示器
我们做互联网音视频开发, 一般说的 YUV 是 指 YCbCr ,U 就是 Cb,V 就是 Cr。
大家经常在一些音视频书籍看到 YCbCr ,把它当成是 YUV 就行。实际上 YCbCr 才是比较准确的术语,JPEG、MPEG 标准 用的也是 YCbCr
上图的第一张是原图,下面的三张分别是 Y Cb Cr。这张图是并未降低色度进行降采样的,事实上我们把色度降采样后拼起来的原图效果是一样的。
YUV采样格式的压缩
帧内压缩
帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。
当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,达不到很高的压缩比。
如上图,将图片分为多个小方块,对于色值相同的小方块,我们只需要记录一个小方块的数据,其他的就引用该方块的数据即可。
帧间压缩
帧间压缩(Interframe compression)也称为时间压缩(Temporal_compression),是基于许多视频或动画的
连续前后两帧具有很大的相关性(即连续的视频其相邻帧之间具有冗余信息)的特点来实现的。
通过比较时间轴上不同帧之间的数据实施压缩,进一步提高压缩比.一般是无损压缩。
=>对于画面中静态的不去记录处理它,只去记录变化的画面,称之为记录残差。在呈现的时候,叠加残差值即可获得后面的帧的画面了。
帧的编码类型
I-frame:Intra-frame 帧内帧 (不会依赖其他帧,靠自己就能绘制出完整的画面,压缩比小)
P-frame:Predicted Frame 前向预测帧 (依赖前面的帧,叠加残差值绘制出画面,压缩比较高)
B-frame:Bi-Directional frame (双向预测帧,参考前后的帧)
由于B帧可以参考和插入在它之前和之后发生的两个(或更多)帧(在时间维度上),所以它可以显著降低帧的大小,同时保持视频质量。B帧能够利用空间冗余和时间冗余(未来的帧和过去的帧),这使得它在视频压缩中非常有用。
上图中的第一行数字是帧展示的顺序,第二行数字是帧的解码顺序。上图我们就可以看到,先解码I帧后,就去解码了第四个位置的p帧,然后中间的P帧就依赖这两个前后帧来进行解码。(解码顺序:I->P->B)
当拖动进度条,视频改变播放进度后,如果不在同一个 GOP 中,需要从新位置所在的 GOP 的 I 帧开始解码(一定是从I帧开始解码的)
拖动后起播所需的耗时取决于位置在 GOP 中的位置,越靠前能越快响应
不同场景对 GOP 的设置
视频点播:节省带宽,高压缩率,会使用 B 帧
直播:低延迟,不使用 B 帧
视频编辑:提高响应,个别会使用全 I 帧
视频编码格式
现下的编码格式(后者压缩比都比前者提高一倍)有:
H265 压缩比更高,需要更多的算力
H264 : AVC 更普及
H265 : HEVC 更小体积
参考
Color Wheel - Color Calculator | Sessions College
【Android 客户端专场 学习资料二】第四届字节跳动青训营 - 掘金 (juejin.cn)
ffprobe常用命令_我有两颗星星的博客-CSDN博客_ffprobe命令