2015-09-12 36 views
6

Il server salva i dati audio come stringa di dati base64. Il client Web mobile recupera i dati e riproduce l'audio.Converti dati audio da stringa a file

Ma trovato un problema in Chrome mobile in iOS e Android che l'audio con dati uri non può riprodurre (issue).

Per farlo funzionare, mi chiedevo se c'è un modo nel lato client per convertire la stringa di dati in un file audio (come .m4a) e collegare l'audio src al file?

risposta

7

capito direttamente utilizzando l'API Web audio ha la migliore compatibilità tra la browser per dispositivi mobili in iOS e Android.

function base64ToArrayBuffer(base64) { 
    var binaryString = window.atob(base64); 
    var len = binaryString.length; 
    var bytes = new Uint8Array(len); 
    for (var i = 0; i < len; i++)  { 
    bytes[i] = binaryString.charCodeAt(i); 
    } 
    return bytes.buffer; 
} 

var base64 = '<data string retrieved from server>'; 
var audioContext = new (window.AudioContext || window.webkitAudioContext)(); 
var source = audioContext.createBufferSource(); 
audioContext.decodeAudioData(base64ToArrayBuffer(base64), function(buffer) { 
    source.buffer = buffer; 
    source.connect(audioContext.destination); 
    source.start(0); 
}); 

Funziona in iOS safari, Chrome e Android browser predefinito e Chrome.

5

C'è un modo per fare un po 'quello che vuoi, funziona su desktop, ma non posso garantire che funzioni sul cellulare. L'idea è di convertire dataURI in ArrayBuffer, costruire un Blob da esso e quindi creare un ObjectURL con esso, per passare all'elemento audio. Ecco il codice (ho provato in Chrome/Firefox sotto Linux e funziona):

<script> 
    var base64audio = "data:audio/ogg;base64,gibberish"; 

    function dataURItoBlob(dataURI) 
    { 
     // Split the input to get the mime-type and the data itself 
     dataURI = dataURI.split(','); 

     // First part contains data:audio/ogg;base64 from which we only need audio/ogg 
     var type = dataURI[ 0 ].split(':')[ 1 ].split(';')[ 0 ]; 

     // Second part is the data itself and we decode it 
     var byteString = atob(dataURI[ 1 ]); 
     var byteStringLen = byteString.length; 

     // Create ArrayBuffer with the byte string and set the length to it 
     var ab = new ArrayBuffer(byteStringLen); 

     // Create a typed array out of the array buffer representing each character from as a 8-bit unsigned integer 
     var intArray = new Uint8Array(ab); 
     for (var i = 0; i < byteStringLen; i++) 
     { 
      intArray[ i ] = byteString.charCodeAt(i); 
     } 

     return new Blob([ intArray ], {type: type}); 
    } 
    document.addEventListener('DOMContentLoaded', function() 
    { 
     // Construct an URL from the Blob. This URL will remain valid until user closes the tab or you revoke it 
     // Make sure at some point (when you don't need the audio anymore) to do URL.revokeObjectURL() with the constructed URL 
     var objectURL = URL.createObjectURL(dataURItoBlob(base64audio)); 

     // Pass the URL to the audio element and load it 
     var audio = document.getElementById('test'); 
     audio.src = objectURL; 
     audio.load(); 
    }); 
</script> 
... 
<audio id="test" controls /> 

Mi auguro che aiuta;)

+0

Thx, con voto positivo. Ha fatto funzionare il Chrome in iOS 8. Tuttavia, né il browser né il browser predefinito di Android 4.4.2 funzionano –