navigator.mediaDevices.getUserMedia录制桌面视频并保存

如果,需要同时录制麦克风声音以及桌面声音,请看最后

以下代码中有用到electron的desktopCapturer模块(用于PC应用开发),如果你并不需要,可以直接忽略,直接定义你要录制的视频源和音频源。重点如果要录制桌面,audio约束必须为 false,否则会报错,暂时不支持audio,如果你需要录制桌面的声音,则必须设置audio约束
audio: {
mandatory: {
chromeMediaSource: ‘desktop’
}
}

import {
  desktopCapturer
} from 'electron'

import fs from 'fs';


/**
 *自动录屏模块*录制桌面
 *
 * @class Recorder
 */
class Recorder {

  constructor(path) {
    this.mediaOutputPath = path;
  }


  /**
   *开始录制
   *
   * @memberof Recorder
   */
  startRecord = () => {

    desktopCapturer.getSources({
      types: ['screen']
    }, (error, sources) => {
      if (error) {
        throw error;
      }
      /* 要获取桌面音频必须设置audio约束如下 */
      navigator.mediaDevices.getUserMedia({
        audio:  {
          mandatory: {
            chromeMediaSource: 'desktop'
          }
        },
        video:   {
          mandatory: {
            chromeMediaSource: 'desktop',
            maxWidth: window.screen.width,
            maxHeight: window.screen.height
            /*cursor:"never" */
            /*取消录制鼠标,以免鼠标闪烁,这个目前标准定义了各浏览器还没实现,
            如果需要请使用webrtc-adapter,使用最新API,
            视频录制被单独分离成getDisplayMedia,
            但是cursor约束条件是否有效暂时也不确定。没试过。*/
          }
        }  
      }).then(Mediastream => {
        this.getMicroAudioStream().then((audioStream)=>{
          Mediastream.addTrack(audioStream.getAudioTracks()[0])//注!此处添加麦克风音轨无效
          this.createRecorder(Mediastream);
        });
        
      }).catch(err => {
        this.getUserMediaError(err);

      })

    })


  }

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



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


  }


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

  }

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

    };

  }


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

  }



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




}

export default Recorder;


如何录制桌面声音及麦克风声音

上面的代码中,强制录制桌面以及系统声音。但是会发现上面代码中的添加麦克风音轨是无效的,如下

this.getMicroAudioStream().then((audioStream)=>{
          Mediastream.addTrack(audioStream.getAudioTracks()[0])//注!此处添加麦克风音轨无效
          this.createRecorder(Mediastream);
        });

最后录下来的视频还是只能听到系统音而听不到麦克风的声音。如果输出Mediastream的话会发现,里面确实包含了两个audioTrack,一个系统的,一个麦克风的,但很明显,麦克风的音轨并不起作用。

解决方法:通过AudioContext API来混音,再添加进视频流。

AudioContext 为音频上下文,旨在创建一个可以处理音频的环境。
解决思路: 获取到Mediastream之后,抽出 桌面系统音轨(system audio track),然后再获取麦克风音频流(microphone audio stream)。

记住,因为获取的系统音是一个audio track对象,所以需要转变成stream才能处理。
把两个stream连接到mixStream。最后把这个mixStream的音轨(track)合到 一开始获得的 Mediastream中,【重点】,如果直接addtrack 进去,还是无法听到麦克风的声音的。必须在addtrack mixstream的音轨之前先移除 MediaStream的track(即原本的桌面音轨)

核心代码


  /**
   *混合音轨
   *
   * @memberof Recorder
   */
  mixAudioStream=(Mediastream)=>{
    let systemAudioTrack=Mediastream.getAudioTracks()[0]; //获取强制获取的桌面音【轨】
    return new Promise((resolve,reject)=>{
      this.getMicroAudioStream().then(audioStream=>{//获取麦克风音频【流】
        let audioContext=new AudioContext();//创建音频上下文
        let microphoneStreamNode=audioContext.createMediaStreamSource(audioStream);//创建节点
        let sysAudioStream=new MediaStream();//创建一个媒体流
        sysAudioStream.addTrack(systemAudioTrack);//把系统音轨添加到新的媒体流
        let sysAudioStreamNode=audioContext.createMediaStreamSource(sysAudioStream);//创建系统音频节点
        let mixedOutput = audioContext.createMediaStreamDestination();//创建一个输出媒体流节点
        microphoneStreamNode.connect(mixedOutput);//把麦克风节点和系统音节点添加到输出媒体流
        sysAudioStreamNode.connect(mixedOutput);//把麦克风节点和系统音节点添加到输出媒体流
        resolve(mixedOutput.stream);//返回混合后的媒体流
      }).catch(err=>{
        reject()
      })
    })

  }

你可能感兴趣的:(javascript,electron)