在 iPadOS17 显示采集卡采集到的视频

网页地址

pi-cast.com/capture.html

使用方式

在 iPad OS 17 设备上插上采集卡然后 chrome 或者 safari 打开上面的网址允许访问摄像头和麦克风就行了。

源码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>

<body>
    <select id="select" title="输入设备" onselect="switchDirection()">
        <option></option>
    </select>
    <button onclick="playPause()">播放/暫停</button>
    <button onclick="screenshot()">截圖</button>
    <!-- video 標籤中的自動播放屬性 autoplay,沒有它,你需要調用 video.play() 才能真正開始顯示圖像 -->
    <video autoplay id="video" controls="controls" width="96%"></video>
    <canvas id="canvas"></canvas>
    <div id="imageData"></div>
</body>
<script>
    const select = document.getElementById('select');
    // JavaScript訪問設備前後攝像頭
    const constraints = { // 初始值
        video: {
            // width: {
            //     min: 300,
            //     ideal: 1920,
            //     max: 500
            // },
            // height: {
            //     min: 250,
            //     ideal: 1080,
            //     max: 400
            // },
            width: { ideal: 1920 },
            height: { ideal: 1080 }
        }, // 流以正確的寬度和高度比例進入,如果它是處於縱向模式的手機,則需要進行尺寸反轉
        audio: true,
    };
    const myVideo = document.querySelector('#video');
    let videoStream = null; // 視頻流對象
    let useFrontCamera = true; // 前置攝像頭
    if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) { // 檢查瀏覽器是否支持此API
        enumerateDevices((devices) => { gotDevices(devices); }); // 瀏覽器支持
    } else {
        console.log('暫不支持');
    }
    function playPause() {
        if (myVideo.paused)
            myVideo.play();
        else
            myVideo.pause();
    }
    // 繪製canvas畫布、獲取data
    function screenshot() {
        canvas.width = myVideo.videoWidth;
        canvas.height = myVideo.videoHeight;
        canvas.getContext('2d').drawImage(myVideo, 0, 0);
        const img = document.createElement('img');
        img.src = canvas.toDataURL('image/png');
        let divImage = document.getElementById('#imageID');
        divImage.appendChild(img);
    }
    // 你想在已經播放視頻的情況下更換攝像機的前後攝像頭,需要先停止當前的前置或者後置的視頻流,再將其替換成攝像機的前置或者後置的視頻流。
    async function switchDirection() {
        if (videoStream) {
            videoStream.getTracks().forEach((track) => {
                track.stop();
            });
        }
        constraints.video.deviceId = select.value;
        enumerateDevices((devices) => {
            devices.forEach((device) => {
                // 重设分辨率
                if (device.deviceId == select.value) {
                    // constraints.video.width.min = device.width.min;
                    // constraints.video.width.ideal = device.width.ideal;
                    // constraints.video.width.max = device.width.max;
                    // constraints.video.height.min = device.height.min;
                    // constraints.video.height.ideal = device.height.ideal;
                    // constraints.video.height.max = device.height.max;
                }
            });
            try {
                videoStream = navigator.mediaDevices.getUserMedia(constraints).then(videoStream => myVideo.srcObject = videoStream); // 調用將詢問用戶是否允許訪問攝像機。如果用戶拒絕,它將引發異常並且不返回流。因此,必須在 try/catch 塊內處理這種情況,它返回一個Promise,必須使用 async/await 或 then 塊
            } catch (error) {
                console.log(error)
            }
        });

    }
    async function enumerateDevices(callback) {
        try {
            navigator.mediaDevices.enumerateDevices().then(devices => {
                // const filtered = devices.filter(device => device.kind === "videoinput");
                callback(devices);
            });
        } catch (error) {
            console.log(error)
        }
    }

    function gotDevices(mediaDevices) {
        select.innerHTML = '';
        select.appendChild(document.createElement('option'));
        let count = 1;
        mediaDevices.forEach(mediaDevice => {
            if (mediaDevice.kind === 'videoinput') {
                const option = document.createElement('option');
                option.value = mediaDevice.deviceId;
                if (count == 1) {
                    option.selected = true;
                }
                const label = mediaDevice.label || `Camera ${count++}`;
                const textNode = document.createTextNode(label);
                option.appendChild(textNode);
                select.appendChild(option);
            }
        });
        switchDirection();
    }
</script>

</html>

鸣谢

  • IoT Security Wiki
  • pi-cast.com
本作品采用《CC 协议》,转载必须注明作者和本文链接
感谢阅读,有收获的话不妨点个赞:smiling_imp:
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!