Gravação de áudio no Chrome para Android usando a API de áudio da web e navigator.getUserMedia

As versões 30 e 31 beta do Android para Android no Android 4.1 não parecem gravar corretamente o áudio usando áudio da web HTML5 e navigator.webkitGetUserMedia. (O Chrome 30+ no Android deve suportar essas APIs.)

O sintoma é que o código parece funcionar corretamente, incluindo a exibição do prompt para permitir ou não o acesso ao microfone, mas os dados gravados não contêm nada além de zeros.

Eu criei um testcase simplificado (vá parahttp://jsfiddle.net/JCFtK/e clique no botão Gravar e escolha a opção apropriada para permitir que ele acesse seu microfone). A parte chave do código está abaixo (a função 'registro' é o ponto de entrada).

function processAudioBuffer(e) {
    var floats = e.inputBuffer.getChannelData(0);
    var min = 0, max = 0;
    for (var i = 0; i < floats.length; i++) {
        var current = floats[i];
        min = Math.min(current, min);
        max = Math.max(current, max);
    }
    log('Block min/max: ' + min.toFixed(3) + ', ' + max.toFixed(3));
}

function record() {
    if (!window.AudioContext) {
        window.AudioContext = window.webkitAudioContext;
    }
    if (!navigator.getUserMedia) {
        navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
    }
    data.context = new AudioContext();
    navigator.getUserMedia({audio: true}, function(stream) {
        data.mediaStream = stream;
        startAudio();
    }, function(error) {
        log('Stream get error: ' + error);
    });
}

function startAudio() {
    // Get input media stream.
    data.audioStream = data.context.createMediaStreamSource(data.mediaStream);

    // Set up JS processor.
    data.processor = data.context.createScriptProcessor(2048, 1, 1);
    data.processor.onaudioprocess = processAudioBuffer;

    // You need to connect the output of processor to the audio output or it
    // doesn't work. (In Firefox, connecting it just to a gain node works;
    // in Chrome you have to connect to output like this.)
    data.processor.connect(data.context.destination);

    // Connect input stream to processor, then we're done.
    data.audioStream.connect(data.processor);
    log('Stream connected OK');
}

O teste mostra o valor mínimo / máximo de áudio de cada bloco gravado. Quando estiver funcionando - como no Chrome de desktop, por exemplo - você verá que os valores mínimo / máximo variam dependendo do ruído de fundo. Quando não está funcionando, esses valores são sempre 0,000.

Este teste funciona no seguinte:

Chrome 30 (Windows)Firefox 25 (Windows)Firefox 25 (Android 4.1) em um Sony Xperia MFirefox 25 (Android 4.1) em um tablet Samsung

Este caso de teste não funciona no seguinte:

Chrome 30 (Android 4.1) em um Sony Xperia MChrome beta 31 (Android 4.1) em um Sony Xperia MChrome 30 (Android 4.1) em um tablet Samsung

O testcase também não funciona em outros navegadores, como o Safari ou o IE, mas isso é esperado, pois eles não suportam as APIs necessárias. É apenas o Chrome para Android que eu esperava fazer isso funcionar, mas isso não acontece.

Arquivei isso como um problema usando o processo de geração de relatórios de problemas do Chrome (que é particular e possivelmente um buraco negro), mas também gostaria de perguntar aqui: alguém está ciente de soluções alternativas que consertariam esse código para que eu pudesse realmente fazer isso? trabalhar no Chrome para Android?

(Um requisito para meus propósitos é que o áudio gravado deve ir para um manipulador de eventos JavaScript, como o que está aqui, e, por exemplo, não diretamente para o servidor como parte de um upload de formulário, o que possivelmente já pode funcionar.)

Tenho a impressão de que este é um material de ponta e que poucas pessoas estão tentando usá-lo, mas achei que valeria a pena perguntar. :)

questionAnswers(1)

yourAnswerToTheQuestion