前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Electron音视频录制

Electron音视频录制

作者头像
码客说
发布2019-10-21 17:14:43
3.9K1
发布2019-10-21 17:14:43
举报
文章被收录于专栏:码客

获取设备的支持情况

代码语言:javascript
复制
var types = [
  "video/webm",
	"audio/webm",
	"video/webm\;codecs=vp8",
	"video/webm\;codecs=daala",
	"video/webm\;codecs=h264",
	"audio/webm\;codecs=opus",
	"video/mpeg"
];

for (var i in types) {
	console.log(types[i] + ":" + (MediaRecorder.isTypeSupported(types[i]) ? "支持" : "不支持"));
}

获取可用的视频源

代码语言:javascript
复制
desktopCapturer.getSources({
  types: ['screen']
}, (error, sources) => {
  if (error) throw error
  for (let source of sources) {
    console.info(source);
  }
});

定义全局变量

代码语言:javascript
复制
let audioStream;
let vedioStream;

let mediaRecorder;
let recordedChunks = [];

获取音频流

代码语言:javascript
复制
function getAudioStream() {
  navigator.mediaDevices.getUserMedia({audio: true, video: false})
      .then(function (stream) {
          audioStream = stream;
          getVedioStream()
          stream.onended = () => {
              console.log('Micro audio ended.')
          }
      })
      .catch(function (error) {
          console.log('getUserMedia() failed.')
      });
}

或者

代码语言:javascript
复制
function getAudioStream() {
  navigator.webkitGetUserMedia(
    {audio: true, video: false},
    function (stream) {
      console.log('Received audio stream.')
      audioStream = stream;
      getVedioStream()
      stream.onended = () => {
        console.log('Micro audio ended.')
      }
    },
    function () {
      console.log('getUserMedia() failed.')
    }
  );
}

获取视频流

sourceid可以通过获取可用的录制源返回source.id获取

代码语言:javascript
复制
function getVedioStream() {
  navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      mandatory: {
        chromeMediaSource: 'desktop',
        // chromeMediaSourceId: sourceid,
        maxWidth: window.screen.width,
        maxHeight: window.screen.height
      }
    }
  }).then(function (stream) {
    vedioStream = stream;
    let liveVideo = document.querySelector("video");
    liveVideo.srcObject = stream;
    liveVideo.muted = true;
    liveVideo.play();

    startRecord();
  }).catch(function (err) {
    console.log('The following error occured: ' + err);
  })
}

或者

代码语言:javascript
复制
function getVedioStream() {
  navigator.webkitGetUserMedia({
    audio: false,
    video: {
      mandatory: {
        chromeMediaSource: 'desktop',
        // chromeMediaSourceId: sourceid,
        maxWidth: window.screen.width,
        maxHeight: window.screen.height
      }
    }
  }, function (stream) {
    vedioStream = stream;
    let liveVideo = document.querySelector("video");
    liveVideo.srcObject = stream;
    liveVideo.muted = true;
    liveVideo.play();
    startRecord();
  }, function () {

  })
}

录制带声音

代码语言:javascript
复制
function startRecord() {
  if (audioStream) {
    let audioTracks = audioStream.getAudioTracks();
    vedioStream.addTrack(audioTracks[0]);
  }

  mediaRecorder = new MediaRecorder(vedioStream);

  mediaRecorder.ondataavailable = (event) => {
    if (event.data && event.data.size > 0) {
      recordedChunks.push(event.data)
    }
  };

  mediaRecorder.onstart = () => {
    console.log("开始录制")
  };
  mediaRecorder.onstop = () => {
    console.log("停止录制")
  };

  mediaRecorder.start();
}

停止录制

代码语言:javascript
复制
// 结束录制
function stopRecord() {
  if (mediaRecorder) {
    mediaRecorder.stop();
  } else {
    alert("还没有开始。");
  }
}

保存

代码语言:javascript
复制
function formatLength(str, length) {
  str += '';
  if (str.length < length)
    return formatLength('0' + str, length)
  else
    return str
}

function getnowstr() {
  var now = new Date();
  var year = now.getFullYear(); //得到年份
  var month = formatLength(now.getMonth(), 2);//得到月份
  var date = formatLength(now.getDate(), 2);//得到日期
  var hour = formatLength(now.getHours(), 2);//得到小时
  var minu = formatLength(now.getMinutes(), 2);//得到分钟
  var all_time = year + "-" + month + "-" + date + "_" + hour + "-" + minu;
  return all_time;
}

// 保存视频
function saveRecord() {
  let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
  let url = URL.createObjectURL(blob);
  let a = document.createElement('a');
  var all_time = getnowstr();
  document.body.appendChild(a);
  a.style = 'display: none';
  a.href = url;
  a.download = all_time + 'video.webm';
  a.click()
  setTimeout(function () {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url)
  }, 100)
}

