ld-videojs-record
Version:
A video.js plugin for recording audio/video/image files.
8 lines • 17.1 kB
JavaScript
/*!
* vmsg plugin for ld-videojs-record
* @version 0.0.1
* @see https://github.com/collab-project/videojs-record
* @copyright 2014-2020 Collab
* @license MIT
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("videojs")):"function"==typeof define&&define.amd?define("vmsg",["videojs"],t):"object"==typeof exports?exports.vmsg=t(require("videojs")):(e.VideojsRecord=e.VideojsRecord||{},e.VideojsRecord.vmsg=t(e.videojs))}(window,(function(e){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=34)}([function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t){e.exports=function(e){return e&&e.__esModule?e:{default:e}}},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}e.exports=function(e,t,i){return t&&n(e.prototype,t),i&&n(e,i),e}},function(e,t,n){var i=n(5),r=n(6);e.exports=function(e,t){return!t||"object"!==i(t)&&"function"!=typeof t?r(e):t}},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?e.exports=n=function(e){return typeof e}:e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(t)}e.exports=n},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t,n){var i=n(8);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&i(e,t)}},function(e,t){function n(t,i){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,i)}e.exports=n},function(t,n){t.exports=e},,,,,,,,,,,,,,,,,,,,,,,,,function(e,t,n){"use strict";var i=n(1);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=i(n(2)),o=i(n(3)),s=i(n(4)),a=i(n(0)),c=i(n(7)),l=i(n(9)),u=n(35),d=function(e){function t(e,n){var i;return(0,r.default)(this,t),(i=(0,s.default)(this,(0,a.default)(t).call(this,e,n))).debug=!1,i.audioWebAssemblyURL="vmsg.wasm",i.pluginLibraryOptions={},i}return(0,c.default)(t,e),(0,o.default)(t,[{key:"setup",value:function(e,t,n){var i=this;this.inputStream=e,this.mediaType=t,this.debug=n,this.config={wasmURL:this.audioWebAssemblyURL},this.config=Object.assign(this.config,this.pluginLibraryOptions),this.engine=new u.Recorder(this.config,this.onRecordingAvailable.bind(this)),this.engine.stream=this.inputStream;var r=window.AudioContext||window.webkitAudioContext;this.audioContext=new r,this.audioSourceNode=this.audioContext.createMediaStreamSource(this.inputStream),this.processor=this.audioContext.createScriptProcessor(0,1,1),this.audioSourceNode.connect(this.processor),this.engine.initWorker().catch((function(e){i.player().trigger("error",e)}))}},{key:"start",value:function(){this.engine.blob=null,this.engine.blobURL&&URL.revokeObjectURL(this.engine.blobURL),this.engine.blobURL=null,this.engine.worker.postMessage({type:"start",data:this.audioContext.sampleRate}),this.processor.onaudioprocess=this.onAudioProcess.bind(this),this.processor.connect(this.audioContext.destination)}},{key:"stop",value:function(){this.processor&&(this.processor.disconnect(),this.processor.onaudioprocess=null),this.engine&&void 0!==this.engine.worker&&this.engine.worker.postMessage({type:"stop",data:null})}},{key:"destroy",value:function(){this.engine&&"function"==typeof this.engine.close&&this.engine.close()}},{key:"onAudioProcess",value:function(e){var t=e.inputBuffer.getChannelData(0);this.engine.worker.postMessage({type:"data",data:t})}},{key:"onRecordingAvailable",value:function(){this.onStopRecording(this.engine.blob)}}]),t}(l.default.getComponent("RecordEngine"));l.default.VmsgEngine=d;var h=d;t.default=h,e.exports=t.default},function(e,t,n){"use strict";function i(e){return(e|=0)<10?`0${e}`:`${Math.min(e,99)}`}function r(){function e(e,t){return new Promise((n,i)=>{const r=new XMLHttpRequest;r.open("GET",e),r.responseType="arraybuffer",r.onload=()=>{n(WebAssembly.instantiate(r.response,t))},r.onerror=i,r.send()})}let t=null,n=5242880;function i(e){const t=n;return n+=e,t}function r(e){postMessage({type:"internal-error",data:e})}let o=null,s=null,a=null;onmessage=n=>{const c=n.data;switch(c.type){case"init":const{wasmURL:n,shimURL:l}=c.data;Promise.resolve().then(()=>(self.WebAssembly&&!function(){const e=new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,1,127,1,127,3,2,1,0,5,3,1,0,1,7,8,1,4,116,101,115,116,0,0,10,16,1,14,0,32,0,65,1,54,2,0,32,0,40,2,0,11]),t=new WebAssembly.Module(e);return 0!==new WebAssembly.Instance(t,{}).exports.test(4)}()&&delete self.WebAssembly,self.WebAssembly||importScripts(l),t=new WebAssembly.Memory({initial:256,maximum:256}),{memory:t,pow:Math.pow,exit:r,powf:Math.pow,exp:Math.exp,sqrtf:Math.sqrt,cos:Math.cos,log:Math.log,sin:Math.sin,sbrk:i})).then(t=>(function(t,n){if(!WebAssembly.instantiateStreaming)return e(t,n);const i=fetch(t,{credentials:"same-origin"});return WebAssembly.instantiateStreaming(i,n).catch(i=>{if(i.message&&i.message.indexOf("Argument 0 must be provided and must be a Response")>0)return e(t,n);throw i})})(n,{env:t})).then(e=>{o=e.instance.exports,postMessage({type:"init",data:null})}).catch(e=>{postMessage({type:"init-error",data:e.toString()})});break;case"start":if(!function(e){if(s=o.vmsg_init(e),!s)return!1;const n=new Uint32Array(t.buffer,s,1)[0];return a=new Float32Array(t.buffer,n),!0}(c.data))return postMessage({type:"error",data:"vmsg_init"});break;case"data":if(!function(e){return a.set(e),o.vmsg_encode(s,e.length)>=0}(c.data))return postMessage({type:"error",data:"vmsg_encode"});break;case"stop":const u=function(){if(o.vmsg_flush(s)<0)return null;const e=new Uint32Array(t.buffer,s+4,1)[0],n=new Uint32Array(t.buffer,s+8,1)[0],i=new Uint8Array(t.buffer,e,n),r=new Blob([i],{type:"audio/mpeg"});return o.vmsg_free(s),s=null,a=null,r}();if(!u)return postMessage({type:"error",data:"vmsg_flush"});postMessage({type:"stop",data:u})}}}n.r(t),n.d(t,"Recorder",(function(){return o})),n.d(t,"Form",(function(){return s})),n.d(t,"record",(function(){return c}));class o{constructor(e={},t=null){this.wasmURL=new URL(e.wasmURL||"/static/js/vmsg.wasm",location).href,this.shimURL=new URL(e.shimURL||"/static/js/wasm-polyfill.js",location).href,this.onStop=t,this.pitch=e.pitch||0,this.stream=null,this.audioCtx=null,this.gainNode=null,this.pitchFX=null,this.encNode=null,this.worker=null,this.workerURL=null,this.blob=null,this.blobURL=null,this.resolve=null,this.reject=null,Object.seal(this)}close(){this.encNode&&this.encNode.disconnect(),this.encNode&&(this.encNode.onaudioprocess=null),this.stream&&this.stopTracks(),this.audioCtx&&this.audioCtx.close(),this.worker&&this.worker.terminate(),this.workerURL&&URL.revokeObjectURL(this.workerURL),this.blobURL&&URL.revokeObjectURL(this.blobURL)}initAudio(){return(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?function(e){return navigator.mediaDevices.getUserMedia(e)}:function(e){const t=navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((function(n,i){t.call(navigator,e,n,i)})):Promise.reject(new Error("getUserMedia is not implemented in this browser"))})({audio:!0}).then(e=>{this.stream=e;const t=this.audioCtx=new(window.AudioContext||window.webkitAudioContext),n=t.createMediaStreamSource(e),i=this.gainNode=(t.createGain||t.createGainNode).call(t);i.gain.value=1,n.connect(i);const r=this.pitchFX=new p(t);r.setPitchOffset(this.pitch);const o=this.encNode=(t.createScriptProcessor||t.createJavaScriptNode).call(t,0,1,1);r.output.connect(o),i.connect(0===this.pitch?o:r.input)})}initWorker(){if(!this.stream)throw new Error("missing audio initialization");const e=new Blob(["(",r.toString(),")()"],{type:"application/javascript"}),t=this.workerURL=URL.createObjectURL(e),n=this.worker=new Worker(t),{wasmURL:i,shimURL:o}=this;return n.postMessage({type:"init",data:{wasmURL:i,shimURL:o}}),new Promise((e,t)=>{n.onmessage=n=>{const i=n.data;switch(i.type){case"init":e();break;case"init-error":t(new Error(i.data));break;case"error":case"internal-error":console.error("Worker error:",i.data),this.reject&&this.reject(i.data);break;case"stop":this.blob=i.data,this.blobURL=URL.createObjectURL(i.data),this.onStop&&this.onStop(),this.resolve&&this.resolve(this.blob)}}})}init(){return this.initAudio().then(this.initWorker.bind(this))}startRecording(){if(!this.stream)throw new Error("missing audio initialization");if(!this.worker)throw new Error("missing worker initialization");this.blob=null,this.blobURL&&URL.revokeObjectURL(this.blobURL),this.blobURL=null,this.resolve=null,this.reject=null,this.worker.postMessage({type:"start",data:this.audioCtx.sampleRate}),this.encNode.onaudioprocess=e=>{const t=e.inputBuffer.getChannelData(0);this.worker.postMessage({type:"data",data:t})},this.encNode.connect(this.audioCtx.destination)}stopRecording(){if(!this.stream)throw new Error("missing audio initialization");if(!this.worker)throw new Error("missing worker initialization");return this.encNode.disconnect(),this.encNode.onaudioprocess=null,this.stopTracks(),this.worker.postMessage({type:"stop",data:null}),new Promise((e,t)=>{this.resolve=e,this.reject=t})}stopTracks(){this.stream.getTracks&&this.stream.getTracks().forEach(e=>e.stop())}}class s{constructor(e={},t,n){this.recorder=new o(e,this.onStop.bind(this)),this.resolve=t,this.reject=n,this.backdrop=null,this.popup=null,this.recordBtn=null,this.stopBtn=null,this.timer=null,this.audio=null,this.saveBtn=null,this.tid=0,this.start=0,Object.seal(this),this.recorder.initAudio().then(()=>this.drawInit()).then(()=>this.recorder.initWorker()).then(()=>this.drawAll()).catch(e=>this.drawError(e))}drawInit(){if(this.backdrop)return;const e=this.backdrop=document.createElement("div");e.className="vmsg-backdrop",e.addEventListener("click",()=>this.close(null));const t=this.popup=document.createElement("div");t.className="vmsg-popup",t.addEventListener("click",e=>e.stopPropagation());const n=document.createElement("div");n.className="vmsg-progress";for(let e=0;e<3;e++){const e=document.createElement("div");e.className="vmsg-progress-dot",n.appendChild(e)}t.appendChild(n),e.appendChild(t),document.body.appendChild(e)}drawTime(e){const t=Math.round(e/1e3);this.timer.textContent=i(t/60)+":"+i(t%60)}drawAll(){this.drawInit(),this.clearAll();const e=document.createElement("div");e.className="vmsg-record-row",this.popup.appendChild(e);const t=this.recordBtn=document.createElement("button");t.className="vmsg-button vmsg-record-button",t.textContent="●",t.addEventListener("click",()=>this.startRecording()),e.appendChild(t);const n=this.stopBtn=document.createElement("button");n.className="vmsg-button vmsg-stop-button",n.style.display="none",n.textContent="■",n.addEventListener("click",()=>this.stopRecording()),e.appendChild(n);const i=this.audio=new Audio;i.autoplay=!0;const r=this.timer=document.createElement("span");r.className="vmsg-timer",r.addEventListener("click",()=>{i.paused?this.recorder.blobURL&&(i.src=this.recorder.blobURL):i.pause()}),this.drawTime(0),e.appendChild(r);const o=this.saveBtn=document.createElement("button");o.className="vmsg-button vmsg-save-button",o.textContent="✓",o.disabled=!0,o.addEventListener("click",()=>this.close(this.recorder.blob)),e.appendChild(o);const s=document.createElement("div");s.className="vmsg-slider-wrapper vmsg-gain-slider-wrapper";const a=document.createElement("input");a.className="vmsg-slider vmsg-gain-slider",a.setAttribute("type","range"),a.min=0,a.max=2,a.step=.2,a.value=1,a.onchange=()=>{const e=+a.value;this.recorder.gainNode.gain.value=e},s.appendChild(a),this.popup.appendChild(s);const c=document.createElement("div");c.className="vmsg-slider-wrapper vmsg-pitch-slider-wrapper";const l=document.createElement("input");l.className="vmsg-slider vmsg-pitch-slider",l.setAttribute("type","range"),l.min=-1,l.max=1,l.step=.2,l.value=this.recorder.pitch,l.onchange=()=>{const e=+l.value;this.recorder.pitchFX.setPitchOffset(e),this.recorder.gainNode.disconnect(),this.recorder.gainNode.connect(0===e?this.recorder.encNode:this.recorder.pitchFX.input)},c.appendChild(l),this.popup.appendChild(c)}drawError(e){console.error(e),this.drawInit(),this.clearAll();const t=document.createElement("div");t.className="vmsg-error",t.textContent=e.toString(),this.popup.appendChild(t)}clearAll(){this.popup&&(this.popup.innerHTML="")}close(e){this.audio&&this.audio.pause(),this.tid&&clearTimeout(this.tid),this.recorder.close(),this.backdrop.remove(),e?this.resolve(e):this.reject(new Error("No record made"))}onStop(){this.recordBtn.style.display="",this.stopBtn.style.display="none",this.stopBtn.disabled=!1,this.saveBtn.disabled=!1}startRecording(){this.audio.pause(),this.start=Date.now(),this.updateTime(),this.recordBtn.style.display="none",this.stopBtn.style.display="",this.saveBtn.disabled=!0,this.recorder.startRecording()}stopRecording(){clearTimeout(this.tid),this.tid=0,this.stopBtn.disabled=!0,this.recorder.stopRecording()}updateTime(){this.drawTime(Date.now()-this.start),this.tid=setTimeout(()=>this.updateTime(),300)}}let a=!1;function c(e){return new Promise((t,n)=>{if(a)throw new Error("Record form is already opened");a=!0,new s(e,t,n)}).then(e=>(a=!1,e),e=>{throw a=!1,e})}t.default={Recorder:o,Form:s,record:c};const l=.1,u=.05,d=.1;function h(e,t,n,i){for(var r=t*e.sampleRate,o=r+(t-2*n)*e.sampleRate,s=e.createBuffer(1,o,e.sampleRate),a=s.getChannelData(0),c=0;c<r;++c)a[c]=i?(r-c)/o:c/r;for(c=r;c<o;++c)a[c]=0;return s}function p(e){this.context=e;var t=(e.createGain||e.createGainNode).call(e),n=(e.createGain||e.createGainNode).call(e);this.input=t,this.output=n;var i=e.createBufferSource(),r=e.createBufferSource(),o=e.createBufferSource(),s=e.createBufferSource();this.shiftDownBuffer=h(e,d,u,!1),this.shiftUpBuffer=h(e,d,u,!0),i.buffer=this.shiftDownBuffer,r.buffer=this.shiftDownBuffer,o.buffer=this.shiftUpBuffer,s.buffer=this.shiftUpBuffer,i.loop=!0,r.loop=!0,o.loop=!0,s.loop=!0;var a=(e.createGain||e.createGainNode).call(e),c=(e.createGain||e.createGainNode).call(e),p=(e.createGain||e.createGainNode).call(e);p.gain.value=0;var f=(e.createGain||e.createGainNode).call(e);f.gain.value=0,i.connect(a),r.connect(c),o.connect(p),s.connect(f);var m=(e.createGain||e.createGainNode).call(e),b=(e.createGain||e.createGainNode).call(e),g=(e.createDelay||e.createDelayNode).call(e),v=(e.createDelay||e.createDelayNode).call(e);a.connect(m),c.connect(b),p.connect(m),f.connect(b),m.connect(g.delayTime),b.connect(v.delayTime);var y=e.createBufferSource(),w=e.createBufferSource(),R=function(e,t,n){for(var i=t*e.sampleRate,r=i+(t-2*n)*e.sampleRate,o=e.createBuffer(1,r,e.sampleRate),s=o.getChannelData(0),a=n*e.sampleRate,c=a,l=i-a,u=0;u<i;++u){var d;d=u<c?Math.sqrt(u/a):u>=l?Math.sqrt(1-(u-l)/a):1,s[u]=d}for(u=i;u<r;++u)s[u]=0;return o}(e,d,u);y.buffer=R,w.buffer=R,y.loop=!0,w.loop=!0;var k=(e.createGain||e.createGainNode).call(e),x=(e.createGain||e.createGainNode).call(e);k.gain.value=0,x.gain.value=0,y.connect(k.gain),w.connect(x.gain),t.connect(g),t.connect(v),g.connect(k),v.connect(x),k.connect(n),x.connect(n);var U=e.currentTime+.05,L=U+d-u;i.start(U),r.start(L),o.start(U),s.start(L),y.start(U),w.start(L),this.mod1=i,this.mod2=r,this.mod1Gain=a,this.mod2Gain=c,this.mod3Gain=p,this.mod4Gain=f,this.modGain1=m,this.modGain2=b,this.fade1=y,this.fade2=w,this.mix1=k,this.mix2=x,this.delay1=g,this.delay2=v,this.setDelay(l)}p.prototype.setDelay=function(e){this.modGain1.gain.setTargetAtTime(.5*e,0,.01),this.modGain2.gain.setTargetAtTime(.5*e,0,.01)},p.prototype.setPitchOffset=function(e){e>0?(this.mod1Gain.gain.value=0,this.mod2Gain.gain.value=0,this.mod3Gain.gain.value=1,this.mod4Gain.gain.value=1):(this.mod1Gain.gain.value=1,this.mod2Gain.gain.value=1,this.mod3Gain.gain.value=0,this.mod4Gain.gain.value=0),this.setDelay(l*Math.abs(e))}}])}));