美文网首页让前端飞超有趣的JSjavaScript学习
使用amr.js播放"amr"格式的录音文件

使用amr.js播放"amr"格式的录音文件

作者: Nanayai | 来源:发表于2019-07-08 08:35 被阅读3次
    image

    问题所在:做项目的时候,要求能在平台端播放app上传而来的录音文件,而安卓端目前只能录制"amr"、"3gp"格式,完美的避开了html支持的三种音频格式。

    我们选择了每分钟约100kb的“amr”格式来完成录制和上传功能,而在html5中:

    video 元素支持三种视频格式:

    格式 IE Firefox Opera Chrome Safari
    Ogg No 3.5+ 10.5+ 5.0+ No
    MPEG 4 9.0+ No No 5.0+ 3.0+
    WebM No 4.0+ 10.6+ 6.0+ No

    audio 元素支持三种音频格式:

    格式 IE 9 Firefox 3.5 Opera 10.5 Chrome 3.0 Safari 3.0
    Ogg Vorbis
    MP3
    Wav

    解决办法:我在github上找到了这个库 opencore-amr-js ,这个库使用amr.js对“amr”文件进行转码:AMR.decode(amr) ,再使用AudioContext 对象进行播放即可。各位可去github上看具体实现和作者的demo,下面是我整理的得小demo,实现了播放功能和兼容性处理,除了不支持AudioContext 的IE之外,其他桌面端浏览器基本都可以正常运行,移动端兼容性上我没有测试,据说ios端行不通,安卓端可以:

    <!DOCTYPE html>
    <html>
        <head>
            <title>AMR decode/encode tests</title>
            <meta charset="utf-8">
            <script src="amrnb.js" defer></script>
        </head>
    
        <body>
            <button id="but">Play</button>
            <script>
                but.onclick = function() {
                    var xhr = new XMLHttpRequest();
                    xhr.open('GET', "test.amr");
                    xhr.responseType = 'blob';
                    xhr.onload = function() {
                        readBlob(this.response, function(data) {
                            playAmrArray(data);
                        });
                    };
                    xhr.onerror = function() {
                        alert('Failed to fetch ' + url);
                    };
                    xhr.send();
                }
    
                window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
    
                function readBlob(blob, callback) {
                    var reader = new FileReader();
                    reader.onload = function(e) {
                        var data = new Uint8Array(e.target.result);
                        callback(data);
                    };
                    reader.readAsArrayBuffer(blob);
                }
    
                function playAmrArray(array) {
                    var samples = AMR.decode(array);
                    if(!samples) {
                        alert('Failed to decode!');
                        return;
                    }
                    playPcm(samples);
                }
    
                function playPcm(samples) {
                    try {
                        var ctx = new AudioContext();
                    } catch(e) {
                        alert('您的浏览器暂不支持播放录音');
                        return;
                    }
                    var src = ctx.createBufferSource();
                    var buffer = ctx.createBuffer(1, samples.length, 8000);
                    if(buffer.copyToChannel) {
                        buffer.copyToChannel(samples, 0, 0);
                    } else {
                        var channelBuffer = buffer.getChannelData(0);
                        channelBuffer.set(samples);
                    }
                    src.buffer = buffer;
                    src.connect(ctx.destination);
                    src.start();
                }
            </script>
        </body>
    </html>
    

    AudioContext相关以及兼容性请参考: AudioContext

    更新:以上只是实现了简单的播放,如果想添加其他功能的话,可以使用wavesurfer-js 来实现炫酷的效果:

    部分代码(ps:我们测试的效果蛮丑的,希望你可以弄得比上面这个还要漂亮):

    var wavesurfer = Object.create(WaveSurfer);
    
    // Init & load audio file
    document.addEventListener("DOMContentLoaded", function() {
        var options = {
            container: document.querySelector("#waveform"),
            waveColor: "violet",
            progressColor: "purple",
            loaderColor: "purple",
            cursorColor: "navy"
        };
    
        if (location.search.match("scroll")) {
            options.minPxPerSec = 100;
            options.scrollParent = true;
        }
    
        // Init
        wavesurfer.init(options);
        // Load audio from URL
        //wavesurfer.load("example/media/demo.wav");
    
        // Regions
        // if (wavesurfer.enableDragSelection) {
        //     wavesurfer.enableDragSelection({
        //         color: "rgba(0, 255, 0, 0.1)"
        //     });
        // }
    });
    
    // Play at once when ready
    // Won't work on iOS until you touch the page
    wavesurfer.on("ready", function() {
        wavesurfer.play();
    });
    
    // Report errors
    wavesurfer.on("error", function(err) {
        console.error(err);
    });
    
    // Do something when the clip is over
    wavesurfer.on("finish", function() {
        console.log("播放完成");
    });
    
    function readBlob(blob, callback) {
        var reader = new FileReader();
        reader.onload = function(e) {
            var data = new Uint8Array(e.target.result);
            callback(data);
        };
        reader.readAsArrayBuffer(blob);
    }
    
    function playAmrArray(array) {
        var samples = AMR.decode(array);
        if (!samples) {
            alert("解码失败!");
            return;
        }
    
        wavesurfer.loadAMRDecodedBuffer(samples);
    }
    
    function playAmrContent(url) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.responseType = "blob";
        xhr.onload = function() {
            readBlob(this.response, function(data) {
                playAmrArray(data);
            });
        };
        xhr.onerror = function() {
            alert("加载资源失败");
        };
        xhr.send();
    }
    /* Progress bar */
    document.addEventListener("DOMContentLoaded", function() {
        var progressDiv = document.querySelector("#progress-bar");
        var progressBar = progressDiv.querySelector(".progress-bar");
    
        var showProgress = function(percent) {
            progressDiv.style.display = "block";
            progressBar.style.width = percent + "%";
        };
    
        var hideProgress = function() {
            progressDiv.style.display = "none";
        };
    
        wavesurfer.on("loading", showProgress);
        wavesurfer.on("ready", hideProgress);
        wavesurfer.on("destroy", hideProgress);
        wavesurfer.on("error", hideProgress);
        var fileId = getQueryStringByName("file");
        playAmrContent("/file/download?param=" + JSON.stringify({ id: fileId }));
    });
    

    相关文章

      网友评论

        本文标题:使用amr.js播放"amr"格式的录音文件

        本文链接:https://www.haomeiwen.com/subject/zyqbhctx.html