diff --git a/audio-video-technology/pic/WebRTC1对1音视频实时通话过程示意图.png b/audio-video-technology/pic/WebRTC1对1音视频实时通话过程示意图.png new file mode 100644 index 0000000..856f4ce Binary files /dev/null and b/audio-video-technology/pic/WebRTC1对1音视频实时通话过程示意图.png differ diff --git a/audio-video-technology/pic/getUserMedia-API.png b/audio-video-technology/pic/getUserMedia-API.png new file mode 100644 index 0000000..dee272c Binary files /dev/null and b/audio-video-technology/pic/getUserMedia-API.png differ diff --git a/audio-video-technology/音视频技术.md b/audio-video-technology/音视频技术.md new file mode 100644 index 0000000..6477403 --- /dev/null +++ b/audio-video-technology/音视频技术.md @@ -0,0 +1,211 @@ +# 音视频技术 + + +## 0. 目录 + + + +## 1. 背景 +- 一方面,**视频压缩技术从 H261 到 H264,再到现在的 H265及未来不久将出现的 AV1**,视频压缩率越来越高;**音频压缩技术也从电话使用的 G.711、 + G.722 等窄带音频压缩技术,发展到现代的 AAC、OPUS 等宽带音频压缩技术**。 +- 标准: 所开发的直播系统既可以支持上万人同时在线,又可以进行多人实时音视频互动,此外还可以与固话、MCU等硬件设备互联互通 + +- 音频技术的现在与未来 +- H264/H265、VP8/VP9 以及后面的 AV1 编解码器,解决了视频压缩率的问题;而 5G 的商用,解决了带宽的问题。 +- 尤其是 2011 年 Google 推出 WebRTC 技术后,大大降低了音视频技术的门槛。有了WebRTC,你就**不必自己去实现回音消除算法了**;有了 WebRTC ,你也**不必自己去实现各 + 种音视频的编解码器了**;有了 WebRTC,你更**不必去考虑跨平台的问题了**。因此,可以说WebRTC 的出现大大加速了音视频技术的应用与推广。 +- WebRTC 有个特别有诱惑力的愿景:可以在浏览器上快速开发出各种音视频应用。 + +- 行业及学习痛点 +- 如果你想开发一款音视频产品,**不仅需要有最基础的音视频知识(如音视频的编码、解码),往往还需要多层级的技术栈,涉及移动端开发、PC 端开发、各种协议规范、网络 + 协议、socket 开发**等。所以,要想成为一员合格的音视频开发工程师,你需要对各领域的知识都有一些掌握才行。 + +- 如何学习音视频技术 +- 首先,让你学会如何**使用浏览器相关 API 调用 WebRTC 实现 1 对 1 通话;然后,再逐步深入学习其他音视频知识**。 + +- 主题一:WebRTC 1 对 1 通话 + - 实现WebRTC 1 对 1 通话 +- 主题二:WebRTC 多人音视频实时通话 + - 介绍几种多人音视频实时互动的架构,以及这几种架构的优劣 + - 重点讲解如何使用 SFU 架构实现多人音视频实时通话(SFU 是现在最流行的多人实时互动架构) +- 主题三:支持上万人同时在线的直播系统 + - 支持上万人同时在线的直播系统主要使用 CDN 技术,它是一种比较老的直播架构,使用的底层传输协议是 RTMP 和 HLS。以及如何使用各种播放器从 + CDN 拉取媒体流 + +## 2. WebRTC1对1通话 +- 随着 WebRTC 1.0 规范的推出,现在主流浏览器 **Chrome、Firefox、Safari 以及 Edge** 都已经支持了 WebRTC 库。换句话说,在这些浏览器之间进行实时音视频通信已经很成熟了。 + +- WebRTC 处理过程 +- 在正式讲解如何通过浏览器采集音视频数据之前,我先向你介绍一下 WebRTC 实现一对一音视频实时通话的整个处理过程 +- ![WebRTC 1 对 1 音视频实时通话过程示意图](pic/WebRTC1对1音视频实时通话过程示意图.png) +- 这幅图从大的方面可以分为 4 部分,即**两个 WebRTC 终端**(上图中的两个大方框)、**一个 Signal(信令)服务器**和**一个 STUN/TURN 服务器**。 + - WebRTC 终端,负责音视频采集、编解码、NAT 穿越、音视频数据传输。 + - Signal 服务器,负责信令处理,如加入房间、离开房间、媒体协商消息的传递等。 + - STUN/TURN 服务器,负责获取 WebRTC 终端在公网的 IP 地址,以及 NAT 穿越失败后的数据中转。 +- 描述一下WebRTC 进行音视频通话的大体过程。 + - 当一端(WebRTC 终端)进入房间之前,它首先会检测自己的设备是否可用。如果此时设备可用,则进行**音视频数据采集**。 + - 采集到的数据一方面可以做预览,也就是让自己可以看到自己的视频;另一方面,可以将其录制下来保存成文件,等到视频通话结束后,上传到服务器让用户回看之前的内容。 + - 在获取音视频数据就绪后,WebRTC 终端要发送 “加入” 信令到 Signal 服务器。Signal服务器收到该消息后会创建房间。在另外一端,也要做同样的事情,只不过它不是创建房 + 间,而是加入房间了。待第二个终端成功加入房间后,第一个用户会收到 “另一个用户已经加入成功” 的消息。 + - 在获取音视频数据就绪后,WebRTC 终端要发送 “**加入**” 信令到 Signal 服务器。Signal 服务器收到该消息后会创建房间。在另外一端,也要做同样的事情,只不过它不是创建房 + 间,而是加入房间了。待第二个终端成功加入房间后,第一个用户会收到 “**另一个用户已经加入成功**” 的消息。 + - 此时,第一个终端将创建 “**媒体连接**” 对象,即 **RTCPeerConnection**(该对象会在后面的文章中做详细介绍),并将采集到的音视频数据通过 RTCPeerConnection 对象进行编 + 码,最终通过 P2P 传送给对端。 + - 当然,在进行 P2P 穿越时很有可能失败。所以,当 P2P 穿越失败时,为了保障音视频数据仍然可以互通,则需要通过 TURN 服务器(TURN 服务会在后面文章中专门介绍)进行音 + 视频数据中转。 + - 这样,当音视频数据 “历尽千辛万苦” 来到对端后,对端首先将收到的音视频数据进行解码,最后再将其展示出来,这样就完成了一端到另一端的单通。如果双方要互通,那么,两 + 方都要通过 RTCPeerConnection 对象传输自己一端的数据,并从另一端接收数据。 + +- 音视频采集基本概念 +- 在正式介绍 JavaScript 采集音视频数据的 API 之前,你还需要了解一些基本概念。 + - **摄像头**。用于捕捉(采集)图像和视频。 + - **帧率**。现在的摄像头功能已非常强大,一般情况下,一秒钟可以采集 30 张以上的图像,一些好的摄像头甚至可以采集 100 张以上。我们把**摄像头一秒钟采集图像的次数称为帧** + 率。帧率越高,视频就越平滑流畅。然而,在直播系统中一般不会设置太高的帧率,因为帧率越高,占的网络带宽就越多。 + - **分辨率**。摄像头除了可以设置帧率之外,还可以调整分辨率。我们常见的分辨率有 2K、1080P、720P、420P 等。分辨率越高图像就越清晰,但同时也带来一个问题,即占用的 + 带宽也就越多。所以,在直播系统中,分辨率的高低与网络带宽有紧密的联系。也就是说,分辨率会跟据你的网络带宽进行动态调整。 + - **宽高比**。分辨率一般分为两种宽高比,即 16:9 或 4:3。4:3 的宽高比是从黑白电视而来,而 16:9 的宽高比是从显示器而来。现在一般情况下都采用 16:9 的比例。 + - **麦克风**。用于采集音频数据。它与视频一样,可以指定一秒内采样的次数,称为采样率。每个采样用几个 bit 表示,称为采样位深或采样大小。 + - **轨(Track)**。WebRTC 中的“轨”借鉴了多媒体的概念。火车轨道的特性你应该非常清楚,两条轨永远不会相交。“轨”在多媒体中表达的就是每条轨数据都是独立的,不会 + 与其他轨相交,如 MP4 中的音频轨、视频轨,它们在 MP4 文件中是被分别存储的。 + - **流(Stream)**。可以理解为容器。在 WebRTC 中,“流”可以分为媒体流(MediaStream)和数据流(DataStream)。其中,**媒体流**可以存放 0 个或多个音频 + 轨或视频轨;数据流可以存 0 个或多个数据轨。 + - **媒体流**: 参考 https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia + +- 音视频采集 +- 有了上面这些基本概念,你就可以很容易理解后面所要讲的内容了。接下来,就让我们来具体看看在浏览器下采集音视频的 API 格式以及如何控制音视频的采集吧。 + +- **getUserMedia 方法** +- 在浏览器中访问音视频设备非常简单,只要调用 **getUserMedia** 这个 API 即可。该 API 的基本格式如下: +```js +var promise = navigator.mediaDevices.getUserMedia(constraints); +``` +- 它返回一个 **Promise** 对象。 + - 如果 **getUserMedia** 调用成功,则可以通过 Promise 获得 **MediaStream** 对象,也就是说现在我们已经从音视频设备中获取到音视频数据了。 + - 如果调用失败,比如用户拒绝该 API 访问媒体设备(音频设备、视频设备),或者要访问的媒体设备不可用,则返回的 Promise 会得到 PermissionDeniedError 或 + NotFoundError 等错误对象。 + +- **MediaStreamConstraints 参数** + - 从上面的调用格式中可以看到,**getUserMedia** 方法有一个输入参数 **constraints**,其类型为 **MediaStreamConstraints**。它可以指定 **MediaStream** 中包含哪些类型的媒体轨(音 + 频轨、视频轨),并且可为这些媒体轨设置一些限制。 + - 下面我们就来详细看一下它包括哪些限制,这里我引用一下 WebRTC 1.0 规范对 MediaStreamConstraints 的定义,其格式如下: + - PS: MediaStreamConstraints 详解 https://w3c.github.io/mediacapture-main/getusermedia.html#mediastreamconstraints +```js +dictionary MediaStreamConstraints { + (boolean or MediaTrackConstraints) video = false, + (boolean or MediaTrackConstraints) audio = false +}; +``` +- 从上面的代码中可以看出,**该结构可以指定采集音频还是视频,或是同时对两者进行采集**。 + +- 举个例子,比如你**只想采集视频**,则可以像下面这样定义 constraints: +```js +const mediaStreamContrains = { + video: true +}; +``` +- 或者,同时采集音视和视频: +```js +const mediaStreamContrains = { + video: true, + audio: true +}; +``` +- 其实,你还可以通过 MediaTrackConstraints 进一步对**每一条媒体轨进行限制**,比如下面的代码示例: +```js +const mediaStreamContrains = { + video: { + frameRate: {min: 20}, + width: {min: 640, ideal: 1280}, + height: {min: 360, ideal: 720}, + aspectRatio: 16/9 + }, + audio: { + echoCancellation: true, + noiseSuppression: true, + autoGainControl: true + } +}; +``` +- 上面这个例子表示:视频的帧率最小 20 帧每秒;宽度最小是 640,理想的宽度是 1280;同样的,高度最小是 360,最理想高度是 720;此外宽高比是 16:9;对于音频则是开启回 + 音消除、降噪以及自动增益功能。 +- 除了上面介绍的这些参数来控制摄像头和麦克风外,当然还有其他一些参数可以设置,更详细的参数信息,可以跳到下面的参考部分。 + +- 如何使用 getUserMedia API +- 如何使用上面介绍的 API 来采集视频数据吧 +- 下面的 HTML 代码非常简单,它引入一段 JavaScript 代码用于捕获音视频数据,然后将采集到的音视频数据通过 video 标签播放出来。 +```html + + + + Realtime communication with WebRTC + + + +

