[JS筆記]JS 開啟鏡頭權限,電腦及 iOS、Android 手機皆可切換前後鏡頭

如何使用 HTML 和 JS 開啟鏡頭權限,電腦及 iOS、Android 手機皆可切換前後鏡頭,並且設定每 1 秒繪製一次截圖的功能。這篇是使用純 JavaScript 來執行的範例程式碼。

JS 開啟鏡頭權限
JS 開啟鏡頭權限。圖片來源:Unsplash

JS 開啟鏡頭權限程式碼

HTML 的部分需要

  1. 一個 video 標籤用來顯示鏡頭畫面
  2. 一個 div 標籤可以拿來做為每 1 秒截圖的顯示
  3. 加上切換鏡頭的按鈕
<!-- 視訊串流顯示位置 -->
<video id="videoElement" class="videoElement" autoplay muted playsinline></video>

<!-- 繪製截圖 -->
<div id="imageContainer"></div>

<!-- 切換鏡頭按鈕 -->
<div>
    <button onclick="switchCamera()">切換鏡頭</button>
</div>

程式碼範例
程式碼範例。圖片來源:Unsplash

JS 開啟鏡頭權限後,每秒進行一次 canvas 繪製的動作,成為截圖的概念:

<script>
const videoElement = document.getElementById("videoElement");

// 切換鏡頭
function switchCamera() {
  if (videoElement.srcObject) {
    let videoTracks = videoElement.srcObject.getVideoTracks();
    if (videoTracks.length > 0) {
      let currentTrack = videoTracks[0];
      let facingMode = currentTrack.getSettings().facingMode;

      const constraints = { video: {} };
      if (facingMode === "user") {
        constraints.video.facingMode = "environment"; // 切換到後鏡頭
      } else {
        constraints.video.facingMode = "user"; // 切換到前鏡頭
      }

      // 停止原本的視訊串流
      videoTracks.forEach(function (track) {
        track.stop();
      });

      // 確保瀏覽器支援 MediaDevices API
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        // 取得新的視訊串流
        navigator.mediaDevices
          .getUserMedia(constraints)
          .then(function (stream) {
            videoElement.srcObject = stream;
          })
          .catch(function (error) {
            console.error("無法取得視訊串流:", error);
            alert(
              "您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!"
            );
          });
      } else {
        alert(
          "您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!"
        );
      }
    }
  }
}

function startCam() {
  // 手機前後鏡頭切換 前鏡頭為 'user',後鏡頭為 'environment'
  const constraints = { video: { facingMode: "user" } };
  // 確保瀏覽器支援MediaDevices API
  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    // 取得視訊串流
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(function (stream) {
        // iOS 手機使用時,必須增加的屬性
        videoElement.setAttribute("autoplay", "");
        videoElement.setAttribute("muted", "");
        videoElement.setAttribute("playsinline", "");

        videoElement.srcObject = stream;

        // 每秒繪製一格畫面
        setInterval(function () {
          let canvas = document.createElement("canvas");
          canvas.width = videoElement.videoWidth;
          canvas.height = videoElement.videoHeight;
          canvas
            .getContext("2d")
            .drawImage(videoElement, 0, 0, canvas.width, canvas.height);

          // 改變圖片解析度
          let scaleFactor = 2; // 調整這個數值以增加解析度

          let offscreenCanvas = document.createElement("canvas");
          offscreenCanvas.width = canvas.width * scaleFactor;
          offscreenCanvas.height = canvas.height * scaleFactor;
          let offscreenCtx = offscreenCanvas.getContext("2d");
          offscreenCtx.drawImage(
            canvas,
            0,
            0,
            offscreenCanvas.width,
            offscreenCanvas.height
          );

          // 直接顯示在前端
          // 需要動態創建 <img> 元素,因為手機版可能會無法讀取
          let imageElement = document.createElement("img");

          // 將 <img> 元素添加到 HTML 中的指定元素上
          let containerElement = document.getElementById("imageContainer");
          containerElement.innerHTML = "";
          imageElement.setAttribute("style", "width:100%");
          containerElement.appendChild(imageElement);
          imageElement.src = offscreenCanvas.toDataURL("image/jpeg", 1);
        }, 1000); // 每秒繪製一次畫面
      })
      .catch(function (error) {
        console.log("無法取得視訊串流:", error);
        alert(
          "您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!"
        );
      });
  } else {
    alert("您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!");
  }
}
// 初始執行函式
startCam();
</script>

