你将学到什么
在本步骤中,你将学习如何:
- 拍照片并从 canvas无素中获得数据
- 与远端用户交换图像数据
本步骤的完整版本在 step-06目录下。
它是如何工作的
将面已经学习了如何使用RTCDataChannel 交换广本数据。 这步将用它来共享整个文件。在这个例子中通过 getUserMedia()捕获照片。
这步的核心部分如下:
- 建立数据通道。 在这一步你不需要添加任何媒体流到 peer connection.
- 通过 getUserMedia()捕获用户的 webcam 视频流。
var video = document.getElementById('video');
function grabWebCamVideo() {
console.log('Getting user media (video) ...');
navigator.mediaDevices.getUserMedia({
video: true
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' e.name);
});
}
- 当用户点击
Snap
按钮时,从视频流得到一个快照(一个视频帧)并在canvas
元素里显示它。
- 当用户点击
var photo = document.getElementById('photo');
var photoContext = photo.getContext('2d');
function snapPhoto() {
photoContext.drawImage(video, 0, 0, photo.width, photo.height);
show(photo, sendBtn);
}
- 当用户点击
Send
按钮时,将图片转成字节并通过数据通道发送出去:
- 当用户点击
function sendPhoto() {
// Split data channel message in chunks of this byte length.
var CHUNK_LEN = 64000;
var img = photoContext.getImageData(0, 0, photoContextW, photoContextH),
len = img.data.byteLength,
n = len / CHUNK_LEN | 0;
console.log('Sending a total of ' len ' byte(s)');
dataChannel.send(len);
// split the photo and send in chunks of about 64KB
for (var i = 0; i < n; i ) {
var start = i * CHUNK_LEN,
end = (i 1) * CHUNK_LEN;
console.log(start ' - ' (end - 1));
dataChannel.send(img.data.subarray(start, end));
}
// send the reminder, if any
if (len % CHUNK_LEN) {
console.log('last ' len % CHUNK_LEN ' byte(s)');
dataChannel.send(img.data.subarray(n * CHUNK_LEN));
}
}
- 接收端将数据通道中的字节转换回图片再显示给用户:
function receiveDataChromeFactory() {
var buf, count;
return function onmessage(event) {
if (typeof event.data === 'string') {
buf = window.buf = new Uint8ClampedArray(parseInt(event.data));
count = 0;
console.log('Expecting a total of ' buf.byteLength ' bytes');
return;
}
var data = new Uint8ClampedArray(event.data);
buf.set(data, count);
count = data.byteLength;
console.log('count: ' count);
if (count === buf.byteLength) {
// we're done: all data chunks have been received
console.log('Done. Rendering photo.');
renderPhoto(buf);
}
};
}
function renderPhoto(data) {
var canvas = document.createElement('canvas');
canvas.width = photoContextW;
canvas.height = photoContextH;
canvas.classList.add('incomingPhoto');
// trail is the element holding the incoming images
trail.insertBefore(canvas, trail.firstChild);
var context = canvas.getContext('2d');
var img = context.createImageData(photoContextW, photoContextH);
img.data.set(data);
context.putImageData(img, 0, 0);
}
获得代码
用 step-06目录中的内容替换你工作目录中的内容。在work
目录中的 index.html现在看起来像这样:
<!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>
<h2>
<span>Room URL: </span><span id="url">...</span>
</h2>
<div id="videoCanvas">
<video id="camera" autoplay></video>
<canvas id="photo"></canvas>
</div>
<div id="buttons">
<button id="snap">Snap</button><span> then </span><button id="send">Send</button>
<span> or </span>
<button id="snapAndSend">Snap & Send</button>
</div>
<div id="incoming">
<h2>Incoming photos</h2>
<div id="trail"></div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="js/main.js"></script>
</body>
</html>
如果在你的work
目录下没有一直跟着codelab, 你可能需要安装step-06目录或你的当前目录的依赖。可以在你的目录下简单的运行下面的命令即可:
npm install
一旦安装后,如果Node.js没有运行的话,在你的工作目录下调用下面的命令来启动它:
代码语言:javascript复制node index.js
要确保你正在使用的index.js版本实现了 Sokcet.IO, 如果做了改变记得重启 Node.js。关于 Node和 Socket IO更多的信息查看 "为交换消息建立信令服务"一节。
如果需要,点击"Allow"按钮允许应用使用你的webcam。 应该将创建一个随机的 room ID并将它添加到 URL里。 从浏览器的新的 tab或窗口地址栏中打开些 URL。
点击 Snap & Send
按钮,然后观察一下网页底部的另一个选项卡中输入区域。些应用在两个选项卡之间传输照片。
你应该看到像下面这个样子:
点滴
- 你如何改代码才能使尽可能的共享任意类型的文件呢?