JavaScript记录屏幕错误在移动设备上

发布于 2025-01-27 14:16:06 字数 5181 浏览 4 评论 0 原文

问题摘要: JavaScript解决方案在浏览器(Chrome,Edge,Firefox)的桌面版本上工作,而不是移动浏览器(Chrome,Safari)。

用于录制屏幕的 /基于vanilla-javascript的屏幕 - 屏幕 - recorder-29fff1cc7b00“ rel =“ nofollow noreferrer”>这个很棒的例子我能够构建一个在桌面浏览器上正常工作的原型。

但是,当对移动浏览器(iOS上的Chrome/Safari)进行测试时,有一个错误:

typeError:未定义不是功能(靠近 '... navigator.mediadevices.getDisplayMedia ...')

下面是屏幕上按钮的HTML代码:

        <input id="btnStartRecording" class="btn btn-lg btn-primary col-4" onclick="startRecord()" value="Start Recording" type="button">
        <input id="btnStopRecording" class="btn btn-lg btn-primary col-4 invisible" onclick="stopScreen()" value="Stop Recording" type="button">
        <a id="btnDownloadRecording" href="#" class="btn btn-lg btn-primary col-4 text-white invisible">Download Video</a>

下面是一个隐藏的视频元素,可以保存录音,而录制脚本:

    <div>
        <video controls="true" style="display: none" id="videoResult" src=""></video>
    </div>
    <script> // client side recording script https://javascript.plainenglish.io/vanilla-javascript-based-screen-recorder-29fff1cc7b00
        let completeBlob = null
        let recorder = null
        let chunks = [];
        let stream = null
        async function startRecord() {
            chunks = []; // need to reset chucks each time recording is started

            try {

                stream = await navigator.mediaDevices.getDisplayMedia({
                    video: {
                        mediaSource: 'screen'
                    },
                })

                recorder = new MediaRecorder(stream);
                recorder.ondataavailable = (e) => chunks.push(e.data);
                recorder.start();
                recorder.onstop = onstop

                $("#btnStartRecording").addClass("invisible");
                $("#btnStopRecording").removeClass("invisible");
                $("#btnDownloadRecording").addClass("invisible");

            } catch (error) {

                navigator.getUserMedia = navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia || navigator.msGetUserMedia; 

                if (navigator.getUserMedia) {
                    navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
                        function (streamobj) {

                            recorder = new MediaRecorder(streamobj);
                            recorder.ondataavailable = (e) => chunks.push(e.data);
                            recorder.start();
                            recorder.onstop = onstop

                            $("#btnStartRecording").addClass("invisible");
                            $("#btnStopRecording").removeClass("invisible");
                            $("#btnDownloadRecording").addClass("invisible");

                            //var video = document.querySelector('video');
                            //video.srcObject = stream;
                            //video.onloadedmetadata = function (e) {
                            //    video.play();
                            //};
                        },
                        function (err) {
                            window.alert("#1 " + err)
                        }
                    );
                }
                else {
                    window.alert("#2 " + error)
                }
            }
        }


        async function stopScreen() {
            recorder.stop();
            //document.getElementById("stopBtn").style.display = "none";
            $("#btnStartRecording").removeClass("invisible");
            $("#btnStopRecording").addClass("invisible");
            stream.getTracks().forEach(function (track) {
                track.stop();
            });
        }

        function onstop() {
            console.log("onstop");
            completeBlob = new Blob(chunks, {
                type: chunks[0].type
            });
            $("#btnDownloadRecording").removeClass("invisible");
            let downloadButton = document.getElementById('btnDownloadRecording');
            let video = document.getElementById('videoResult');
            //video.style.display = 'block'
            video.src = URL.createObjectURL(completeBlob);
            //downloadButton.style.display = 'unset'
            downloadButton.href = URL.createObjectURL(completeBlob);
            downloadButton.download = Date.now() + '.mp4';
        }
    </script>

