webrtc实现录制屏幕小工具

webrtc(网页即时通信)

大家平常都会听到webrtc,那么webrtc是什么呢,实际上WebRTC是一个免费的开放项目,它通过简单的API为浏览器和移动应用程序提供实时通信(RTC)功能,而对于开发人员来说就是一组api。同时我们说webrtc上一组标准,协议也没错。已被Google、Mozilla、Opera等浏览器支持。

chrome中录制桌面

接下来我们通过使用webrtc中的api实现一个简单的录屏工具

先来介绍下相关api:

getDisplayMedia方法

var promise = 
  navigator.mediaDevices.getDisplayMedia(constraints);
  • mediaDevices接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等.
  • getDisplayMedia() 方法提示用户去选择和授权捕获展示的内容或部分内容(如一个窗口)
  • constraints,MediaStreamConstraints对象,指定返回的MediaStream的要求
  • 返回值, 解析为MediaStream的Promise,包含指定的视频轨和音频轨

我们这里只来捕获视频图像。

MediaRecorder

名字既可以看出来,是作为录制的api

  • 构造函数
var mediaRecorder = new MediaRecorder(stream[, options]);

stream就是录制的数据来源,options可选参数,字典对象,包含mimeType(指定mime类型),audioBitsPerSecond(指定音频比特率),videoBitsPerSecond(指定视频比特率),bitsPerSecond(指定音频和视频的比特率)具体参考MDN

  • 方法
  1. isTypeSupported(),是否支持设置MIME type
  2. start(),开始录制,可以设置毫秒为参数,这样录制内容会按照你设置的这个值分割成小块,不然就是整体一个大块数据
  3. pause(),resume(), stop() 暂停,继续,停止录制
  • 事件处理
  1. ondataavailable, 调用start后数据后会执行这个事件
  2. onerror,发生错误
  3. onstop, 停止录制后调用

捕获视频图像

下边我们自己开始实现

首先我们设置constraints,我们设置捕获的图像分辨率为1280*720,帧率为15

const streamContrains = {
    video: {
        width: 1280,
        height: 720,
        frameRate: 15,
    },
    audio: false
};

然后我们来捕获视频帧,捕获成功后进入onGetStream,出现错误时onGetStreamError打印错误信息

function onGetStream(stream) {}

function onGetStreamError(error) {
    console.log('getDisplayMedia error', error);
}

const mDevices = navigator.mediaDevices;
const promise = mDevices.getDisplayMedia(streamContrains);
promise.then(
    onGetStream
).catch(
    onGetStreamError
);

录制捕获的stream

我们看到onGetStream函数还没有实现,我们已经拿到了stream,接下来我们将stream录制下来:

同样我们先来指定mimetype,然后判断下浏览器是否支持,我们这里录制视频的webm封装格式,编码格式是h264。

var options = {mimeType: 'video/webm;codecs=h264'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
      console.error(`${options.mimeType} not supported!`);
      return;
}

然后我们把stream和options传入MediaRecorder的构造函数。调用start,指定事件的回调函数:

function onDataAvailable(d) {}

function onRecordError(e) {
    console.error('Recorder error', e);
}

// snip...
try {
    mediaRecorder = new MediaRecorder(stream, options);
}
catch (e) {
    console.error('create MediaRecorder error', e);
    return;
}

mediaRecorder.ondataavailable = onDataAvailable;
mediaRecorder.onerror = onRecordError;

mediaRecorder.start(10);

保存录制内容

我们已经将录制的内容在onDataAvailable体现。我们先用一个数组来存放:

var buffer = [];
//snip...

function onDataAvailable(d) {
    if (d && d.data && d.data.size > 0) {
        buffer.push(d.data);
    }
}

等到我们停止录制的时候,我们需要把数据保存成文件。

function saveVideo() {
    if (buffer) {
        var blob = new Blob(buffer, {type: 'video/webm'});
        var url = window.URL.createObjectURL(blob);
        var a = document.createElement('a');

        a.href = url;
        a.style.display = 'none';
        a.download = 'record.webm';
        a.click();
    }
    else {
        console.error("record failed");
    }
}

通过buffer创建Blob对象,同时创建一个隐藏的a标签,将内容保存成文件。

完整的代码

如果只是需要这个小工具,可以将此处代码复制保存成html,chrome打开即可使用。

<!DOCTYPE html>
<html>
    <head>
        <title>Record Desktop</title>
    </head>
    <body>
        <h1>Record Desktop with webRTC</h1>
        <div>
            <button id = "record">record</button>
            <button id = "pause">pause</button>
        </div>

        <script>
            'use strict'

            var mediaRecorder;
            const pauseBtn = document.getElementById('pause');
            pauseBtn.disabled = true;
            pauseBtn.onclick = function(ev) {
                if (!mediaRecorder) {
                    return;
                }

                if (pauseBtn.textContent == "pause") {
                    mediaRecorder.pause();
                    pauseBtn.textContent = "resume";
                }
                else {
                    mediaRecorder.resume();
                    pauseBtn.textContent = "pause";
                }
            }

            var buffer = [];
            function onDataAvailable(d) {
                if (d && d.data && d.data.size > 0) {
                    buffer.push(d.data);
                }
            }

            function onRecordError(e) {
                console.error('Recorder error', e);
            }

            const recordBtn = document.getElementById('record');
            function onGetStream(stream) {
                recordBtn.textContent = "stop";
                var options = {mimeType: 'video/webm;codecs=vp8'};
                if (!MediaRecorder.isTypeSupported(options.mimeType)) {
                    console.error(`${options.mimeType} is not supported!`);
                    return;
                }

                try {
                    mediaRecorder = new MediaRecorder(stream, options);
                }
                catch (e) {
                    console.error('Filed to create MediaRecorder', e);
                    return;
                }

                mediaRecorder.ondataavailable = onDataAvailable;
                mediaRecorder.onerror = onRecordError;
                mediaRecorder.start(10);
            }

            function saveVideo() {
                if (buffer) {
                    var blob = new Blob(buffer, {type: 'video/webm'});
                    var url = window.URL.createObjectURL(blob);
                    var a = document.createElement('a');

                    a.href = url;
                    a.style.display = 'none';
                    a.download = 'record.webm';
                    a.click();
                }
                else {
                    console.error("record failed");
                }
            }

            // 捕获视频
            const streamContrains = {
                video: {
                    width: 1280,
                    height: 720,
                    frameRate: 15,
                },
                audio: false
            };

            function onGetStreamError(error) {
                console.log('getDisplayMedia error', error);
            }

            recordBtn.onclick = function(ev) {
                if (mediaRecorder && recordBtn.textContent != "record") {
                    recordBtn.textContent = "record";
                    pauseBtn.disabled = false;

                    let tracks = mediaRecorder.stream.getTracks();
                    tracks.forEach(track => track.stop());
                    saveVideo();
                    return;
                }
                
                pauseBtn.disabled = false;
                const mDevices = navigator.mediaDevices;
                const promise = mDevices.getDisplayMedia(streamContrains);
                promise.then(
                    onGetStream
                ).catch(
                    onGetStreamError
                );
            }
        </script>
    </body>
</html>

运行

以上代码保存html文件,chrome浏览器打开:
在这里插入图片描述

点击record时,会弹出框,选择共享屏幕或者其他窗口,然后点击分享就开始录制了,
在这里插入图片描述
此时可以点击stop停止录制或者暂停然后继续录制等等。
在这里插入图片描述
点击stop就会自动下载视频文件,浏览器打开就可以查看录制的视频了。

参考

https://developer.mozilla.org/
https://github.com/avdance/webrtc_web.git

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值