recorder.js 4.57 KB
Newer Older
liujiangnan's avatar
liujiangnan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
(function (exports) {
  //公共方法
  var Util = {
    //初始化
    init: function () {
      navigator.getUserMedia = navigator.getUserMedia ||
        navigator.webkitGetUserMedia ||
        navigator.mozGetUserMedia ||
        navigator.msGetUserMedia;

      window.AudioContext = window.AudioContext ||
        window.webkitAudioContext;
    },
    //日志
    log: function () {
      console.log.apply(console, arguments);
    }
  };
  //构造函数
  var Recorder = function (config) {

    var _this = this;
    config = config || {}; //初始化配置对象
    config.sampleRate = config.sampleRate || 44100; //采样频率,默认为44100Hz(标准MP3采样率)
    config.bitRate = config.bitRate || 128; //比特率,默认为128kbps(标准MP3质量)

    Util.init();

    if (navigator.getUserMedia) {
      navigator.getUserMedia({
          audio: true //配置对象
        },
        function (stream) { //成功回调
          var context = new AudioContext(),
            microphone = context.createMediaStreamSource(stream), //媒体流音频源
            processor = context.createScriptProcessor(16384, 1, 1), //js音频处理器
            successCallback, errorCallback;

          config.sampleRate = context.sampleRate;

          processor.onaudioprocess = function (event) {
            //监听音频录制过程
            var array = event.inputBuffer.getChannelData(0);
            realTimeWorker.postMessage({cmd: 'encode', buf: array});
          };

          var realTimeWorker = new Worker('assets/libs/audio-recorder/worker.js'); //开启后台线程
          _this.worker = realTimeWorker;
          realTimeWorker.onmessage = function (e) { //主线程监听后台线程,实时通信
            switch (e.data.cmd) {
              case 'init':
                Util.log('初始化成功');
                if (config.success) {
                  config.success();
                }
                break;
              case 'end':
                if (successCallback) {
                  var blob = new Blob(e.data.buf, {type: 'audio/mp3'});
                  successCallback(blob);
                  Util.log('MP3大小:' + blob.size + '%cB', 'color:#0000EE');
                }
                break;
              case 'error':
                Util.log('错误信息:' + e.data.error);
                if (errorCallback) {
                  errorCallback(e.data.error);
                }
                break;
              default:
                Util.log('未知信息:' + e.data);
            }
          };
          //接口列表
          //开始录音
          _this.start = function () {
            if (processor && microphone) {
              microphone.connect(processor);
              processor.connect(context.destination);
              Util.log('开始录音');
            }
          };
          //结束录音
          _this.stop = function () {
            if (processor && microphone) {
              microphone.disconnect();
              processor.disconnect();
              Util.log('录音结束');
            }
          };
          //获取blob格式录音文件
          _this.getBlob = function (onSuccess, onError) {
            successCallback = onSuccess;
            errorCallback = onError;
            realTimeWorker.postMessage({cmd: 'finish'});
          };

          realTimeWorker.postMessage({
            cmd: 'init',
            config: {
              sampleRate: config.sampleRate,
              bitRate: config.bitRate
            }
          });
        },
        function (error) { //失败回调
          var msg;
          switch (error.code || error.name) {
            case 'PermissionDeniedError':
            case 'PERMISSION_DENIED':
            case 'NotAllowedError':
              msg = '用户拒绝访问麦克风';
              break;
            case 'NOT_SUPPORTED_ERROR':
            case 'NotSupportedError':
              msg = '浏览器不支持麦克风';
              break;
            case 'MANDATORY_UNSATISFIED_ERROR':
            case 'MandatoryUnsatisfiedError':
              msg = '找不到麦克风设备';
              break;
            default:
              msg = '无法打开麦克风,异常信息:' + (error.code || error.name);
              break;
          }
          Util.log(msg);
          if (config.error) {
            config.error(msg);
          }
        });
    } else {
      Util.log('当前浏览器不支持录音功能');
      if (config.fix) {
        config.fix('当前浏览器不支持录音功能');
      }
    }

  };
  //模块接口
  exports.Recorder = Recorder;
})(window);