websoket/imrecorder.js
developertrinidad08 7e6cf29479 first commit
2023-01-16 18:11:14 -03:00

519 lines
16 KiB
JavaScript

function IMRecorder() {
var me = this;
var recorded = false;
//------------------------------------------------------------
// Destroy all
//------------------------------------------------------------
terminate = function () {
reset(); // Chronometer
me.recorder && me.recorder.stop();
me.recorder && me.recorder.clear() && delete me.recorder;
if(me.wavesurfer.isPlaying()) {
me.wavesurfer.pause();
};
me.wavesurfer.empty();
me.microphone.stop();
delete me.microphone;
delete me.wavesurfer;
//document.body.innerHTML = ''; | Elimina el html del grabador.
//window.location.replace('about:blank'); | Carga una pantalla en blanco.
};
this.terminate = function() {
terminate();
};
//------------------------------------------------------------
// Open wav from server arrayBuffer
//------------------------------------------------------------
this.openFromArrayBuffer = function(arrayBuffer) {
Ciseaux.from(arrayBuffer).then(function(tape) {
tape.render().then(function(audiobuffer) {
me.wavesurfer.loadDecodedBuffer(audiobuffer);
me.oldtape = tape;
set(tottime()); // Chronometer
});
}, function(error) {
console.log('El archivo solicitado no existe o está corrupto.');
//terminate();
if(afterLoad !== null) afterLoad();
});
}
//------------------------------------------------------------
// Load wav from server
//------------------------------------------------------------
this.load = function (url, afterLoad) {
Ciseaux.from(url).then(function(tape) {
if(afterLoad !== null) afterLoad();
tape.render().then(function(audiobuffer) {
me.wavesurfer.loadDecodedBuffer(audiobuffer);
me.oldtape = tape;
set(tottime()); // Chronometer
});
}, function(error) {
console.log('El archivo solicitado no existe o está corrupto.');
//terminate();
if(afterLoad !== null) afterLoad();
});
}
//------------------------------------------------------------
// Quit recording.
//------------------------------------------------------------
var out = function () {
var q = confirm("Si desea salir sin grabar, pulse Ok.\nEn caso contrario, pulse Cancel.");
if (q == true) {
terminate();
}
};
//------------------------------------------------------------
// Save wav to server
//------------------------------------------------------------
this.save = function (url, aOnProgress, aOnDone) {
if(recorded === false) {
// Saliendo sin guardar audio.
aOnDone();
return;
};
// Guardando audio.
//
// primero obtenemos "oldtape" como audiobuffer
var progr = aOnProgress;
var ondone = aOnDone;
me.oldtape.render().then(function(audiobuffer) {
// una vez obtenido el buffer generamos el wav
// código obtenido desde: http://stackoverflow.com/questions/22560413/html5-web-audio-convert-audio-buffer-into-wav-file
// start a new worker
// we can't use Recorder directly, since it doesn't support what we're trying to do
var worker = new Worker('js/recorderWorker.js');
// initialize the new worker
worker.postMessage({
command: 'init',
config: {
numChannels: me.recorder.config.numChannels,
sampleRate: me.recorder.context.sampleRate
}
});
// callback for "exportWAV"
worker.onmessage = function( e ) {
var blob = e.data;
// this is would be your WAV blob
// por último enviamos el wav a destino
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.upload.onprogress = progr;
xhr.onload = function () {
if (xhr.status === 200) {
aOnDone();
} else {
alert('An error occurred while uploading recording!');
}
};
xhr.send(blob);
};
// send the channel data from our buffer to the worker
worker.postMessage({
command: 'record',
buffer: [
audiobuffer.getChannelData(0)
//audiobuffer.getChannelData(1)
]
});
// ask the worker for a WAV
worker.postMessage({
command: 'exportWAV',
type: 'audio/wav'
});
});
//terminate();
};
//------------------------------------------------------------
// Save wav to websocket
//------------------------------------------------------------
// La función está asignada a la propiedad onmessage del WebSocket,
//lo que significa que se ejecutará cada vez que el WebSocket reciba un mensaje.
// El mensaje recibido es un objeto Blob de audio, que se procesa con la función exportWAV del objeto recorder.
// Esta función devuelve un objeto Blob con el audio codificado en formato WAV.
// El objeto Blob se convierte a una matriz de bytes (ArrayBuffer) con la ayuda del objeto FileReader.
// Finalmente, se envía la matriz de bytes a través del WebSocket con el método send.
this.save1 = function () {
// me.ws.onmessage = function() {
// // Aquí puedes procesar el mensaje recibido y hacer algo con él
// const audioBlob = me.recorder.exportWAV(
// function(blob) {
// me.url = URL.createObjectURL(blob);
// me.myblob = blob;
// Ciseaux.from(me.url).then(function(tape) {
// var lPos = me.seekpos;
// var lDur = tape.tracks[0].duration;
// me.oldtape = me.oldtape.replace(lPos, lDur, tape);
// me.oldtape.render().then(function(audiobuffer){
// me.ws.binaryType = "blob";
// me.recorder.clear();
// me.wavesurfer.empty();
// me.wavesurfer.loadDecodedBuffer(audiobuffer);
// me.wavesurfer.skip(lPos + lDur);
// });
// });
// }
// );
// const reader = new FileReader();
// reader.onload = function() {
// me.ws = new WebSocket("ws://localhost:8000");
// me.ws.send(reader.result);
// };
// };
me.ws.onmessage = function(event) {
console.log(event.data)
var audioData = me.wavesurfer.microphone.getAudioData();
var binaryAudioData = new Float32Array(audioData);
var buffer = new ArrayBuffer(binaryAudioData.length * 4);
var view = new Float32Array(buffer);
for (var i = 0; i < binaryAudioData.length; i++) {
view[i] = binaryAudioData[i];
}
var ws = new WebSocket('ws://localhost:8000');
ws.binaryType = 'arraybuffer';
ws.onopen = function() {
ws.send(buffer);
};
};
terminate();
};
//------------------------------------------------------------
// Calculate total blob duration on wavesurfer canvas
//------------------------------------------------------------
totlen = function () {
var ini = new Date().getTime();
var num = Math.ceil(me.wavesurfer.getDuration() * 1000);
var fin = ini + num;
var lap = fin - ini;
totpos = lap / 1000;
}
//------------------------------------------------------------
// Calculate partial blob duration on wavesurfer canvas
//------------------------------------------------------------
parlen = function () {
var ini = new Date().getTime();
var num = Math.ceil(me.wavesurfer.getCurrentTime() * 1000);
var fin = ini + num;
var lap = fin - ini;
me.seekpos = lap / 1000;
}
//------------------------------------------------------------
// Calculate total blob duration on stopwatch display
//------------------------------------------------------------
tottime = function () {
var ini = new Date().getTime();
var num = Math.ceil(me.wavesurfer.getDuration() * 1000);
var fin = ini + num;
var lap = fin - ini;
return lap;
}
//------------------------------------------------------------
// Calculate partial blob duration on stopwatch display
//------------------------------------------------------------
partime = function () {
var ini = new Date().getTime();
var num = Math.ceil(me.wavesurfer.getCurrentTime() * 1000);
var fin = ini + num;
var lap = fin - ini;
return lap;
}
//------------------------------------------------------------
// Create empty blob
//------------------------------------------------------------
emptyBlob = function () {
me.oldtape = new Ciseaux.Tape();
me.recorder && me.recorder.clear();
}
//------------------------------------------------------------
// Generate blob
//------------------------------------------------------------
createBlob = function () {
me.recorder.exportWAV(function(blob) {
me.url = URL.createObjectURL(blob);
me.myblob = blob;
Ciseaux.from(me.url).then(function(tape) {
var lPos = me.seekpos;
var lDur = tape.tracks[0].duration;
me.oldtape = me.oldtape.replace(lPos, lDur, tape);
me.oldtape.render().then(function(audiobuffer){
me.recorder.clear();
me.wavesurfer.empty();
me.wavesurfer.loadDecodedBuffer(audiobuffer);
me.wavesurfer.skip(lPos + lDur);
});
});
});
}
//------------------------------------------------------------
// PLAY/STOP on button click
//------------------------------------------------------------
this.play_stop = function() {
me.wavesurfer.playPause();
};
//------------------------------------------------------------
// RECORD on button click
//------------------------------------------------------------
record = function() {
start(); // Chronometer
me.microphone.play();
me.recorder.record(function() {
console.log("here");
});
recorded = true;
}
//------------------------------------------------------------
// PAUSE on button click
//------------------------------------------------------------
this.pause = function(){
stop(); // Chronometer
me.microphone.pause();
me.recorder.stop();
createBlob();
}
//------------------------------------------------------------
// REVIEW on button click
//------------------------------------------------------------
this.review = function() {
me.wavesurfer.skipBackward(me.wavesurfer.getDuration() / 5);
};
//------------------------------------------------------------
// CUE on button click
//------------------------------------------------------------
this.cue = function() {
me.wavesurfer.skipForward(me.wavesurfer.getDuration() / 5);
};
//------------------------------------------------------------
// Get voiceRecognitionBuffer
//------------------------------------------------------------
this.processVoiceRecognition = function(voiceRecognitionAudioBlob) {
if(!me.recorder) return;
// Web Socket is connected, send data using send()
var d = { "config": { "sample_rate": 44100 } };
me.ws.send(JSON.stringify(d));
me.ws.binaryType = "blob";
me.ws.send(voiceRecognitionAudioBlob);
};
//------------------------------------------------------------
// CLEAR on button click
//------------------------------------------------------------
this.clear_rec = function() {
var r = confirm("Para borrar la grabación y crear una nueva, pulse Ok.\nPara continuar, pulse Cancel.");
if (r == true) {
reset(); // Chronometer
me.recorder && me.recorder.clear();
me.wavesurfer.empty();
emptyBlob();
}
};
//------------------------------------------------------------
// QUIT on button click
//------------------------------------------------------------
quit_click = function() {
out();
};
//------------------------------------------------------------
// START/STOP mic on button click or start recording
//------------------------------------------------------------
this.rec_pause_toggle = function() {
if( me.recstate === undefined ) {
// esto abre la ventana de solicitud de habilitación del micrófono
me.microphone.start();
}
else if( me.recstate === "REC" ) {
me.recstate = "PAUSED";
this.pause();
} else {
me.recstate = "REC";
record();
}
};
//------------------------------------------------------------
// STOP mic on button click
//------------------------------------------------------------
this.rec_pause = function() {
if( me.recstate === "REC" ) {
me.recstate = "PAUSED";
this.pause();
}
};
//------------------------------------------------------------
// STOP play on button click
//------------------------------------------------------------
this.play_pause = function() {
if(me.wavesurfer.isPlaying()) {
me.wavesurfer.pause();
};
};
//------------------------------------------------------------
// voiceRecognitionAudioBlobCallback
//------------------------------------------------------------
this.voiceRecognitionAudioBlobCallback = function(blob) {
var audioBlob = new Blob([blob], { type: 'audio/wav' });
me.processVoiceRecognition(audioBlob);
};
//------------------------------------------------------------
// Initialize object
//------------------------------------------------------------
init = function () {
//------------------------------------------------------------
// General global variables
//------------------------------------------------------------
me.recorder;
me.recstate = undefined; // Primera pasada (sólo para incializar el micrófono
me.newtape;
me.oldtape;
me.totpos = 0;
me.seekpos = 0;
me.url = null;
me.recContext;
recContext = new AudioContext;
//------------------------------------------------------------
// Options for playing canvas
//------------------------------------------------------------
me.optplay = {
container : '#waveform',
waveColor : 'darkorange',
progressColor : 'purple',
height : 40,
interact : true,
hideScrollbar : true,
cursorColor : 'darkgray',
cursorWidth : 1,
normalize : true,
audioRate : 1
};
//------------------------------------------------------------
// Create a wavesurfer instance
//------------------------------------------------------------
me.wavesurfer = Object.create(WaveSurfer);
me.wavesurfer.init(me.optplay); // Init wavesurfer for recording
//------------------------------------------------------------
// Wavesurfer events
//------------------------------------------------------------
me.wavesurfer.on('seek', function () {
set(partime()); // Chronometer
totlen();
parlen();
});
me.wavesurfer.on('play', function () {
set(partime()); // Chronometer
start(); // Chronometer
});
me.wavesurfer.on('pause', function () {
stop(); // Chronometer
});
me.wavesurfer.on('ready', function () {
//
});
//------------------------------------------------------------
// Create new audio context and blank tape
//------------------------------------------------------------
var cisContext = new AudioContext();
Ciseaux.context = cisContext;
emptyBlob();
show(); // muestra el timer
//------------------------------------------------------------
// Init Microphone plugin
//------------------------------------------------------------
me.microphone = Object.create(WaveSurfer.Microphone);
me.microphone.init({wavesurfer: me.wavesurfer});
me.microphone.on('deviceReady', function(stream) {
var mic_input = recContext.createMediaStreamSource(stream);
me.recorder = new Recorder(mic_input, {numChannels: 1}, me.voiceRecognitionAudioBlobCallback);
me.recstate = "REC";
record();
});
me.microphone.on('deviceError', function(code) {
console.warn('Device error: ' + code);
});
me.ws = new WebSocket("ws://localhost:8000");
me.ws.onopen = function() {
console.log("conectado");
me.wsoen = true;
};
me.ws.onclose = function() {
// websocket is closed.
console.log("desconectado");
};
};
// init method is called fron within object
// no need to be called from the outside
init();
};