{"version":3,"sources":["../../src/component/AudioAnalyser/MediaRecorder.js"],"names":["convertWav","WebWorker","MediaRecorderFn","constraints","audio","mp3Worker","Worker","props","startAudio","recorder","MediaRecorderClass","mediaRecorder","state","navigator","mediaDevices","getUserMedia","then","recordAudio","stream","catch","checkAndExecFn","errorCallback","err","resumeAudio","pauseAudio","pause","onpause","pauseCallback","audioCtx","suspend","stopAudio","audioType","audioOptions","includes","stop","onstop","audioStream2Blob","stopCallback","audioChunk","initCanvas","compatibility","analyser","createAnalyser","audioBitsPerSecond","mimeType","timeslice","MediaRecorder","ondataavailable","event","onRecordCallback","data","push","resume","start","onstart","e","startCallback","onresume","initAudioAnalyser","onerror","renderCurve","source","createMediaStreamSource","connect","promisifiedOldGUM","webkitGetUserMedia","mozGetUserMedia","Promise","reject","Error","resolve","call","undefined","fn","type","cb","wavBlob","chunk","audioWav","fr","FileReader","readAsArrayBuffer","Blob","frOnload","buffer","target","result","decodeAudioData","DataView","onload","audioMp3","wavBuf","postMessage","cmd","config","bitRate","rawInput","onmessage","mp3Blob","buf","Target","window","AudioContext","webkitAudioContext"],"mappings":"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","file":"MediaRecorder.js","sourcesContent":["/**\r\n * @author j_bleach 2018/8/18\r\n * @describe 媒体记录(包含开始,暂停,停止等媒体流及回调操作)\r\n * @param Target 被装饰类(AudioAnalyser)\r\n */\r\nimport convertWav from \"./audioConvertWav\";\r\nimport WebWorker from \"./mp3worker.js\";\r\n\r\nconst MediaRecorderFn = Target => {\r\n const constraints = {audio: true};\r\n const mp3Worker = new Worker(WebWorker);\r\n return class MediaRecorderClass extends Target {\r\n static audioChunk = [] // 音频信息存储对象\r\n static mediaRecorder = null // 媒体记录对象\r\n static audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // 音频上下文\r\n\r\n constructor(props) {\r\n super(props);\r\n MediaRecorderClass.compatibility();\r\n this.analyser = MediaRecorderClass.audioCtx.createAnalyser();\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/08/02 17:06\r\n * @describe 浏览器navigator.mediaDevices兼容性处理\r\n */\r\n static compatibility() {\r\n const promisifiedOldGUM = (constraints) => {\r\n // First get ahold of getUserMedia, if present\r\n const getUserMedia =\r\n navigator.getUserMedia ||\r\n navigator.webkitGetUserMedia ||\r\n navigator.mozGetUserMedia;\r\n\r\n // Some browsers just don't implement it - return a rejected promise with an error\r\n // to keep a consistent interface\r\n if (!getUserMedia) {\r\n MediaRecorderClass.checkAndExecFn(this.props.errorCallback);\r\n return Promise.reject(\r\n new Error(\"getUserMedia is not implemented in this browser\")\r\n );\r\n }\r\n // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise\r\n return new Promise(function (resolve, reject) {\r\n getUserMedia.call(navigator, constraints, resolve, reject);\r\n });\r\n };\r\n\r\n // Older browsers might not implement mediaDevices at all, so we set an empty object first\r\n if (navigator.mediaDevices === undefined) {\r\n navigator.mediaDevices = {};\r\n }\r\n\r\n // Some browsers partially implement mediaDevices. We can't just assign an object\r\n // with getUserMedia as it would overwrite existing properties.\r\n // Here, we will just add the getUserMedia property if it's missing.\r\n if (navigator.mediaDevices.getUserMedia === undefined) {\r\n navigator.mediaDevices.getUserMedia = promisifiedOldGUM;\r\n }\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/8/19\r\n * @describe 验证函数,如果存在即执行\r\n * @param fn: function 被验证函数\r\n * @param e: object 事件对象 event object\r\n */\r\n static checkAndExecFn(fn, e) {\r\n typeof fn === \"function\" && fn(e)\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/8/19\r\n * @describe 音频流转blob对象\r\n * @param type: string 音频的mime-type\r\n * @param cb: function 录音停止回调\r\n */\r\n static audioStream2Blob(type, audioOptions, cb) {\r\n let wavBlob = null;\r\n const chunk = MediaRecorderClass.audioChunk;\r\n const audioWav = () => {\r\n let fr = new FileReader();\r\n fr.readAsArrayBuffer(new Blob(chunk, {type}))\r\n let frOnload = (e) => {\r\n const buffer = e.target.result\r\n MediaRecorderClass.audioCtx.decodeAudioData(buffer).then(data => {\r\n wavBlob = new Blob([new DataView(convertWav(data, audioOptions))], {\r\n type: \"audio/wav\"\r\n })\r\n MediaRecorderClass.checkAndExecFn(cb, wavBlob);\r\n })\r\n }\r\n fr.onload = frOnload\r\n }\r\n const audioMp3 = () => {\r\n let fr = new FileReader();\r\n fr.readAsArrayBuffer(new Blob(chunk, {type: \"audio/wav\"}))\r\n let frOnload = (e) => {\r\n const buffer = e.target.result;\r\n MediaRecorderClass.audioCtx.decodeAudioData(buffer).then(data => {\r\n const wavBuf = convertWav(data, audioOptions)\r\n mp3Worker.postMessage({\r\n cmd: \"init\",\r\n config: {bitRate: 128}\r\n });\r\n mp3Worker.postMessage({cmd: \"encode\", rawInput: wavBuf});\r\n mp3Worker.postMessage({cmd: \"finish\"});\r\n\r\n mp3Worker.onmessage = (e) => {\r\n if (e.data.cmd == \"end\") {\r\n const mp3Blob = new Blob(e.data.buf, {type});\r\n MediaRecorderClass.checkAndExecFn(cb, mp3Blob);\r\n }\r\n };\r\n })\r\n }\r\n fr.onload = frOnload\r\n }\r\n switch (type) {\r\n case \"audio/webm\":\r\n MediaRecorderClass.checkAndExecFn(cb, new Blob(chunk, {type}));\r\n break;\r\n case \"audio/wav\":\r\n audioWav();\r\n break;\r\n case \"audio/mp3\":\r\n audioMp3();\r\n break;\r\n default:\r\n return void 0\r\n }\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/8/18\r\n * @describe 开始录音\r\n */\r\n startAudio = () => {\r\n const recorder = MediaRecorderClass.mediaRecorder;\r\n if (!recorder || (recorder && recorder.state === \"inactive\")) {\r\n navigator.mediaDevices.getUserMedia(constraints).then(stream => {\r\n this.recordAudio(stream);\r\n }).catch(err => {\r\n MediaRecorderClass.checkAndExecFn(this.props.errorCallback, err);\r\n // throw new Error(\"getUserMedia failed:\", err);\r\n }\r\n )\r\n return false\r\n }\r\n if (recorder && recorder.state === \"paused\") {\r\n MediaRecorderClass.resumeAudio();\r\n }\r\n }\r\n /**\r\n * @author j_bleach 2018/8/19\r\n * @describe 暂停录音\r\n */\r\n pauseAudio = () => {\r\n const recorder = MediaRecorderClass.mediaRecorder;\r\n if (recorder && recorder.state === \"recording\") {\r\n recorder.pause();\r\n recorder.onpause = () => {\r\n MediaRecorderClass.checkAndExecFn(this.props.pauseCallback);\r\n }\r\n MediaRecorderClass.audioCtx.suspend();\r\n }\r\n }\r\n /**\r\n * @author j_bleach 2018/8/18\r\n * @describe 停止录音\r\n */\r\n stopAudio = () => {\r\n const {audioType, audioOptions} = this.props;\r\n const recorder = MediaRecorderClass.mediaRecorder;\r\n if (recorder && [\"recording\", \"paused\"].includes(recorder.state)) {\r\n recorder.stop();\r\n recorder.onstop = () => {\r\n MediaRecorderClass.audioStream2Blob(audioType, audioOptions, this.props.stopCallback);\r\n MediaRecorderClass.audioChunk = []; // 结束后,清空音频存储\r\n }\r\n MediaRecorderClass.audioCtx.suspend();\r\n this.initCanvas();\r\n }\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/8/18\r\n * @describe mediaRecorder音频记录\r\n * @param stream: binary data 音频流\r\n */\r\n recordAudio(stream) {\r\n const {audioBitsPerSecond, mimeType, timeslice} = this.props;\r\n MediaRecorderClass.mediaRecorder = new MediaRecorder(stream, {audioBitsPerSecond, mimeType});\r\n MediaRecorderClass.mediaRecorder.ondataavailable = (event) => {\r\n MediaRecorderClass.checkAndExecFn(this.props.onRecordCallback, event.data);\r\n MediaRecorderClass.audioChunk.push(event.data);\r\n }\r\n MediaRecorderClass.audioCtx.resume();\r\n MediaRecorderClass.mediaRecorder.start(timeslice);\r\n MediaRecorderClass.mediaRecorder.onstart = (e) => {\r\n MediaRecorderClass.checkAndExecFn(this.props.startCallback, e);\r\n }\r\n MediaRecorderClass.mediaRecorder.onresume = (e) => {\r\n this.initAudioAnalyser(stream)\r\n MediaRecorderClass.checkAndExecFn(this.props.startCallback, e);\r\n }\r\n MediaRecorderClass.mediaRecorder.onerror = (e) => {\r\n MediaRecorderClass.checkAndExecFn(this.props.errorCallback, e);\r\n }\r\n this.initAudioAnalyser(stream)\r\n this.renderCurve(this.analyser);\r\n }\r\n\r\n /**\r\n * @author j_bleach 2019/10/31\r\n * @describe 重置音频上下文(解决谷歌浏览器 音频数组链接断开问题)\r\n */\r\n\r\n initAudioAnalyser(stream){\r\n this.analyser = MediaRecorderClass.audioCtx.createAnalyser();\r\n const source = MediaRecorderClass.audioCtx.createMediaStreamSource(stream);\r\n source.connect(this.analyser);\r\n }\r\n\r\n /**\r\n * @author j_bleach 2018/8/19\r\n * @describe 恢复录音\r\n */\r\n static resumeAudio() {\r\n MediaRecorderClass.audioCtx.resume();\r\n MediaRecorderClass.mediaRecorder.resume();\r\n }\r\n }\r\n}\r\nexport default MediaRecorderFn;"]}