播放

代码语言:javascript
复制
function playRecord() {
  let video = document.querySelector('video')
  video.controls = true;
  video.muted = false;
  let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"})
  video.src = window.URL.createObjectURL(blob)
  video.play();
}

整体代码

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>Document</title>
</head>

<body>
<video id="live"></video>

<div class="toolbar">
    <span class="timer"></span>
    <button id="startOrStop">开始</button>
    <button id="save">保存</button>
    <button id="play">播放</button>
</div>

<style>
    body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        width: 100vw;
        height: 100vh;
        display: flex;
        flex-direction: column;
    }

    #live {
        width: 100%;
        height: 0;
        flex-grow: 1;
    }

    .toolbar {
        width: 100%;
        height: 60px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .toolbar button {
        margin-left: 6px;
        margin-right: 6px;
        padding: 10px 16px;
        border-radius: 4px;
        background-color: blue;
        color: white;
    }

    .timer {
        width: 60px;
        text-align: center;
    }
</style>

<script>
    let n = 0;
    let timer;

    let audioStream;
    let vedioStream;

    let mediaRecorder;
    let recordedChunks = [];

    const startOrStopButton = document.getElementById("startOrStop");
    const saveButton = document.getElementById("save");
    const playButton = document.getElementById("play");
    startOrStopButton.addEventListener("click", startOrStopRecord);
    saveButton.addEventListener("click", saveRecord);
    playButton.addEventListener("click", playRecord);

    function getAudioStream() {
        navigator.mediaDevices.getUserMedia({audio: true, video: false})
            .then(function (stream) {
                audioStream = stream;
                getVedioStream()
                stream.onended = () => {
                    console.log('Micro audio ended.')
                }
            })
            .catch(function (error) {
                console.log('getUserMedia() failed.')
            });
    }

    function getVedioStream() {
        navigator.mediaDevices.getUserMedia({
            audio: false,
            video: {
                mandatory: {
                    chromeMediaSource: 'desktop',
                    maxWidth: window.screen.width,
                    maxHeight: window.screen.height
                }
            }
        }).then(function (stream) {
            vedioStream = stream;
            let liveVideo = document.querySelector("video");
            liveVideo.src = null;
            liveVideo.srcObject = vedioStream;
            liveVideo.controls = false;
            liveVideo.muted = true;
            liveVideo.play();

        }).catch(function (err) {
            console.log('The following error occured: ' + err);
        })
    }

    // 显示录制的秒数
    function startTimer() {
        const timerEl = document.querySelector(".timer");
        n = 0;
        timerEl.textContent = `${n}s`;
        timer = setInterval(() => {
            n += 1;
            timerEl.textContent = `${n}s`;
        }, 1000);
    }

    // 开始录制
    function startRecord() {
        if (audioStream) {
            let audioTracks = audioStream.getAudioTracks();
            vedioStream.addTrack(audioTracks[0]);
        }

        mediaRecorder = new MediaRecorder(vedioStream);
        mediaRecorder.ondataavailable = (event) => {
            if (event.data && event.data.size > 0) {
                recordedChunks.push(event.data)
            }
        };

        mediaRecorder.onstart = () => {
            console.log("开始录制")
        };
        mediaRecorder.onstop = () => {
            console.log("停止录制")
        };

        mediaRecorder.start();
    }

    // 结束录制
    function startOrStopRecord() {
        if (startOrStopButton.innerHTML === "开始") {
            recordedChunks = [];
            startTimer();
            startRecord();
            startOrStopButton.innerHTML = "停止"
        } else {
            clearInterval(timer);
            if (mediaRecorder) {
                mediaRecorder.stop();
                //停止视频音频流
                // vedioStream.getVideoTracks()[0].stop();
                // audioStream.getAudioTracks()[0].stop();
            }
            startOrStopButton.innerHTML = "开始"
        }
    }

    function formatLength(str, length) {
        str += '';
        if (str.length < length)
            return formatLength('0' + str, length);
        else
            return str
    }

    function getnowstr() {
        let now = new Date();
        let year = now.getFullYear(); //得到年份
        let month = formatLength(now.getMonth(), 2);//得到月份
        let date = formatLength(now.getDate(), 2);//得到日期
        let hour = formatLength(now.getHours(), 2);//得到小时
        let minu = formatLength(now.getMinutes(), 2);//得到分钟
        let time_all = year + "-" + month + "-" + date + "_" + hour + ":" + minu;
        return time_all;
    }

    // 保存视频
    function saveRecord() {
        let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
        let url = URL.createObjectURL(blob);
        let a = document.createElement('a');
        var all_time = getnowstr();
        document.body.appendChild(a);
        a.style = 'display: none';
        a.href = url;
        a.download = all_time + 'vedio.webm';
        a.click()
        setTimeout(function () {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url)
        }, 100)
    }

    function playRecord() {
        if (playButton.innerHTML === "播放") {
            let liveVideo = document.querySelector('video');
            liveVideo.controls = true;
            liveVideo.muted = false;
            let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
            liveVideo.srcObject = null;
            liveVideo.src = window.URL.createObjectURL(blob);
            liveVideo.play();
            playButton.innerHTML = "取消播放"
        } else {
            let liveVideo = document.querySelector("video");
            liveVideo.src = null;
            liveVideo.srcObject = vedioStream;
            liveVideo.controls = false;
            liveVideo.muted = true;
            liveVideo.play();
            playButton.innerHTML = "播放"
        }
    }

    getAudioStream();
