最近在做桌面端应用基于electron-vue,涉及音频播放,就简单研究一下。

一种是基于audio标签,另一种是基于AudioContext方法。

audio标签

两种实现,第一种是直接在HTML中使用标签
<audio src="../viper.mp3" controls="controls"></audio>
第二种是在js文件中使用

    let audio = new Audio()
    audio.src = "../viper.mp3"
    audio.play();

但在electron中是存在问题,因为electron是基于chrome内核,所以不能直接访问本地文件,还请哪位大神指导如何规避该问题。

AudioContext方法

其实该方法也存在访问本地的问题,所以借助node.js来获取文件。

let fs = require('fs');
let AudioContext = window.AudioContext ;
let audioCtx = AudioContext ? new AudioContext() : '';


fs.readFile(_this.voicePath,function(err, data){
      _this.audioPlay(data);
});

audioPlay:function (data) {
    let audioBufferSourceNode = audioCtx.createBufferSource();
    audioCtx.decodeAudioData(data.buffer).then(function (decodedData) {
        audioBufferSourceNode.buffer = decodedData;
    });
    audioBufferSourceNode.connect(audioCtx.destination);
    audioBufferSourceNode && audioBufferSourceNode.start(0,0,1);
}
这里面存在三个坑。
一是,fs.readFile返回的数据,如果不能直接解析,那么返回的是原生buffer,但audioBufferSourceNode.buffer需要的audioBuffer格式。
那么就需要从buffer转换到audioBuffer,网上暂时没有找到直接方法,现在的解决方法是Buffer转arrayBuffer再转audioBuffer。
fs.readFile(_this.voicePath,function(err, data){
      _this.audioPlay(data);
});
console.log(typeof data)  //返回类型为object,就是原生Buffer

let dataTmp = data.buffer  // arrayBuffer

audioCtx.decodeAudioData(dataTmp)  //这才是最后的audioBuffer
二是,audioBufferSourceNode只能播放音频一次,所以这就是为什么在audioPlay方法中需要重新new。而不是抽到公共部分。
audioPlay:function (data) {
    let audioBufferSourceNode = audioCtx.createBufferSource();
}
三是,存在部分音频解析失败的情况,不知道是类型转换导致,还是audioContext自身的BUG,如果哪位大神指导,还请多多指点
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