如何使用 HTML 和 JS 開啟鏡頭權限,電腦及 iOS、Android 手機皆可切換前後鏡頭,並且設定每 1 秒繪製一次截圖的功能。這篇是使用純 JavaScript 來執行的範例程式碼。
目錄
JS 開啟鏡頭權限程式碼
HTML 的部分需要
- 一個 video 標籤用來顯示鏡頭畫面
- 一個 div 標籤可以拿來做為每 1 秒截圖的顯示
- 加上切換鏡頭的按鈕
<!-- 視訊串流顯示位置 -->
<video id="videoElement" class="videoElement" autoplay muted playsinline></video>
<!-- 繪製截圖 -->
<div id="imageContainer"></div>
<!-- 切換鏡頭按鈕 -->
<div>
<button onclick="switchCamera()">切換鏡頭</button>
</div>
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 範例。
延伸閱讀:
- [JS筆記]實作上傳圖片功能、圖片網址轉圖片格式轉換 base64 to blob
- [JS筆記]JavaScript 陣列移除重複的方法,使用 Set 達成效果
- [JS筆記]前端 JS 圖片預加載 3 行完成!最簡單的前端緩存方式