H5音頻踩坑與填坑

最近用createjs完成了個H5需求,體驗二維碼以下。在音效接入方面踩了一點坑,但...慶幸的是,坑仍是能被填上的。html

clipboard.png

本文能爲你解決:web

  • 微信音頻自動播放問題
  • audio預加載問題(解決網絡環境差下,音頻因爲未緩衝完形成的音效動畫不一樣步問題

微信環境下音頻自動播放

問題

IOS設備系統是不容許視頻音頻自動播放的,須要用戶明確指定播放(經過必定的交互動做),相關的音頻或視頻才能被加載。api

解決(推薦使用方法一

方法一:使用weixin提供的sdk瀏覽器

// 引入sdk
<script src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

var audio = (function(){
  var _audio = new Audio();
  _audio.src = 'xxx';
  _audio.load();
  return _audio;
})()

// 微信配置信息(即便不正確也沒問題
wx.config({
  debug: false,
  appId: '',
  timestamp: 1,
  nonceStr: '',
  signature: '',
  jsApiList: []
});
// 在ready時觸發相關事件
wx.ready(function() {
  // 觸發一下play事件
  audio.play();
});

方法二:野生方法微信

var audio = (function(){
  var _audio = new Audio();
  _audio.src = 'xxx';
  _audio.load();
  return _audio;
})()

document.addEventListener("WeixinJSBridgeReady", function () {
  WeixinJSBridge.invoke('getNetworkType', {}, function (e) {
    // 觸發一下play事件
    audio.play();
  });
}, false);

說明

一、爲何推薦使用方法一?通過驗證,方法二的會在微信瀏覽器準備完成後立刻執行回調函數,假如咱們使用了第三方庫預加載音頻,在頁面監聽到WeixinJSBridgeReady事件時,音頻因爲未加載完成,因此是獲取不到的。網絡

二、只要咱們在WeixinJSBridgeReady OR ready時觸發了audio.play()事件,瀏覽器會識別到audio對象已被啓用,這樣咱們能夠在H5動畫的任意位置使用audio.play()audio.pause(),而不須要再監聽用戶動做以觸發音頻播放。app

音頻預加載

上文提到過,爲何須要音頻預加載,在動畫音效豐富的H5中,可能不止bgm一個音頻,同時,咱們還要根據場景的變換播放不一樣的音效。假如在咱們動畫播放過程當中,音頻尚未緩衝完畢,或者只緩衝了一部分,音頻是會不播放或者中止播放的。這樣,就會形成動效音效不一樣步的問題了。(在敘事性H5動畫中尤其重要dom

使用audio 標籤屬性 preload(不推薦

很簡單,直接在標籤裏使用preload,燃鵝該方法兼容性不太好,不一樣機型差別大,而且有些機型下會有preload與無preload表現一致,並不會對音頻緩衝帶來多大改善。函數

<audio src='xxx.mp3' loop=true preload='auto' />

preloadjs

推薦使用createjs裏的preloadjs,但還須要配合soundjs使用。oop

官方文檔給出的預加載緣由,和上文提到的大同小異。

Without CreateJS, most modern browsers do a great job of loading enough audio data to play back a sound continuously until the end using HTML tags. The canplaythrough event will fire when the buffer is full, and the sound will start. This is sufficient for a click-to-play sound, or for a background sound that can start whenever its ready - but in order to play on-demand audio for games, applications, and web sites, sounds must be preloaded first.

使用

一、preloadjs + soundjs

var queue = new createjs.LoadQueue();

// 添加聲音支持
queue.installPlugin(createjs.Sound)

queue.addEventListener("fileload", handleFileLoad);
queue.addEventListener("complete", handleComplete);
 
queue.loadFile({id:"bgm", src:"assets/bgm.mp3"});
// OR
queue.loadManifest([
  {id:"bgm", src:"assets/bgm.mp3"},
  {id:"myImage2", src:"assets/image2.jpg"}
]);

// 資源所有加載完成時觸發
var handleComplete = function () {
  // 在次調用weixinReady事件,讓瀏覽器得到音頻對象
  /*
     注意:音頻實例爲 var bgmInstance = createjs.Sound.play("bgm")
     而後能夠經過控制 bgmInstance.play() OR bgmInstance.stop() 播放暫停音效
  */
  ...
}

二、僅使用soundjs

// createjs.Sound.alternateExtensions = ["mp3"]; 控制音頻類型
createjs.Sound.registerSound({id:"bgm", src:"assets/bgm.mp3"});
createjs.Sound.play("bgm");

使用preloadjs會在預加載時調用createjs.Sound.registerSound事件註冊聲音,因此無需顯示調用。

*音頻實例類型選擇
preloadjs加載的默認音頻實例是AudioBuffer,也就是已解碼的音頻流,感興趣的同窗能夠看看api,本人對它不太瞭解,就不誤導你們了。

即:

console.log(createjs.Sound.play('bgm')) // 返回AudioBuffer實例

因此咱們不能經過audioapi來對它進行操做,soundjs爲咱們提供了控制它:AbstractSoundInstanceapi 。那麼咱們還能不能經過audio dom的方式控制呢?答案是能夠的,可是官方不推薦,而且本人在移動端也遇到獲取不到實例對象的問題,仍是稍微提一下:

// 註冊HTMLAudioPlugin,那麼將聲音註冊爲原生的audio dom
createjs.Sound.registerPlugins([createjs.HTMLAudioPlugin]);

// 預加載
var queue = new createjs.LoadQueue();

// 添加聲音支持
queue.installPlugin(createjs.Sound);

queue.addEventListener("fileload", handleFileLoad);
queue.addEventListener("complete", handleComplete);
 
queue.loadFile({id:"bgm", src:"assets/bgm.mp3"});

// 獲取
var handleComplete = function () {
  var bgmAudioDom = queue.getResult('bgm');
  // console.log(bgmAudioDom) 返回 <audio src='assets/bgm.mp3' loop></audio>
}

項目代碼截取

// 定義loader
var loader = new createjs.LoadQueue();

// 添加聲音支持
loader.installPlugin(createjs.Sound)

loader.addEventListener('progress', __handleLoading);
loader.addEventListener('complete', __handleComplete);
loader.loadManifest(manifest);

var manifest = [
{src:"plugin/bgm.mp3", id:"bgm"},
  {src:"plugin/s1_female1.mp3", id:"s1_female1"},
  {src:"plugin/s1_female2.mp3", id:"s1_female2"},
  {src:"plugin/s1_danmu.mp3", id:"s1_danmu"},
  {src:"plugin/s1_effect.mp3", id:"s1_effect"},
  {src:"plugin/s3_switch.mp3", id:"s3_switch"},
]

// 加載完成
var __handleComplete = function (evt) {
  wx.config({
    debug: false,
    appId: '',
    timestamp: 1,
    nonceStr: '',
    signature: '',
    jsApiList: []
  });

  wx.ready(function() {
    musicControlData['bgm'].instance = createjs.Sound.play('bgm');
    musicControlData['bgm'].instance.stop();
  });

}

該H5使用了preload預加載第一屏所需音效,分屏加載其餘音效的方式,因此是方法1和2結合使用的,這裏不展開敘述了,有興趣的同窗私下交流(拒絕伸手黨,禮貌微笑~
clipboard.png

【完】

相關文章
相關標籤/搜索