前段时间做了个功能(有2、3个月了,突然想起来了,就记录一下),语言播放。一开始觉得很简单~~~
计划应用的是H5的audio标签,但因为这个标签不支持amr格式的语言,但是手机端传到后台的录音却都是amr格式的,无奈,只好先进行了转码工作。
amr格式语言转mp3格式,在windows服务器上均已通过,百度有很多博客。挺简单。
但是,最怕的但是,服务器是Linux环境,之前的一切工作全部白瞎了。之后就是各种Linux环境下的尝试了,然并卵,苦逼了一个一个礼拜,按照网上方法一个个尝试,结果过程和人家一样,但是就是无法实现转码功能。
最后,上天无路,入地无门,换种思路,直接开始学习AudioContext文档,结合网上资料,开始学习利用AudioContext直接播放amr语言文件。
AudioContext 学习:https://developer.mozilla.org/zh-CN/docs/Web/API/AudioContext
直接贴代码
HTML部分(href存amr文件访问路径)
<a class="amrnb" href="'+obj.fileDownloadUrl+'" download=""></a>
业务代码部分(initAudio方法需要在语言加载完毕后初始化)
/*语音播放控制js代码*/ function initAudio(){ setTimeout(function(){ //var audio = $("audio"); var audio = $(".amrnb"); var audioIngI=9999;//正在播放的语音的角标 for(var i = 0; i < audio.length; i++){ var dshiqi; var second = 2; /*var second = audio[i].duration;//获取音频秒数 if(second <= 60){ $(".yuyin-time").eq(i).text(parseInt(second) + "s"); }else if(second > 60){ var m = parseInt(second / 60); var s = parseInt(second % 60); $(".yuyin-time").eq(i).text(m + ":" + s + "s"); }*/ (function(i,audioIngI){ $($(".yuyin")[i]).live("click", function () { $(".yuyin-play").removeClass("yuyin-playing");//播放完毕去除动画 var ctx = getAudioContext(); var state = ctx.state; //alert(audioIngI==i); /*if(audioIngI==i){ ctx.close(); if(state == "running"){ ctx.suspend(); } if(state == "suspended"){ ctx.resume(); } return; }*/ if(state == "running"){ ctx.close(); if(audioIngI==i){ gAudioContext = new AudioContext(); audioIngI=9999; clearTimeout(dshiqi); return; } gAudioContext = new AudioContext(); } fetchBlob($(this).find("a.amrnb")[0].href, function(blob) { audioIngI = i; playAmrBlob(blob); //$(this).find(".yuyin-play").attr("class","yuyin-playing"); //$(this).find(".yuyin-play").addClass("yuyin-playing"); }); $(this).find(".yuyin-play").addClass("yuyin-playing"); var time = $(this).find("span").text(); dshiqi = setTimeout(function(){ $(".yuyin-play").removeClass("yuyin-playing");//播放完毕去除动画 audioIngI=9999; },time.substr(0,time.length-1) * 1000); //console.log($(this).find("a.amrnb")[i]); /*for(var j = 0; j < $("audio").length; j++){ if(j != i){ audio[j].pause();// 这个就是暂停 audio[j].currentTime = 0; $($(".yuyin-play")[j]).removeClass("yuyin-playing"); } } if(audio[i]!==null){ //检测播放是否已暂停.audio.paused 在播放器播放时返回false. if(audio[i].paused){ audio[i].play();//audio.play();// 这个就是播放 $(this).find(".yuyin-play").addClass("yuyin-playing"); clearTimeout(dshiqi); }else{ audio[i].pause();// 这个就是暂停 audio[i].currentTime = 0; $(this).find(".yuyin-play").removeClass("yuyin-playing"); clearTimeout(dshiqi); } } dshiqi = setTimeout(function(){ $(".yuyin-play").removeClass("yuyin-playing");//播放完毕去除动画 },audio[i].duration * 1000);*/ }); })(i); } },10); }
AudioContext代码支持
/*************************************JS控制语音播放*****************************************/ /*function E(selector) { return document.querySelector(selector); } $('#sample-amr > button').onclick = function() { fetchBlob(E('#sample-amr > a').href, function(blob) { playAmrBlob(blob); }); };*/ var gAudioContext = new AudioContext(); function getAudioContext() { if(!gAudioContext) { gAudioContext = new AudioContext(); } return gAudioContext; } function fetchBlob(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'blob'; xhr.onload = function() { callback(this.response); }; xhr.onerror = function() { alert('Failed to fetch ' + url); }; xhr.send(); } 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 fetchAndReadBlob(url, callback) { fetchBlob(url, function(blob) { readBlob(blob, callback); }); } function playAmrBlob(blob, callback) { readBlob(blob, function(data) { playAmrArray(data); }); } function playAmrArray(array) { var samples = AMR.decode(array); if(!samples) { alert('Failed to decode!'); return; } playPcm(samples); } function playPcm(samples) { var ctx = getAudioContext(); 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(); }
点击a标签就可以了~~
学然后知不足,教然后知困。知不足,然后能自反也;知困,然后能自强也。