webrtc-采集基础知识

音视频采集

基础知识

摘自 李超 - 从 0 打造音视频直播系统

非编码帧

好多人小时候应该都学过,在几张空白的纸上画同一个物体,并让物体之间稍有一些变化,然后连续快速地翻动这几张纸,它就形成了一个小动画。音视频播放器就是利用这样的原理来播放音视频文件的。

当你要播放某个视频文件时,播放器会按照一定的时间间隔连续地播放从 音视频文件解码后的视频帧,这样视频就动起来了。同理,播放从 摄像头获取的视频帧 也是如此,只不过从 ==摄像头获取的是非编码视频帧,不需要解码。==

通过上面的描述,你应该能得到以下两点信息:

  1. 播放的视频帧之间的时间间隔是非常小的。如按每秒钟 20 帧的帧率计算,每帧之间的间隔是 50ms(1000ms/20)。
  2. 播放器播的是非编码帧(解码后的帧),这些非编码帧就是一幅幅独立的图像。
  3. 摄像头里采集的帧通过解码器解码后的帧 都是非编码帧。非编码帧的格式一般是 YUV 格式或是 RGB 格式。

编码帧

通过编码器(如 H264/H265、VP8/VP9)压缩后的帧称为编码帧。

  • 以 H264 为例,经过 H264 编码的帧包括以下三种类型。
    • I 帧:关键帧。压缩率低,可以单独解码成一幅完整的图像。
    • P 帧:参考帧。压缩率较高,解码时依赖于前面已解码的数据。
      • P帧需要参考其前面的一个I帧或者P帧来解码成一张完整的视频画面。
    • B 帧:前后参考帧。压缩率最高,解码时不光依赖前面已经解码的帧,而且还依赖它后面的 P 帧。换句话说就是,B 帧后面的 P 帧要优先于它进行解码,然后才能将 B 帧解码。
      • B帧则需要参考其前一个I帧或者P帧及其后面的一个P帧来生成一张完整的视频画面,所以P帧与B帧去掉的是视频帧在时间维度上的冗余信息

从播放器里获取的视频帧一定是非编码帧。也就是说,拍照的过程其实是从连续播放的一幅幅画面中抽取正在显示的那张画面

借助 canvas 进行拍照

  1. 借助 cancas drawImage 绘制 video 中的视频流 : picture.getContext('2d').drawImage(video, 0, 0, picture.width, picture.height);
    • image:可以是一幅图片,或 HTMLVideoElement。
    • dx, dy:图片起点的 x、y 坐标。
    • dWidth:图片的宽度。
    • dHeight:图片的高度
  2. 通过 Canvas 的 toDataURL 方法获得图片的 URL 地址:picture.toDataURL("image/jpeg"),在使用 a 标签等 进行下载