将音频数据uri字符串转换为文件

7
服务器将音频数据保存为base64数据字符串。移动Web客户端获取数据并播放音频。
但是,在iOS和Android的移动Chrome中发现了一个问题,即无法播放使用data uri的音频(问题)。
为了使其正常工作,我想知道在客户端是否有一种方法可以将数据字符串转换为音频文件(如.m4a),并将音频src链接到该文件?
2个回答

11

通过直接使用Web音频API来解决问题,在iOS和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);
});

它在iOS Safari、Chrome和Android默认浏览器及Chrome中运行。


6

有一种方法可以实现您想要的功能,它适用于桌面端,但我不能保证在移动设备上也能正常工作。思路是将dataURI转换为ArrayBuffer,从中构造一个Blob,并使用它创建ObjectURL,以传递给音频元素。以下是代码(我在Linux下测试了Chrome/Firefox,可以正常工作):

<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 />

我希望这可以帮助到您;)

谢谢,已点赞。它使得iOS8上的Chrome可以正常工作。然而,在Android 4.4.2上,无论是Chrome还是默认浏览器都不能正常工作。 - Yujun Wu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接