iOS 手機開啟鏡頭必要的 HTML 內容

其中,iOS 手機我除錯了很久,最後發現:以下這三行一定要寫!

videoElement.setAttribute("autoplay", "");
videoElement.setAttribute("muted", "");
videoElement.setAttribute("playsinline", "");

也就是 video 一定要給 autoplay、muted、playsinline 這 3 個屬性,在 iOS 手機上才可以正常讓視訊進行串流!

否則 iOS 手機會定在第一格就不動了。

每秒下載一張圖片檔

想要每秒不只是繪製,而是下載成圖片檔案的話,可以把 startCam() 改寫成以下這樣:

function startCam() {
  // 手機前後鏡頭切換 前鏡頭為 'user',後鏡頭為 'environment'
  const constraints = { video: { facingMode: "user" } };
  // 確保瀏覽器支援MediaDevices API
  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    // 取得視訊串流
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(function (stream) {
        // iOS 手機使用時,必須增加的屬性
        videoElement.setAttribute("autoplay", "");
        videoElement.setAttribute("muted", "");
        videoElement.setAttribute("playsinline", "");

        videoElement.srcObject = stream;

        // 每秒下載一格畫面
        setInterval(function () {
          let canvas = document.createElement("canvas");
          canvas.width = videoElement.videoWidth;
          canvas.height = videoElement.videoHeight;
          canvas
            .getContext("2d")
            .drawImage(videoElement, 0, 0, canvas.width, canvas.height);

          // 改變圖片解析度
          let scaleFactor = 2; // 調整這個數值以增加解析度

          let offscreenCanvas = document.createElement("canvas");
          offscreenCanvas.width = canvas.width * scaleFactor;
          offscreenCanvas.height = canvas.height * scaleFactor;
          let offscreenCtx = offscreenCanvas.getContext("2d");
          offscreenCtx.drawImage(
            canvas,
            0,
            0,
            offscreenCanvas.width,
            offscreenCanvas.height
          );

          // 直接顯示在前端
          // 需要動態創建 <img> 元素,因為手機版可能會無法讀取
          let imageElement = document.createElement("img");

          // 將 <img> 元素添加到 HTML 中的指定元素上
          let containerElement = document.getElementById("imageContainer");
          containerElement.innerHTML = "";
          imageElement.setAttribute("style", "width:100%");
          containerElement.appendChild(imageElement);
          imageElement.src = offscreenCanvas.toDataURL("image/jpeg", 1);

          offscreenCanvas.toBlob(
            function (blob) {
              // 下載圖片
              let link = document.createElement("a");
              link.href = URL.createObjectURL(blob);
              link.download = "frame.jpg";
              // link.click();
            },
            "image/jpeg",
            1
          );
        }, 1000); // 每秒下載一次畫面
      })
      .catch(function (error) {
        console.log("無法取得視訊串流:", error);
        alert(
          "您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!"
        );
      });
  } else {
    alert("您使用的瀏覽器不支援視訊串流,請使用其他瀏覽器,再重新開啟頁面!");
  }
}

這樣就可以每 1 秒進行下載囉!

總結

以上就是最簡單可以同時錄影 + 下載當成截圖的 HTML + JavaScript 範例。

同時錄影 + 下載截圖
同時錄影 + 下載截圖。圖片來源:Unsplash


延伸閱讀:


分享這篇文章

發佈留言