不熟悉API,我使用了一些我使用了一些因此,诸如 this 作为hange navigator.mediadevices.mediadevices.getdisplaymedia的参考。 “捕获”部分。但是显然,它仍然在移动设备上不起作用。访问后,执行 window.alert(“#2” +错误)行,这意味着 if(navigator.getusermedia)评估为false。

进一步的挖掘找到 >说只有Safari有效,但我在Safari上进行了测试,并且使用相同的错误消息失败。

任何帮助都将受到赞赏!

Summary of problem:
A Javascript solution to record screen works on desktop versions of browsers (chrome, edge, firefox), but not on mobile browsers (chrome, safari).

Following this great example I was able to build a prototype that works just fine on desktop browsers (tested on Chrome, Edge, Firefox).

However when testing on mobile browser (chrome/safari on ios), there is an error:

TypeError: undefined is not a function (near
'...navigator.mediaDevices.getDisplayMedia...')

Below is the HTML code for on-screen buttons:

        <input id="btnStartRecording" class="btn btn-lg btn-primary col-4" onclick="startRecord()" value="Start Recording" type="button">
        <input id="btnStopRecording" class="btn btn-lg btn-primary col-4 invisible" onclick="stopScreen()" value="Stop Recording" type="button">
        <a id="btnDownloadRecording" href="#" class="btn btn-lg btn-primary col-4 text-white invisible">Download Video</a>

Below is a hidden video element to hold the recording, and script to record:

    <div>
        <video controls="true" style="display: none" id="videoResult" src=""></video>
    </div>
    <script> // client side recording script https://javascript.plainenglish.io/vanilla-javascript-based-screen-recorder-29fff1cc7b00
        let completeBlob = null
        let recorder = null
        let chunks = [];
        let stream = null
        async function startRecord() {
            chunks = []; // need to reset chucks each time recording is started

            try {

                stream = await navigator.mediaDevices.getDisplayMedia({
                    video: {
                        mediaSource: 'screen'
                    },
                })

                recorder = new MediaRecorder(stream);
                recorder.ondataavailable = (e) => chunks.push(e.data);
                recorder.start();
                recorder.onstop = onstop

                $("#btnStartRecording").addClass("invisible");
                $("#btnStopRecording").removeClass("invisible");
                $("#btnDownloadRecording").addClass("invisible");

            } catch (error) {

                navigator.getUserMedia = navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia || navigator.msGetUserMedia; 

                if (navigator.getUserMedia) {
                    navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
                        function (streamobj) {

                            recorder = new MediaRecorder(streamobj);
                            recorder.ondataavailable = (e) => chunks.push(e.data);
                            recorder.start();
                            recorder.onstop = onstop

                            $("#btnStartRecording").addClass("invisible");
                            $("#btnStopRecording").removeClass("invisible");
                            $("#btnDownloadRecording").addClass("invisible");

                            //var video = document.querySelector('video');
                            //video.srcObject = stream;
                            //video.onloadedmetadata = function (e) {
                            //    video.play();
                            //};
                        },
                        function (err) {
                            window.alert("#1 " + err)
                        }
                    );
                }
                else {
                    window.alert("#2 " + error)
                }
            }
        }


        async function stopScreen() {
            recorder.stop();
            //document.getElementById("stopBtn").style.display = "none";
            $("#btnStartRecording").removeClass("invisible");
            $("#btnStopRecording").addClass("invisible");
            stream.getTracks().forEach(function (track) {
                track.stop();
            });
        }

        function onstop() {
            console.log("onstop");
            completeBlob = new Blob(chunks, {
                type: chunks[0].type
            });
            $("#btnDownloadRecording").removeClass("invisible");
            let downloadButton = document.getElementById('btnDownloadRecording');
            let video = document.getElementById('videoResult');
            //video.style.display = 'block'
            video.src = URL.createObjectURL(completeBlob);
            //downloadButton.style.display = 'unset'
            downloadButton.href = URL.createObjectURL(completeBlob);
            downloadButton.download = Date.now() + '.mp4';
        }
    </script>

Being not familiar with the APIs I used some SO threads such as this as reference to handle when "navigator.mediaDevices.getDisplayMedia" failed, which is the code in the "catch" part. But obviously it still does not work on mobile. Once accessed, the window.alert("#2 " + error) line was executed, which implies if (navigator.getUserMedia) evaluates to false.

Further digging found this SO discussion which says only Safari works but I tested it on Safari and it failed with the same error message.

Any help is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文