Jansiel Notes

WebRTC 入门笔记

WebRTC(Web Real-Time Communication)为现代网络应用提供了实时通信的能力。这项技术使得在不需要安装任何插件或第三方软件的情况下,用户可以通过网页浏览器进行音视频通话和数据共享。以下是一个结合了API介绍和实践案例的基础入门文章。

核心特性及API介绍

数据通道(Data Channels)

WebRTC 允许你创建数据通道来发送任意类型的数据。这可以通过 RTCDataChannel API 实现,该 API 提供了一个双向通道来传输数据。

1// 假设已经建立了 RTCPeerConnection
2let dataChannel = peerConnection.createDataChannel("myDataChannel");
3
4dataChannel.onopen = function(event) {
5  dataChannel.send("Hello WebRTC!");
6};
7

信令(Signaling)

虽然 WebRTC API 不直接处理信令,但它提供了所需的所有钩子来交换信令消息。你可以使用 WebSocket、Server-Sent Events 或任何其他服务器端技术来交换这些信息。

 1// 在A端
 2peerConnection.onicecandidate = function(event) {
 3  if (event.candidate) {
 4    // 通过信令服务器发送候选信息到B端
 5    sendToServer({
 6      type: 'new-ice-candidate',
 7      candidate: event.candidate
 8    });
 9  }
10};
11
12// 在B端
13peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
14  .catch(e => console.error(e));
15

媒体捕获和流(MediaStream API)

WebRTC 使用 navigator.mediaDevices.getUserMedia 来捕获音频和视频。

1// 捕获视频和音频流
2navigator.mediaDevices.getUserMedia({ audio: true, video: true })
3  .then(function(stream) {
4    /* 使用这个流 */
5  })
6  .catch(function(err) {
7    /* 处理错误 */
8  });
9

媒体处理

WebRTC 自动处理编解码和其他媒体处理需求。但是,你可以通过 RTCRtpSenderRTCRtpReceiver 接口来获取媒体轨道的详细控制。

1// 获取音视频轨道
2const tracks = stream.getTracks();
3tracks.forEach(function(track) {
4  peerConnection.addTrack(track, stream);
5});
6

安全性

WebRTC 通信是通过 DTLS(数据报传输层安全性)和 SRTP(安全实时传输协议)自动加密的。这些是内建在浏览器中的,无需开发者额外配置。

跨平台支持

WebRTC API 是标准化的,因此它在所有支持的浏览器上提供一致的体验。无需任何特殊配置,就可以在桌面和移动平台上使用。

会话描述(Session Description Protocol, SDP)

通过 RTCPeerConnection 创建的 offer 和 answer 对象包含了使用 SDP 描述的媒体元数据。

1peerConnection.createOffer().then(function(offer) {
2  return peerConnection.setLocalDescription(offer);
3}).then(function() {
4  // 将 offer 发送给远端
5}).catch(function(reason) {
6  // 处理错误
7});
8

统计 API(Stats API)

WebRTC 提供了访问实时通信统计数据的 API,你可以通过 getStats 方法获取。

1peerConnection.getStats(null).then(function(stats) {
2  // 使用统计数据
3});
4

实践案例

视频捕获和显示

以下是一个简单的示例,展示了如何使用 WebRTC API 调用摄像头和麦克风,并显示在本地视频元素上。

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4<meta charset="UTF-8">
 5<title>WebRTC 本地视频示例</title>
 6</head>
 7<body>
 8
 9<video id="localVideo" autoplay playsinline></video>
10
11<script>
12  // 获取视频元素
13  const localVideo = document.getElementById('localVideo');
14
15  // 设置媒体约束条件
16  const mediaConstraints = {
17    video: true, // 请求视频
18    audio: false // 不请求音频
19  };
20
21  // 使用 getUserMedia API 获取媒体流
22  navigator.mediaDevices.getUserMedia(mediaConstraints)
23    .then((stream) => {
24      // 将媒体流绑定到视频元素上,以显示视频
25      localVideo.srcObject = stream;
26    })
27    .catch((error) => {
28      console.error('获取媒体流失败:', error);
29    });
30</script>
31
32</body>
33</html>
34

在这个示例中,我们使用 getUserMedia 方法请求用户的视频和音频设备。成功后,我们将获取到的媒体流绑定到 <video> 元素的 srcObject 属性,从而在页面上显示视频。

录音与播放

首先,需要在HTML中添加一个按钮来控制录音的开始和停止,以及一个 audio 元素用来播放录制的音频。

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4<meta charset="UTF-8">
 5<title>WebRTC 音频录制示例</title>
 6</head>
 7<body>
 8
 9<button id="startButton">开始录音</button>
10<button id="stopButton" disabled>停止录音</button>
11<audio id="audioPlayback" controls></audio>
12
13<script>
14  // 获取页面元素
15  const startButton = document.getElementById('startButton');
16  const stopButton = document.getElementById('stopButton');
17  const audioPlayback = document.getElementById('audioPlayback');
18
19  // 全局MediaRecorder实例
20  let mediaRecorder;
21  // 用于存储音频数据的数组
22  let audioChunks = [];
23
24  // 开始录音
25  startButton.addEventListener('click', () => {
26    navigator.mediaDevices.getUserMedia({ audio: true, video: false })
27      .then(stream => {
28        mediaRecorder = new MediaRecorder(stream);
29        mediaRecorder.start();
30
31        // 数据可用时触发
32        mediaRecorder.addEventListener('dataavailable', event => {
33          audioChunks.push(event.data);
34        });
35
36        // 录音停止时触发
37        mediaRecorder.addEventListener('stop', () => {
38          // 创建音频Blob
39          const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
40          // 清空chunks
41          audioChunks = [];
42          // 创建用于播放的URL
43          const audioUrl = URL.createObjectURL(audioBlob);
44          // 设置audio元素的src
45          audioPlayback.src = audioUrl;
46        });
47
48        // 更新按钮状态
49        startButton.disabled = true;
50        stopButton.disabled = false;
51      })
52      .catch(error => {
53        console.error('获取音频流失败:', error);
54      });
55  });
56
57  // 停止录音
58  stopButton.addEventListener('click', () => {
59    mediaRecorder.stop();
60    // 更新按钮状态
61    startButton.disabled = false;
62    stopButton.disabled = true;
63  });
64</script>
65
66</body>
67</html>
68

在这个示例中,当用户点击“开始录音”按钮时,会调用 getUserMedia 来请求音频流。成功获取流之后,我们创建一个 MediaRecorder 实例并开始录音。录音过程中,通过监听 dataavailable 事件来收集音频数据。当用户点击“停止录音”按钮时, MediaRecorder 停止录音,并触发 stop 事件,此时我们将收集到的音频数据块组合成一个 Blob 对象,并使用 URL.createObjectURL 方法为这个 Blob 对象创建一个URL,这个URL可以被 audio 元素用来播放录制的音频。

结语

WebRTC 是一项强大且灵活的技术,它打开了实时通信的大门,无论是在应用程序中添加视频聊天功能,还是构建复杂的实时数据共享系统。通过了解和使用 WebRTC 提供的各种 API,你可以创建出令人惊叹的实时通信体验。随着 WebRTC 社区的不断发展,我们期待看到更多创新和功能的加入。