</script>
</body>
</html>

工具类

为了方便使用封装成了工具类方便使用

代码语言:javascript
复制
/**
 *自动录屏模块*录制桌面
 *
 * @class Recorder
 */
class Recorder {
    constructor(path) {
        this.mediaOutputPath = path;
    }

    /**
     *开始录制
     *
     * @memberof Recorder
     */
    startRecord = () => {
        /* 要获取桌面音频必须设置audio约束如下 */
        this.getVedioStream().then(vedioStream => {
            this.getAudioStream().then((audioStream) => {
                vedioStream.addTrack(audioStream.getAudioTracks()[0])//注!此处添加麦克风音轨无效
                this.startRecorder(vedioStream);
            });
        }).catch(err => {
            this.getUserMediaError(err);
        });
    };

    /**
     *获取麦克风音频流
     *
     * @memberof Recorder
     */
    getAudioStream = () => {
        return navigator.mediaDevices.getUserMedia({audio: true, video: false})
    };


    /**
     *获取屏幕视频流
     *
     * @memberof Recorder
     */
    getVedioStream = () => {
        return navigator.mediaDevices.getUserMedia({
            audio: false,
            video: {
                mandatory: {
                    chromeMediaSource: 'desktop',
                    maxWidth: window.screen.width,
                    maxHeight: window.screen.height
                }
            }
        })
    };

    /**
     *获取媒体源失败
     *
     * @memberof Recorder
     */
    getUserMediaError = (err) => {
        console.log('mediaError', err);
    };


    getUserAudioError = (err) => {
        console.log('audioError', err);

    };

    /**
     *开始视频录制
     *
     * @memberof Recorder
     */
    startRecorder = (stream) => {
        this.recorder = new MediaRecorder(stream);
        this.recorder.start();
        this.recorder.ondataavailable = event => {
            let blob = new Blob([event.data], {
                type: 'video/webm'
            });
            this.saveMedia(blob);
        };
    };


    formatLength = (str, length) => {
        str += '';
        if (str.length < length)
            return this.formatLength('0' + str, length)
        else
            return str
    };


    getnowstr = () => {
        var now = new Date();
        var year = now.getFullYear(); //得到年份
        var month = this.formatLength(now.getMonth(), 2);//得到月份
        var date = this.formatLength(now.getDate(), 2);//得到日期
        var hour = this.formatLength(now.getHours(), 2);//得到小时
        var minu = this.formatLength(now.getMinutes(), 2);//得到分钟
        var all_time = year + "-" + month + "-" + date + "_" + hour + "-" + minu;
        return all_time;
    };

    /**
     *数据转换并保存成MP4
     *
     * @memberof Recorder
     */
    saveMedia = (blob) => {
        let reader = new FileReader();
        let _t = this;
        var filename = this.mediaOutputPath + this.getnowstr() + "_vedio.webm";
        reader.onload = function () {
            let buffer = Buffer.from(reader.result);
            const fs = require('fs')
            fs.writeFile(filename, buffer, {}, (err, res) => {
                if (err) {
                    console.error(err);
                    return
                }
            })
        };
        reader.readAsArrayBuffer(blob);
    };


    /**
     *停止录制视频
     *
     * @memberof Recorder
     */
    stopRecord = () => {
        this.recorder.stop();
    }


}

exports.Recorder = Recorder;

调用方式

代码语言:javascript
复制
const {Recorder} = require('./utils/Recorder');
let my_recorder = new Recorder("/Users/zhangjian/Downloads/");

// 开始录制
my_recorder.startRecord();
// 结束录制自动保存文件
if (my_recorder) {
  my_recorder.stopRecord();
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 获取设备的支持情况
  • 获取可用的视频源
  • 定义全局变量
  • 获取音频流
  • 获取视频流
  • 录制带声音
  • 停止录制
  • 保存
  • 播放
  • 整体代码
  • 工具类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档