Skip to content

音视频编码(直播/云游戏逻辑)

一、直播架构

  • 音频采集 - 麦克风
    • 音频处理:混音 / 降噪 / 声音特效
      • 音频编码
        • AAC:高级音频编码(Advanced Audio Coding)
          • 基于 MPEG-2/4 的音频编码技术
          • 特点: SBR 技术和 PS 技术
  • 视频采集 - 桌面
    • 视频处理:水印 / 美颜 / 滤镜
      • 视频编码:H264 / H265 / H266

二、推流

  • 协议类型: HLS
  • 推流简单来说,就是把正在直播的音视频数据【推送】给服务器
  • 需要压缩

三、拉流(播放)

  • 协议类型: RTMP、RTP、RTSP、HTTP
  • 解码方式:
    • 使用硬解码(对应系统的 API)
    • 或使用软解码(FFMpeg)来解压音视频数据
  • 用户从服务器【获取】直播的音视频数据
  • 需要解压缩

四、视频播放器的工作原理

  1. 解封装
    • 从文件容器中分离音频和视频压缩编码数据
    • 得到 H.264 编码的视频数据和 AAC 编码的音频数据
  2. 解码(分为硬解码、软解码)
    • H.264 编码压缩的视频数据 --> YUV 或 RGB(非压缩)
    • AAC 编码的音频数据 --> 音频数据 PCM(非压缩)
  3. 渲染及音视频同步
    • 将解码出来的音频和视频数据分别送至系统声卡和显卡进行播放
    • 进行音视频同步

五、核心技术点

1)云游戏

  • 与【直播】不同的是,云游戏主要的逻辑集中在【拉流】阶段
    • 简单来说就是:通过【输入交互】来获取特定的【音频流】
  • 核心技术点
    • 解码(硬解码 / 软解码)
      • 未来趋势是使用硬件编码代替软件编码
  • 要解决的核心问题
    • 延迟降低到最小(50ms 以下)
  • 系统实现框图
    • 流化
      • 游戏图像采集
      • 游戏声音采集
      • 音视频编码
      • VM / Container
      • Host OS
    • 传输
      • 数据流
      • 控制信令
      • TCP / UDP
        • UDP: 一旦丢包就会出现花屏
        • TCP: 丢包的话只是出现几百毫秒的卡顿
    • 渲染交互
      • 音视频解码
      • 音视频渲染
      • 输入交互
  • 业务类型
    • 基于 X86 架构,主要解决 PC 游戏云化,即端游云游
    • 基于 ARM 架构,主要解决移动游戏云化,即手游云游

2)H264

  • 图像表达方式
    • RGBA
    • YUV
      • 一张 1920*1080 分辨率的高清图片
        • 192010808*3 个 bit
          • 算下来总共 47Mb
        • 1920*1080 是像素的数量
        • 3 代表的是 RGB 三个值
        • 8bit 则是每个像素值的大小
        • 而: 视频一般都是 30fps (帧每秒)
          • 1 秒钟: 30 * 47Mb = 1.4Gb
  • YUV 编码流程
    • 帧间和帧内预测(Estimation)
    • 变换(Transform)和反变换
    • 量化(Quantization)和反量化
    • 环路滤波(Loop Filter)
    • 熵编码(Entropy Coding)
      • 常用的熵编码有游程编码,哈夫曼编码和 CAVLC 编码等。
      • I 帧:完整编码的帧叫 I 帧
      • P 帧:参考之前的 I 帧生成的只包含差异部分编码的帧叫 P 帧
      • B 帧:参考前后的帧编码的帧叫 B 帧
      • GOP:GOP 即 Group of picture(图像组),指两个 I 帧之间的距离。
  • 原始码流
    • 视频编码层(VCL, Video Coding Layer)
    • 网络提取层(NAL, Network Abstraction Layer)
    • NALU
    • 切片
      • 宏块
      • I 片
      • P 片
      • B 片
      • SP 片(切换 P)
      • SI 片
  • 核心算法
    • 帧内压缩:是生成 I 帧的算法
    • 帧间压缩:是生成 B 帧和 P 帧的算法
  • 为什么拍摄电影时要用【绿幕背景】?
    • 屏幕上的任何一个颜色都可以由一组 RGB 值来记录和表达。 因此这红色绿色蓝色又称为三原色光,用英文表示就是 R(red)、G(green)、B(blue)。
    • 色键分离(简单来说就是【抠图】)
      • 理论上任何色都可以
      • 绿色
      • 蓝色
    • 因为绿色在人身上更少见(西方人眼睛为蓝色)
  • 电视的类型:4K & 8K
    • 子主题 1
    • 子主题 2
  • 开源库

3)硬解码(MSE:Media Source Extensions)

  • 主流网站的视频 video 元素的 src 属性都是 blob 开头的字符串。
    • 流程: Fetch / XHR --> MediaSource(SourceBuffer ) --> <audio> / <video>
    • MediaSource 和 video 元素连接:
      js
      // URL.createObjectURL
      const video = document.querySelector('video')
      const mediaSource = new MediaSource()
      ......
      video.src = URL.createObjectURL(mediaSource)
    • MediaSource API
      • 属性
        • sourceBuffers
        • activeSourceBuffers
        • duration
        • readyState
          • 表示 MediaSource 的当前状态
            • closed
              • 未附着到一个 media 元素上
            • open
              • 已附着到一个 media 元素并准备好接收 SourceBuffer 对象
            • ended
              • 已附着到一个 media 元素,但流已被 MediaSource.endOfStream() 结束
      • 方法
        • addSourceBuffer(mime)
        • removeSourceBuffer(sourceBuffer)
        • endOfStream(endOfStreamError)
        • setLiveSeekableRange(start, end)
        • clearLiveSeekableRange
        • isTypeSupported(mime)
      • 事件
        • sourceopen
          • readyState 从 closed 或 ended 到 open
        • sourceended
          • readyState 从 open 到 ended
        • sourceclose
          • readyState 从 open 或 ended 到 closed

4)软解码(ffmpeg)

  • 前端视频帧提取 ffmpeg + Webassembly
    • 现有的前端视频帧提取主要是基于 canvas + video 标签的方式,在用户本地选取视频文件后,将本地文件转为 ObjectUrl 后设置到 video 标签的 src 属性中,再通过 canvas 的 drawImage 接口提取出当前时刻的视频帧。
    • 子主题 2
  • 实现视频截图
    • 涉及的库
      • libavcodec:音视频的编码和解码。
      • libavformat:音视频的封装和解封装。
      • libavutil:包含一些公共的工具函数的使用库,包括算数运算,字符操作等。
      • libswscale:图像伸缩和像素格式转化。
    • 涉及的组件
      • demuxer:对视频解封装
      • decoder:对视频解码
      • encoder:得到解码后的帧之后,输出图片编码
      • muxer:图片封装

5)webRTC

TODO

6)其他

TODO

FFmpeg / WebRTC / RTMP / RTSP / HLS / RTP

六、开源库

七、参考地址


An image