独书先生 Menu

webrtc 屏幕录制

需求

我们在复现软件问题,或者做教学的时候,需要录屏,一般来说需要下载屏幕录制软件,经常还会带上水印,有没有一种可以不用安装软件在线录屏的方案呢,答案就是webrtc,使用浏览器自带的功能,打开网页就能录制桌面上的任意窗口,而且没有水印。

演示

https://dushusir.com/tool/web-recorder.html

代码

以下代码你将学习到
– 使用navigator.mediaDevices.getDisplayMedia获取用户窗口
– 使用MediaRecorder获取用户窗口录制的视频流
– 使用Blob和window.URL.createObjectURL来将视频流下载下来

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>webrtc screen recorder</title>
</head>

<body>


    <video autoplay playsinline id="player"></video>
    <video playsinline id="recordPlayer"></video>

    <!-- 在开始录制之前播放和下载按钮时禁用的 -->
    <button id="recordBtn">start</button>
    <button id="playBtn">play</button>
    <button id="downloadBtn">download</button>

    <script type="text/javascript">


        var player = document.querySelector("#player");
        var recordPlayer = document.querySelector("#recordPlayer");
        var recordBtn = document.querySelector("#recordBtn");
        var playBtn = document.querySelector("#playBtn");
        var downloadBtn = document.querySelector("#downloadBtn");

        var buffer; // 用于存储录制数据(数组)
        var mediaStream;
        var mediaRecoder;

        // 录制按钮点击事件
        recordBtn.addEventListener('click', function () {
            // console.log(recordBtn.text());
            if (recordBtn.textContent === 'start') {
                startRecord();
                recordBtn.textContent = 'stop';
                playBtn.setAttribute('disabled', true);
                downloadBtn.setAttribute('disabled', true);
            } else if (recordBtn.textContent === 'stop') {
                stopRecord();
                recordBtn.textContent = 'start';
                playBtn.removeAttribute('disabled');
                downloadBtn.removeAttribute('disabled');
            }
        });

        // 播放按钮点击事件
        playBtn.addEventListener('click', function () {
            var blob = new Blob(buffer, { type: 'video/webm' });
            // 根据缓存数据生成url给recordPlayer进行播放
            recordPlayer.src = window.URL.createObjectURL(blob);
            recordPlayer.srcObject = null;
            recordPlayer.controls = true; // 显示播放控件
        });

        // 下载按钮点击事件
        downloadBtn.addEventListener('click', function () {
            var blob = new Blob(buffer, { type: 'video/webm' });
            // 根据缓存数据生成url
            var url = window.URL.createObjectURL(blob);
            // 创建一个a标签,通过a标签指向url来下载
            var a = document.createElement('a');
            a.href = url;
            a.style.display = 'none'; // 不显示a标签
            a.download = 'test.webm'; // 下载的文件名
            a.click(); // 调用a标签的点击事件进行下载
        });

        // 开始录制
        function start() {

            var options = { mimeType: 'video/webm;codecs=vp8' };
            if (!MediaRecorder.isTypeSupported(options.mimeType)) {
                console.log('不支持' + options.mimeType);
                return;
            }

            try {
                buffer = [];
                mediaRecoder = new MediaRecorder(mediaStream, options);
            } catch (e) {
                console.log('创建MediaRecorder失败!');
                return;
            }
            mediaRecoder.ondataavailable = handleDataAvailable;
            // 开始录制,设置录制时间片为10ms(每10s触发一次ondataavilable事件)
            mediaRecoder.start(1000);
        }

        // 停止录制
        function stopRecord() {
            mediaRecoder.stop();
            mediaStream.getTracks().forEach(track => track.stop())
        }

        // 触发ondataavilable事件的回调函数
        function handleDataAvailable(e) {
            if (e && e.data && e.data.size > 0) {
                buffer.push(e.data);
            }
        }

        function startRecord() {
            if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
                console.log('不支采集音视频数据!');
            } else {
                // 采集音频数据
                var constrants = {
                    video: true,
                    audio: true
                };
                navigator.mediaDevices.getDisplayMedia(constrants).then(gotMediaStream).catch(handleError);

            }
        }

        // 采集音频数据成功时调用的方法
        function gotMediaStream(stream) {
            mediaStream = stream;
            player.srcObject = stream;

            start()
        }

        // 采集音频数据失败时调用的方法
        function handleError(err) {
            console.log(err.name + ':' + err.message);
        }
    </script>
</body>

</html>