本系列文章介绍使用WebRTC实现实时通信,原文参考 Real time communication with WebRTC

4. 从webcam获取视频流

你将学到

通过本节内容,你将学到

  • 从webcam获取视频流
  • 流播放操作
  • 使用CSS和SVG来操作视频

本节的所有内容位于 step-01 文件夹

HTML代码片段

添加 video 元素和 script 元素到 work 目录的 index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<!DOCTYPE html>
<html>

<head>
  <title>Realtime communication with WebRTC</title>
  <link rel="stylesheet" href="css/main.css" />
</head>

<body>
  <h1>Realtime communication with WebRTC</h1>
  <video autoplay playsinline></video>
  <script src="js/main.js"></script>
</body>

</html>

JavaScript代码片段

将如下代码加到 js 目录 main.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'use strict';

// 媒体流约束,本例只开启视频
const mediaStreamConstraints = {
    video: true,
};
// video元素用于保存视频流
const localVideo = document.querySelector('video');

// 本地视频流
let localStream;

// getUserMedia获取视频流成功处理函数,添加MediaStream到video标签
function gotLocalMediaStream(mediaStream) {
    localStream = mediaStream;
    localVideo.srcObject = mediaStream;
}

// 错误处理函数,将错误信息log到console
function handleLocalMediaStreamError(error) {
    console.log('navigator.getUserMedia error: ', error);
}

// 初始化媒体流
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
    .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);

Try it out

浏览器打开 index.html,会弹出浏览器想要访问本地摄像头的提示框,点击允许后将在 video 标签里看到摄像头内容 webrtc-permission-tips.png webrtc-webcam-01.png

How it works

getUserMedia()函数调用后,浏览器请求用户访问摄像头的权限(第一次请求时才会询问权限)。如果成功,返回 MediaStream,该对象通过 srcObject 属性给media元素使用。

1
2
3
4
5
6
7
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
    .then(gotLocalMediaStream).catch(handleLocalMediaStreamError);

function gotLocalMediaStream(mediaStream) {
    localStream = mediaStream;
    localVideo.srcObject = mediaStream;
}

constraints 参数用于标识需要获取的媒体,本示例中,只包含video,因此audio被默认不开启。

1
2
3
const mediaStreamConstraints = {
    video: true,
};

你也可以使用其他额外的约束,比如视频的分辨率

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const hdConstraints = {
  video: {
    width: {
      min: 1280
    },
    height: {
      min: 720
    }
  }
}

MediaTrackConstraints 规范列出了所有的可用约束类型,但是并不是所有的浏览器都支持所有的选项。如果当前摄像头不支持分辨率请求,getUserMedia()将以错误 OverconstrainedError 被拒绝,用户将会提示没有权限访问摄像头。


你可以查看这些demo展示如何使用constraints来请求不同的分辨率,这些demo展示使用constraints选择摄像头和麦克风。


加分项(Bonus points)

  • localStream对象保存在全局空间,因此你可以再浏览器console检查该对象:打开浏览器console,输入localStream回车即可。
  • 思考localStream.getVideoTracks()返回什么?
  • 试着调用localStream.getVideoTracks()[0].stop()
  • 如果将constraints修改为{audio: true, video: true}会发生什么?
  • video标签的大小是多少?怎么通过JavaScript获取视频的原始大小,相对于显示大小?使用Chrome Dev Tools来检查下。
  • 试着添加 CSS filters到video标签。For example:
1
2
3
video {
  filter: blur(4px) invert(1) opacity(0.5);
}
  • 试着添加 SVG filters. For example:
1
2
3
video {
   filter: hue-rotate(180deg) saturate(200%);
 }

Tips

  • 不要忘了给video标签加上 autoplay 属性,否则,你将只会看到一帧。
  • getUserMedia()有很多其他constraints选项,去看一看这些demo: webrtc.github.io/samples/src/content/peerconnection/constraints. 同时,你也会发现有很多有趣的WebRTC示例。

下一步

我们已经获取到了视频,但是怎么传输视频呢?下一节见分晓!