Electron音视频录制

2019-10-21 17:14:43 浏览数 (1)

获取设备的支持情况

代码语言: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();
}

0 人点赞