Realtime communication with WebRTC

+ + + + +``` +- 为便于你更好地理解该部分的知识,上面这段代码中有两条代码我需要解释一下,一句是: +```html + +``` +- 它是 HTML5 的视频标签,不仅可以播放多媒体文件,还可以用于播放采集到的数据。其参数含义如下: + - **autoplay**,表示当页面加载时可以自动播放视频; + - **playsinline**,表示在 HTML5 页面内播放视频,而不是使用系统播放器播放视频。 +- 另一句是: +```html + +``` +- 它引入了外部的 JavaScript 代码,起到的作用就是获取视频数据。具体代码如下: +```js +'use strict'; + +const mediaStreamContrains = { + video: true +}; + +const localVideo = document.querySelector('video'); + +function gotLocalMediaStream(mediaStream){ + localVideo.srcObject = mediaStream; +} + +function handleLocalMediaStreamError(error){ + console.log('navigator.getUserMedia error: ', error); +} + +navigator.mediaDevices.getUserMedia(mediaStreamContrains).then( + gotLocalMediaStream +).catch( + handleLocalMediaStreamError +); +``` +- JavaScript 代码中首先执行 **getUserMedia()** 方法,该方法会请求访问 Camera。如果是第一次请求 Camera,浏览器会向用户弹出提示窗口,让用户决定是否可以访问摄像头。如果 + 用户允许访问,且设备可用,则调用 gotLocalMediaStream 方法。 +- 在 gotLocalMediaStream 方法中,其输入参数为 **MediaStream** 对象,**该对象中存放着getUserMedia方法采集到的音视频轨**。我们将它作为视频源赋值给 HTML5 的 video 标 + 签的 srcObject 属性。这样在 HTML 页面加载之后,就可以在该页面中看到摄像头采集到的视频数据了。 +- 在这个例子中,**getUserMedia** 方法的输入参数 **mediaStreamContraints** 限定了只采集视频数据。同样的,你也可以采集音频数据或同时采集音频和视频数据。 + +- 总结 +- **MediaTrack和MediaStream**这两个概念特别重要,后续学习 WebRTC的过程中,我们会反复用到,所以在这最开始你就要理解透这两个概念。举个例子,如果你 + 想在一个房间里,同时共享视频、共享音频、共享桌面,该怎么做呢?如果你对 MediaTrack 和 MediaStream 真正理解了,就会觉得 WebRTC 处理这种情况太简单了。 + +- getUserMedia API 控制设备的参数及其含义如下: +- ![getUserMedia-API](pic/getUserMedia-API.png) +- 直接在chrome测试成功,声音不正常(回声很想),加了参数消除回音,还是不行,为什么啊? + - 自己的音频没有mute 吧?把video 标签里加个muted 试试 +- NAT穿越是啥? + - P2P,端与端直接进行连接,不需要服务器中转数据,这样可以节省服务器带宽,但并不意味着不需要服务器,服务器作为辅助功能 +- STUN/TURN 服务器是否有开源的,我之前看到都是使用谷歌的。 + - coturn就可以,大家都用它! +- 如果使用freeswitch在其中作为一个什么角色? + - freeswitch可以做混音服务器,或mcu。不过在直播中,一般用它做服务器混音。 +- 现有的 rtmp 的直播解决方案和 webRTC 之间优劣势在什么地方? + - Rtmp 底层用的tcp,wenrtc底层主要使用udp,使用tcp 就注定他在极端网络情况下没法实时通信 +- 在使用nuxt创建的vue项目中, + 使用ip访问:navigator.mediaDevices.是 undefined + 使用localhost访问:navigator.mediaDevices. 存在 + - 出于安全的原因,你只能用localhost 访问或https 访问时才能检测到mediaDevice + diff --git a/database/mysql/MYSQL必知必会.md b/database/mysql/MYSQL必知必会.md index 04b0749..b82f3e4 100644 --- a/database/mysql/MYSQL必知必会.md +++ b/database/mysql/MYSQL必知必会.md @@ -1925,6 +1925,12 @@ log-error="GJTECH-PC.err" ### 2.6 日志(下):系统故障,如何恢复数据? + + + + + + ### 2.7 数据备份:异常情况下,如何确保数据安全?