# [實作篇]MediaStreams API - 基本應用(搭配canvas)

# 學習目標

  • 如何利用 getUserMedia API 實作簡單的canvas應用

# 實作

接下來會展示一些簡單實作, 主要是熟悉能透過getUserMedia 取得 MediaStream 後,能夠做哪些應用。

注意: 因為getUserMedia在相容性上需要額外處理,這邊會利用Google包裝好的shim lib - adapter.js.來方便我們操作。

# Video 控制

<!-- index.html -->
<h1>基礎 getUserMedia 影音流播放控制</h1>
<hr>
<video autoplay></video>
<!-- 取得media stream -->
<button onclick="onCapture()">Capture</button>
<!-- 停止media stream -->
<button onclick="stopMedia()">Stop</button>

加上兩個Button,Capture按鈕負責重新啟用mediaStream,Stop按紐負責停止功能

# 加上adapter.js lib

引入adapter.js幫我們處理好相容性問題,方便主程式操作getUserMedia。

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<!-- 主要程式 -->
<script src="./js/main.js"></script>

# 實作主程式

// ./js/main.js
const video = document.querySelector('video');
const constraints = {
  audio: false,
  video: true
};

function handleSuccess(stream) {
  window.stream = stream; // 方便可以在瀏覽器console
  video.srcObject = stream;
}

function handleError(error) {
  console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}

function onCapture () {
  navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
}

function stopMedia () {
  if (window.stream) {
    const videoStreams = window.stream.getVideoTracks()

    videoStreams.forEach(stream => {
      stream.stop() // 停止所有media stream
    });

    // 釋放資源
    video.src = video.srcObject = null;
  }
}

onCapture ()

延伸思考:

  • stream.stop()換成stream.enabled = false會有什麼差異呢?

但在嘗試前記得要先將video.srcObject = nullmark起來,如下

// video.src = video.srcObject = null;

對 MediaStreamTracks object不熟的話,可以先觀看該章節

# Screenshots With Canvas

提醒: 部分code會延續上面,這邊就會略過。

搭配canvas 來做視訊截圖

這次的index.html將會如下:

<div id="screenshot">
  <h1>搭配 Canvas 做視訊截圖功能</h1>
  <hr>
  <video autoplay></video>
  <button id="screenshot-button">Screenshot Button</button>
  <canvas></canvas>
  <!-- 也能將canvas轉成image data -->
  <img src="">
</div>
<!-- ... -->

透過Screenshot Button綁定click event,讓canvas渲染事件觸發當下的影格內容。

// ./js/main.js
const screenshotButton = document.querySelector('#screenshot-button');
const img = document.querySelector('#screenshot img');
const video = document.querySelector('#screenshot video');
const canvas = document.querySelector('canvas');

screenshotButton.onclick = video.onclick = function () {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  // 渲染
  canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
  
};

// ...

延伸思考:

  • 嘗試利用canvas搭配img src來顯示截圖。
// 轉成image data
img.src = canvas.toDataURL('image/png');

# 總結

本章節了解到:

  • 操作 MediaStream object。
  • 如何搭配Canvas。
  • 除了利用Canvas的2D渲染api drawImage, 將影格內容繪製出來外,也能將其利用toDataURL api 轉為data URI, 就能利用image element渲染出來。