54

[译]WebRTC基础实践 - 9. 拍照并传给对方

 5 years ago
source link: https://blog.csdn.net/renfufei/article/details/85041182?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本节内容

在本节课程中, 我们将学习以下内容:

  • 拍照并通过canvas元素获取图像数据。
  • 给对面发送图片。

本节的完整版代码位于 step-06 文件夹中。

工作原理

前面的小节中, 我们使用 RTCDataChannel 来传递文本消息。

本节课程, 将学习如何发送文件: 下面的示例发送的是通过 getUserMedia() 捕获的照片文件, 原理都是一样的。

核心内容包括:

getUserMedia()
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 (拍照)按钮, 会从 video 流中得到一份快照(一帧视频), 并通过 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 (发送)按钮, 会将图像转换为字节数组(bytes), 并通过数据通道发送给对方:
function sendPhoto() {
  // 将数据分块的字节数长度;
  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>

如果没有执行上一节的操作, 需要在 step-06 目录, 或者工作目录下, 安装相应的依赖, 命令如下:

cnpm install

安装完成后, 需要启动 Node.js 服务器, 在 work 目录下执行命令:

node index.js

请确认 index.js 文件的内容中包含了 Socket.IO 相关的内容, 参考前一小节。更多关于Node和Socket.IO的内容, 请参考 7_Set_up_signaling_service.md

如果弹出对话框, 请点击 Allow (允许)按钮, 授权使用本地摄像头。

本应用会创建一个随机的房间ID, 并将此ID加入URL中。

然后在一个新的标签或窗口打开同样的URL。

点击 SnapSend 按钮, 然后查看另一个标签页中, 是否显示了传过去的照片。

这个应用主要是实现了在不同标签页/不同窗口之间传输照片。

界面看起来类似这样:

09_01_tabs_photo.png

练习与实践

  1. 修改代码, 以传输任意类型的文件。

了解更多

内容回顾

  • 拍照并通过canvas元素获取图像数据。
  • 给对面发送图片。

本节的完整版代码位于 step-06 文件夹中。

原文链接: https://codelabs.developers.google.com/codelabs/webrtc-web/#8

翻译人员: 铁锚 - https://blog.csdn.net/renfufei

翻译日期: 2018年08月27日


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK