前端使用html5、ffmpeg实现录屏摄像等功能
1.1k4WEBffmpeg2018-11-062019-03-15

前段时间做一个windows的桌面应用,vue + electron,涉及到录屏和摄像功能,网上相关的文档蛮少的给需要的人一些参考

如果文章描写有误或者还有更好的方法,请留言告诉我,笔芯 (´▽`ʃ♡ƪ)

背景介绍

涉及技术:vue、electron、ffmpeg、node

关于录屏和摄像对比了两种方法

  • 使用HTML5的api实现

    摄像:mediaDevices(获取设备)+ getUserMedia(获取流) + MediaRecorder(存储)

    录屏:getDisplayMedia(获取流) + MediaRecorder(存储)

  • ffmpeg + node:FFmpeg是一套非常强大的音视频处理的开源工具,不多介绍,而Electron基于node和chromium,它允许使用node的API以及几乎所有的node模块,这意味这着我们可以调用cmd命令来操作ffmpeg实现录屏和摄像录制,当然ffmpeg功能绝不止这点

HTML5实现

mediaDevices

  • 用于收集系统上可用的多媒体输入和输出设备的信息

  • 该方法调用成功返回设备列表,并传入带有devceID的MediaStreamConstraints对象可以指定设备获取流媒体来源

    1
    2
    3
    4
    5
    6
    navigator.mediaDevices.enumerateDevices().then(devicelist => {
    // audiooutput 扬声器
    // audioinput 麦克风
    // audiooutput 摄像
    console.log(devicelist)
    }).catch(err => console.log(err))

    getUserMedia

  • 用户提供访问硬件设备媒体(摄像头、视频、音频、地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件下访问硬件媒体设备。

  • 该方法返回视频流,将获取到的流赋给video标签可实现边录边看

    1
    2
    3
    navigator.mediaDevices.getUserMedia(MediaStreamConstraints).then(stream => {
    videoElement.srcObject = stream; //
    }, error => console.log(error));

    getDisplayMedia

  • 将用户的显示或其部分用作媒体流的来源,它允许以视频流的形式获取用户的显示器或其一部分

  • 录屏主要依靠该方法,和getUserMedia一样返回一个promise对象,调用成功返回流,将这个流赋给video 元素实现边录边看

  • 需要注意的是 如果你做的是网页端在谷歌上使用这个元素,需要在chrome://flags/开启Experimental Web Platform features功能
    demo戳这儿

        而Electron基于node + chromium构建,在electron需要引入desktopCapturer模块,并在基于该模块使用这个方法

    1
    2
    3
    4
    navigator.mediaDevices.getDisplayMedia({ video: true })
    .then(stream => {
    videoElement.srcObject = stream;
    }, error => console.log(error));

    MediaRecorder

  • 记录和捕获媒体,也就是视频和音频

  • getDisplayMedia 和 getUserMedia 获取到的流都需要使用MediaRecorder存储起来,并且可以保存成文件

    1
    2
    3
    4
    5
    6
    7
    let herf
    this.recorder = new MediaRecorder(stream);
    this.recorder.ondataavailable = e => {
    herf = e.data;
    download.href = URL.createObjectURL(herf);
    };
    this.recorder.start();

第二种使用ffmpeg

官网安装包下载 https://ffmpeg.zeranoe.com/builds/

一些基本参数

  • -formats 输出所有可用格式
  • -f fmt 指定格式(音频或视频格式)
  • -i filename 指定输入文件名,在linux下当然也能指定:0.0(屏幕录制)或摄像头
  • -y 覆盖已有文件
  • -t duration 记录时长为t
  • -fs limit_size 设置文件大小上限
  • -itsoffset time_off 设置时间偏移(s),该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss* [.xxx]的格式也支持
    音 频
  • -ab bitrate 设置音频码率
  • -ar freq 设置音频采样率
  • -ac channels 设置通道 缺省为1
    视 频
  • -b bitrate 设置比特率,缺省200kb/s
  • -r fps 设置帧频 缺省25
  • -s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:

录屏相关命令

1
2
3
4
5
列出可用的设备包括音频和摄像等等
ffmpeg -list_devices true -f dshow -i dummy

录屏,你也可以加入关于视频的一些基本参数来获得你想要的文件
ffmpeg -f gdigrab -i desktop captrue.mkv -y

node调用

cd进入bin文件夹后执行录屏相关命令

关于停止录制,虽然ffmpeg按 Q 可以停止录制,但是我们通过代码调用是看不到cmd命令行的而且他在录制过程中是一直占用这个进程什么命令也无法输入
所以这个地方我只想到一个办法就是强制停止该进程

参考文章

MDN https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices

W3C https://w3c.github.io/mediacapture-screen-share/