Rillke has uploaded a new change for review. https://gerrit.wikimedia.org/r/145544
Change subject: Update Recorderjs to f814ac7b3f ...................................................................... Update Recorderjs to f814ac7b3f This is to support Mozilla Firefox which has deprecated `.createJavaScriptNode()` and newer versions of it do not support it. Also securing some code paths logging issues instead of throwing runtime errors. Change-Id: I62d2c5e0e227bda08aff0e0d1035cd226747ab12 --- M resources/ext.pronunciationRecording.pronunciationRecorder.js M resources/mediawiki.libs.recorderjs/recorder.js M resources/mediawiki.libs.recorderjs/recorderWorker.js 3 files changed, 71 insertions(+), 60 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/PronunciationRecording refs/changes/44/145544/1 diff --git a/resources/ext.pronunciationRecording.pronunciationRecorder.js b/resources/ext.pronunciationRecording.pronunciationRecorder.js index 8fad64b..a010d18 100644 --- a/resources/ext.pronunciationRecording.pronunciationRecorder.js +++ b/resources/ext.pronunciationRecording.pronunciationRecorder.js @@ -3,15 +3,21 @@ var audioContext, recorder, uploadHandler, uploadWizardUpload, cachedBlob, userAgent = mw.message( 'pronunciationrecording-title' ).text(); + function startUserMedia( stream ) { $( ".mw-pronunciationrecording-record" ).removeAttr('disabled'); $( ".mw-pronunciationrecording-message" ).empty(); var input = audioContext.createMediaStreamSource( stream ); mw.log( 'Media Stream created' ); - recorder = new Recorder( input ); - mw.log( 'Audio Recorder initialized' ); + try { + // This call may fail if not all APIs necessary are supported. + recorder = new Recorder( input ); + mw.log( 'Audio Recorder initialized' ); + } catch ( noRecorder ) { + // TODO: Emit error message so the UI can reflect it + mw.log( 'Audio Recorder initialization failed.' ); + } } - function getBlob( callback ) { if( cachedBlob ) { callback( cachedBlob ); @@ -83,6 +89,9 @@ return { startRecording: function() { + if ( !recorder ) { + return mw.log( 'Requested recording despite recorder was not initialized.' ); + } cachedBlob = null; recorder.clear(); recorder.record(); diff --git a/resources/mediawiki.libs.recorderjs/recorder.js b/resources/mediawiki.libs.recorderjs/recorder.js index 1f8cfc3..f627a71 100755 --- a/resources/mediawiki.libs.recorderjs/recorder.js +++ b/resources/mediawiki.libs.recorderjs/recorder.js @@ -19,7 +19,7 @@ DEALINGS IN THE SOFTWARE. */ -( function( window, mw ) { +( function( window ) { var WORKER_PATH = mw.config.get( 'wgExtensionAssetsPath' ) + '/PronunciationRecording/resources/mediawiki.libs.recorderjs/recorderWorker.js'; @@ -27,52 +27,58 @@ var config = cfg || {}; var bufferLen = config.bufferLen || 4096; this.context = source.context; - this.node = this.context.createJavaScriptNode( bufferLen, 2, 2 ); - var worker = new Worker(config.workerPath || WORKER_PATH); + this.node = ( this.context.createScriptProcessor || + this.context.createJavaScriptNode ) + .call( this.context, + bufferLen, 2, 2 ); + var worker = new Worker( config.workerPath || WORKER_PATH ); worker.postMessage( { command: 'init', config: { sampleRate: this.context.sampleRate - } + } } ); - var recording = false, - currCallback; + currCallback; this.node.onaudioprocess = function( e ) { if ( !recording ) return; worker.postMessage( { command: 'record', buffer: [ - e.inputBuffer.getChannelData(0), - e.inputBuffer.getChannelData(1) + e.inputBuffer.getChannelData( 0 ), + e.inputBuffer.getChannelData( 1 ) ] } ); } this.configure = function( cfg ) { for ( var prop in cfg ) { - if ( cfg.hasOwnProperty(prop) ){ - config[prop] = cfg[prop]; + if ( cfg.hasOwnProperty( prop ) ) { + config[ prop ] = cfg[ prop ]; } } } - this.record = function(){ + this.record = function() { recording = true; } - this.stop = function(){ + this.stop = function() { recording = false; } this.clear = function() { - worker.postMessage( { command: 'clear' } ); + worker.postMessage( { + command: 'clear' + } ); } - this.getBuffers = function( cb ) { + this.getBuffer = function( cb ) { currCallback = cb || config.callback; - worker.postMessage( { command: 'getBuffers' } ) + worker.postMessage( { + command: 'getBuffer' + } ) } this.exportWAV = function( cb, type ) { @@ -81,16 +87,6 @@ if ( !currCallback ) throw new Error( 'Callback not set' ); worker.postMessage( { command: 'exportWAV', - type: type - } ); - } - - this.exportMonoWAV = function( cb, type ) { - currCallback = cb || config.callback; - type = type || config.type || 'audio/wav'; - if ( !currCallback ) throw new Error( 'Callback not set' ); - worker.postMessage( { - command: 'exportMonoWAV', type: type } ); } @@ -101,9 +97,20 @@ } source.connect( this.node ); - this.node.connect( this.context.destination ); + this.node.connect( this.context.destination ); //this should not be necessary }; + + Recorder.forceDownload = function( blob, filename ) { + var url = ( window.URL || window.webkitURL ) + .createObjectURL( blob ); + var link = window.document.createElement( 'a' ); + link.href = url; + link.download = filename || 'output.wav'; + var click = document.createEvent( "Event" ); + click.initEvent( "click", true, true ); + link.dispatchEvent( click ); + } window.Recorder = Recorder; -} )( window, mediaWiki ); +} )( window ); diff --git a/resources/mediawiki.libs.recorderjs/recorderWorker.js b/resources/mediawiki.libs.recorderjs/recorderWorker.js index aec158a..567f243 100755 --- a/resources/mediawiki.libs.recorderjs/recorderWorker.js +++ b/resources/mediawiki.libs.recorderjs/recorderWorker.js @@ -20,12 +20,12 @@ */ var recLength = 0, -recBuffersL = [], -recBuffersR = [], -sampleRate; + recBuffersL = [], + recBuffersR = [], + sampleRate; this.onmessage = function( e ) { - switch( e.data.command ) { + switch ( e.data.command ) { case 'init': init( e.data.config ); break; @@ -35,11 +35,8 @@ case 'exportWAV': exportWAV( e.data.type ); break; - case 'exportMonoWAV': - exportMonoWAV( e.data.type ); - break; - case 'getBuffers': - getBuffers(); + case 'getBuffer': + getBuffer(); break; case 'clear': clear(); @@ -52,9 +49,9 @@ } function record( inputBuffer ) { - recBuffersL.push( inputBuffer[0] ); - recBuffersR.push( inputBuffer[1] ); - recLength += inputBuffer[0].length; + recBuffersL.push( inputBuffer[ 0 ] ); + recBuffersR.push( inputBuffer[ 1 ] ); + recLength += inputBuffer[ 0 ].length; } function exportWAV( type ) { @@ -62,18 +59,14 @@ var bufferR = mergeBuffers( recBuffersR, recLength ); var interleaved = interleave( bufferL, bufferR ); var dataview = encodeWAV( interleaved ); - var audioBlob = new Blob( [dataview], { type: type } ); + var audioBlob = new Blob( [ dataview ], { + type: type + } ); + this.postMessage( audioBlob ); } -function exportMonoWAV( type ) { - var bufferL = mergeBuffers( recBuffersL, recLength ); - var dataview = encodeWAV( bufferL, true ); - var audioBlob = new Blob( [dataview], { type: type } ); - this.postMessage( audioBlob ); -} - -function getBuffers() { +function getBuffer() { var buffers = []; buffers.push( mergeBuffers( recBuffersL, recLength ) ); buffers.push( mergeBuffers( recBuffersR, recLength ) ); @@ -90,8 +83,8 @@ var result = new Float32Array( recLength ); var offset = 0; for ( var i = 0; i < recBuffers.length; i++ ) { - result.set( recBuffers[i], offset ); - offset += recBuffers[i].length; + result.set( recBuffers[ i ], offset ); + offset += recBuffers[ i ].length; } return result; } @@ -99,20 +92,21 @@ function interleave( inputL, inputR ) { var length = inputL.length + inputR.length; var result = new Float32Array( length ); + var index = 0, - inputIndex = 0; + inputIndex = 0; while ( index < length ) { - result[index++] = inputL[inputIndex]; - result[index++] = inputR[inputIndex]; + result[ index++ ] = inputL[ inputIndex ]; + result[ index++ ] = inputR[ inputIndex ]; inputIndex++; } return result; } function floatTo16BitPCM( output, offset, input ) { - for ( var i = 0; i < input.length; i++, offset+=2 ) { - var s = Math.max( -1, Math.min( 1, input[i] ) ); + for ( var i = 0; i < input.length; i++, offset += 2 ) { + var s = Math.max( -1, Math.min( 1, input[ i ] ) ); output.setInt16( offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true ); } } @@ -123,7 +117,7 @@ } } -function encodeWAV( samples, mono ) { +function encodeWAV( samples ) { var buffer = new ArrayBuffer( 44 + samples.length * 2 ); var view = new DataView( buffer ); @@ -140,7 +134,7 @@ /* sample format (raw) */ view.setUint16( 20, 1, true ); /* channel count */ - view.setUint16( 22, mono?1:2, true ); + view.setUint16( 22, 2, true ); /* sample rate */ view.setUint32( 24, sampleRate, true ); /* byte rate (sample rate * block align) */ @@ -153,6 +147,7 @@ writeString( view, 36, 'data' ); /* data chunk length */ view.setUint32( 40, samples.length * 2, true ); + floatTo16BitPCM( view, 44, samples ); return view; -- To view, visit https://gerrit.wikimedia.org/r/145544 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I62d2c5e0e227bda08aff0e0d1035cd226747ab12 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/PronunciationRecording Gerrit-Branch: master Gerrit-Owner: Rillke <ril...@wikipedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits