h5页面播放wav音频的问题,兼容IOS与Android
前一阵公司有这个需求,要在html5上播放Android设备端传过来的wav音频格式问题,在度娘上一搜音频部分插件,什么就player插件等等,下过来试了之后发现不支持,再往深处看,大部分帖子说MP3的兼容性最好,建议转成MP3什么的,但是目前转MP3什么的貌似要通过Java还有Php什么的,我这边只有我一个苦逼的程序猿,so,此方案被毙了。
条条大路通罗马,此处不通,那就换个转法,终于在某个帖子上看到说可以将amr文件转成Base64格式的文件就可以播放,于是我用Node.js在后台转了,结果发现果真能播放出来了,我这个兴奋啊,代码如下
var promiseGetFile=httpService.promiseGetFile;
promiseGetFile(req,params.url,function (data) {
if(/audio/.test(params.mine)){
//音频文件处理
var data64 = new Buffer(data).toString('base64');
let base64 = 'data:' + params.mine + ';base64,' + data64;
response.send(base64);
else{
//其他未命名的文件处理,为了填后台存文件不存格式的坑
response.header('Content-Type', params.mine);
/*res.setHeader('Content-Type','text/javascript;charset=UTF-8');*/
/*attachment --- 作为附件下载
inline --- 在线打开
response.header('Content-Disposition', 'attachment;'+encodeFileName(req,params.filename));
response.write(data);
response.end();
}
事实证明我还是太年轻,这种方法只支持在Android播放,不支持IOS下播放,一查原因发现是苹果跟Google掐架引起的,早期版本是支持的,哎,又得重新来。
抱怨归抱怨,活还是要干的,我在百度搜索一通,找到了 Opencore-amr-js 神器,这个js可以将amr转成wav文件进行播放,wav文件在IOS跟Android都是支持的
var getAudioContext=function() {
if (!gAudioContext) {
gAudioContext = new AudioContext();
return gAudioContext;
var readBlob=function(blob, callback) {
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
callback(data);
reader.readAsArrayBuffer(blob);
var fetchBlob=function(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();
var fetchAndReadBlob=function(url, callback) {
fetchBlob(url, function(blob) {
readBlob(blob, callback);
var playAmrBlob=function(blob, callback) {
readBlob(blob, function(data) {
playAmrArray(data);
var convertAudioBlobToAmr=function(blob) {
readBlob(blob, function(data) {
var ctx = getAudioContext();
ctx.decodeAudioData(data.buffer, function(audioBuffer) {
var pcm;
if (audioBuffer.copyFromChannel) {
pcm = new Float32Array(audioBuffer.length);
audioBuffer.copyFromChannel(pcm, 0, 0);
} else {
pcm = audioBuffer.getChannelData(0);
var amr = AMR.encode(pcm, audioBuffer.sampleRate, 7);
playAmrArray(amr);
var playAmrArray=function(array) {
var samples = AMR.decode(array);
if (!samples) {
alert('Failed to decode!');
return;
var src=playPcm(samples);
var playPcm=function(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();
return src;
//angular 调用
//此方法是自己写的,确保一个时间段只能播放一个音频
var E = function () {
window.MMplayingMsg && (window.MMplayingMsg.MMPlaying = !1, window.MMplayingMsg = null);
//有播放消息,播放完毕之后的处理
//点击语音,调用该方法进行播放
$scope.playVoice = function (target) {
if (window.MMplayingMsg) {
//针对同一条消息记录
if (target.stamp == window.MMplayingMsg.stamp&& target.MMPlaying&&target.senderId==window.MMplayingMsg.senderId){
target.MMPlaying=!1;
//return void amrObject.amrVoice.stop();
var player;
var n='/getFile?mime=amr/*&url='+target.content.url+'&filename='+target.content.text;
target.MMVoiceUnRead&&(target.MMVoiceUnRead = !1),target.MMPlaying = !0,
fetchBlob(n, function(blob) {
window.MMplayingMsg = target;
convertAmrBlobToWav(blob,event.target,target.VoiceLength,function () {
console.log("ender",target.VoiceLength);
target.MMPlaying=!1;
$scope.$apply();
我的页面长这样
哎呀,终于能播放了,IOS一测试,还是没声音。。。。。。。。。。
不能放弃啊,于是又找原因,(⊙o⊙)…原来是IOS的音频必须通过touch事件才能出发,而我那个playVoice是在click事件触发的,难怪播放不了。
又来码一拨代码
第一步,在html文件中添加
<audio id="voiceMsgPlayer" class="voicePlayer"></audio>
第二步,在js里面添加
var playMusic=function () {
document.getElementById("audio").play();
document.addEventListener('touchstart',playMusic, false);
function audioAutoPlay(id,thus){
document.removeEventListener('touchstart',playMusic, false);
var audio = document.getElementById(id),
play = function(){
audio.play();
thus.removeEventListener("touchstart",play, false);
audio.play();
thus.addEventListener("WeixinJSBridgeReady", function () {//微信
play();
}, false);
thus.addEventListener('YixinJSBridgeReady', function() {//易信
play();
}, false);
thus.addEventListener("touchstart",play, false);
}
第三步,更改调用方式
//将元素目标传过来
var convertAmrBlobToWav=function(blob,thus,duration,fn) {
readBlob(blob, function(data) {
var buffer = AMR.toWAV(data);
var url = URL.createObjectURL(new Blob([buffer], { type: 'audio/x-wav' }));
// Play wav buffer
var audio=document.getElementById("audio");
audio.src=url;
audioAutoPlay("audio",thus);
audio.onloadedmetadata = audio.onerror = function() {
URL.revokeObjectURL(url);
audio.onended=function(){
console.log("执行了");
fn();
/* audio.onend=function () {