Escribí una página simple en js y php para grabar audio en vivo desde el micrófono. La lógica es simple:
JS
PHP
Los datos se escriben con éxito en el archivo, pero cuando intento reproducirlos, el reproductor dice que el archivo está roto.
La solución de blob de la guía de Mozilla funcionó para mí, quiero exactamente la solución PHP con guardar (reescribir) en el archivo.
El código completo a continuación, ¿qué estoy haciendo mal?
<?php if(isset($_POST["data"])) { file_put_contents("r.ogg", base64_decode($_POST["data"])); exit; } ?> <script> var mediaRecorder = null; let chunks = []; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { console.log('getUserMedia supported.'); navigator.mediaDevices.getUserMedia ( { audio: true }) .then(function(stream) { mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(2000); mediaRecorder.ondataavailable = function(e) { chunks.push(e.data); const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' }); chunks = []; var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { var data = reader.result.split(";base64,")[1]; requestp2("a.php", "data="+encodeURIComponent(data)); } } }) .catch(function(err) { console.log('The following getUserMedia error occurred: ' + err); } ); } else { console.log('getUserMedia not supported on your browser!'); } function requestp2(path, data) { var http = new XMLHttpRequest(); http.open('POST', path, true); http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); http.send(data); } </script>Está tratando de elegir su formato de audio y códec especificando un tipo de medio en su constructor Blob. No puedes hacer eso™.
Especifique el tipo de medio en su constructor de MediaRecorder en su lugar. ¡Algo como esto, no depurado!
... /* here's the media type definition vvv */ mrOptions = {mimeType: 'audio/ogg; codecs=opus'} mediaRecorder = new MediaRecorder(stream, mrOptions) mediaRecorder.start(2000) mediaRecorder.ondataavailable = function(e) { ... const blob = new Blob(chunks, { type : mediaRecorder.mimeType }) ... También puede haber algunos problemas con el manejo de los fragmentos de datos electrónicos consecutivos e.data pasa a su controlador de ondataavailable . Para crear un archivo reproducible válido, debe concatenar todos esos fragmentos en el archivo. Si no puede hacer que funcione, haga otra pregunta.
El problema era que parece que solo el primer fragmento tenía una firma, una etiqueta o algo más, y por lo tanto podía reproducirse. Así que tuve que agregar un intervalo para detener y reproducir mediaRecorder cada vez.
Además, el formato del archivo no era ogg sino webm .
El código de trabajo completo:
<?php if(isset($_POST["data"])) { file_put_contents("r.webm", base64_decode($_POST["data"])); exit; } ?> <script> var mediaRecorder = null; var delay = 2000; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { console.log('getUserMedia supported.'); navigator.mediaDevices.getUserMedia ( { audio: true }) .then(function(stream) { mediaRecorder = new MediaRecorder(stream, {mimeType: 'audio/webm; codecs=opus'}); mediaRecorder.start(); mediaRecorder.ondataavailable = function(e) { var blob = e.data; var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { var data = reader.result.split(";base64,")[1]; requestp2("a.php", "data="+encodeURIComponent(data)); } } setInterval(function(){ mediaRecorder.stop(); mediaRecorder.start(); }, delay); }) .catch(function(err) { console.log('The following getUserMedia error occurred: ' + err); } ); } else { console.log('getUserMedia not supported on your browser!'); } function requestp2(path, data) { var http = new XMLHttpRequest(); http.open('POST', path, true); http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); http.send(data); } </script>