Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

225
Visualizações
Live-recorded base64-encoded audio from MediaRecorder is broken

I wrote a simple page on js and php to live record audio from microphone. Logic is simple:

JS

  1. Get chunk of data from mic;
  2. Base64 encode it and urlencode it;
  3. Send it via POST request;

PHP

  1. Base64 decode data;
  2. (re)Write to .ogg file;
  3. Repeat 1 after delay.

The data is successfully written to file, but when I try to play it, player says that file is broken.

The blob solution from Mozilla guide is worked for me, I want exactly PHP solution with saving (rewriting) to file.

The full code below, what am I doing wrong?

<?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>
about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

You're trying to choose your audio format and codec by specifying a media type in your Blob constructor. You Can't Do That™.

Specify the media type in your MediaRecorder constructor instead. Something like this, not debugged!

        ...
        /* 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 })
            ...

There may also be some trouble with your handling of the consecutive e.data chunks MediaRecorder passes to your ondataavailable handler. To make a valid playable file you must concatenate all those chunks into the file. If you can't get it to work ask another question.

about 4 years ago · Juan Pablo Isaza Relatório

0

The problem was that seems only first chunk had like signature a label or something else, and hence could be played. So I had to add an interval to stop and play mediaRecorder every time.

Also the format of the file was not ogg but webm.

The full working code:

<?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>
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda