音视频编码(直播/云游戏逻辑)
一、直播架构
- 音频采集 - 麦克风
- 音频处理:混音 / 降噪 / 声音特效
- 音频编码
- AAC:高级音频编码(Advanced Audio Coding)
- 基于 MPEG-2/4 的音频编码技术
- 特点: SBR 技术和 PS 技术
- AAC:高级音频编码(Advanced Audio Coding)
- 音频编码
- 音频处理:混音 / 降噪 / 声音特效
- 视频采集 - 桌面
- 视频处理:水印 / 美颜 / 滤镜
- 视频编码:H264 / H265 / H266
- 视频处理:水印 / 美颜 / 滤镜
二、推流
- 协议类型: HLS
- 推流简单来说,就是把正在直播的音视频数据【推送】给服务器
- 需要压缩
三、拉流(播放)
- 协议类型: RTMP、RTP、RTSP、HTTP
- 解码方式:
- 使用硬解码(对应系统的 API)
- 或使用软解码(FFMpeg)来解压音视频数据
- 用户从服务器【获取】直播的音视频数据
- 需要解压缩
四、视频播放器的工作原理
- 解封装
- 从文件容器中分离音频和视频压缩编码数据
- 得到 H.264 编码的视频数据和 AAC 编码的音频数据
- 解码(分为硬解码、软解码)
- H.264 编码压缩的视频数据 --> YUV 或 RGB(非压缩)
- AAC 编码的音频数据 --> 音频数据 PCM(非压缩)
- 渲染及音视频同步
- 将解码出来的音频和视频数据分别送至系统声卡和显卡进行播放
- 进行音视频同步
五、核心技术点
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
- 192010808*3 个 bit
- 一张 1920*1080 分辨率的高清图片
- 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
- 开源库
- x264 / openh264 / ffmpeg
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() 结束
- closed
- 表示 MediaSource 的当前状态
- 方法
- 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
- sourceopen
- 属性
- 流程: Fetch / XHR --> MediaSource(SourceBuffer ) -->
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
六、开源库
- x264 / openh264 / ffmpeg
七、参考地址
- 007-音频 AAC 编解码详解
- Microsoft 媒体基础
- AAC 文件解析及解码流程
- AAC 解码算法原理详解
- 音视频基础:H264 各种概念
- h.264 语法结构分析
- H264 编码基本原理
- 流媒体视频基础 MSE 入门 & FFmpeg 制作视频预览缩略图和 fmp4
- 全平台硬件解码渲染方法与优化实践