WebRTC開啟本地攝像頭

AnRFDev發表於2021-11-24

本文使用WebRTC的功能,開啟電腦上的攝像頭,並且把攝像頭預覽到的影像顯示出來。
純網頁實現,能支援除IE外的多數瀏覽器。手機瀏覽器也可用。

引入依賴

我們需要引入adapter-latest.js

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

這個WebRTC adapter曾是WebRTC中的一部分,但現在被移出來了。
我們會用到它提供的功能。

html

我們在介面上先擺放一些控制元件。

<div id="container">
    <video id="video-local" autoplay playsinline></video>
    <button id="showVideo">開啟攝像頭</button>
    <button id="stopVideo">關閉攝像頭</button>
    <p>顯示攝像頭預覽的內容,網頁上由元素video來呈現。</p>
    <p>點選開啟攝像頭按鈕後,瀏覽器會詢問是否允許,請點選“允許”。</p>
    <div id="errorMsg"></div>
    <div id="tipMsg"></div>
</div>
  • video 用來顯示預覽的視訊
  • 兩個button用來控制開啟和關閉
  • 再放幾個顯示資訊的地方

js

先設定一下,我們只使用視訊

const constraints = window.constraints = {
  audio: false,
  video: true
};

在網頁上顯示一些資訊,便於除錯。

function showErrMsg(msg, error) {
  const errorElement = document.querySelector('#errorMsg');
  errorElement.innerHTML += `<p>${msg}</p>`;
  if (typeof error !== 'undefined') {
    console.error(error);
  }
}

function showMsg(msg) {
    const msgEle = document.querySelector('#tipMsg');
    msgEle.innerHTML += `<p>-> ${msg}</p>`;
    console.log(msg);
}

完整程式碼在main.js中。css可自行定義。

開啟攝像頭

要開啟攝像頭,使用MediaDevices.getUserMedia()方法

async function openCamera(e) {
  try {
    showMsg('正在開啟攝像頭');
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    showMsg('獲取到了stream');
    gotStream(stream);
    e.target.disabled = true;
  } catch (err) {
    onErr(err);
  }

MediaDevices.getUserMedia()方法在使用者允許後,按照請求,拿到stream。
stream可以包含視訊或音訊。前面的設定裡,我們只使用視訊。

如果使用者拒絕了使用攝像頭申請,或者申請的媒體不可用,即表現為被拒絕。
使用者拒絕會報NotAllowedError,找不到符合要求的裝置會報NotFoundError DOMException

方法的文件MediaDevices.getUserMedia()

顯示視訊

獲取到stream後,讓video顯示視訊

function gotStream(stream) {
  const videoEle = document.querySelector('video');
  const videoTracks = stream.getVideoTracks();
  showMsg(`正在使用的裝置: ${videoTracks[0].label}`);
  window.stream = stream;
  videoEle.srcObject = stream;
}

document.querySelector('video')直接獲取html上的video控制元件。
把stream直接交給videoEle.srcObject

停止視訊流

要停止視訊,我們可以從video元素入手,拿到stream,然後把裡面的track停掉。

function stopVideo(e) {
    showMsg("停止視訊");
    const videoElem = document.querySelector('video');
    const stream = videoElem.srcObject;

    document.querySelector('#showVideo').disabled = false; // 允許開啟

    if(stream == null) {
        return;
    }
    const tracks = stream.getTracks();
  
    tracks.forEach(function(track) {
      track.stop();
    });
    videoElem.srcObject = null;
}

stream.getTracks()方法拿到所有的軌道(track),遍歷一遍全部關掉。
最後,把videoElem.srcObject設定為null,它與前面的stream解除關聯,方便將它釋放。

參考 MediaStreamTrack-stop

小結

示例使用的WebRTC的功能。顯示的是本地攝像頭的視訊,不涉及傳輸。拿到視訊流後交給video來顯示。
getUserMedia是示例中最關鍵的方法。以後的示例都會用到它。

參考

效果預覽

完整的效果請參考
open-camera

相關文章