本文主要介紹 Flash 播放 AMR 格式 Base64碼 音頻。 在此之前麽有接觸過 Flash ,接觸 AS3 是一頭霧水,不過幸好有 TypeScript 和 JavaScript 的基礎看起來不是很費勁,現學現賣的就是開了 ”跳坑“ 之旅~~~ 1、實現思路 起初一點實現思路都木有,不知道
本文主要介紹 Flash 播放 AMR 格式 Base64碼 音頻。
在此之前麽有接觸過 Flash ,接觸 AS3 是一頭霧水,不過幸好有 TypeScript 和 JavaScript 的基礎看起來不是很費勁,現學現賣的就是開了 ”跳坑“ 之旅~~~
1、實現思路
起初一點實現思路都木有,不知道該從何做起,只知道用 Flash 播放 AMR ,度娘谷姐的一頓找,結果可想而知,沒有糟糕,只有十分糟糕,哈哈。
後來想了想,凡事都得有個思路,不能悶頭乾,瞬間恍然大悟,為自己浪費的快一天的時間,感到羞愧和害怕.....
① Flash 都能播放哪些音頻。
② 在 ActionScript 中AMR 是如何轉換成 Flash 可播放的音頻的。
③ JS 中如何調用 ActionScript 中方法,如何交互。
④ 如何把 SWF 文件嵌入到 HTML 頁面中。
⑤ 如何把 AMR(Audio) 和 Flash 播放AMR 兩種方式封裝起來。
2、逐一破解
① Flash 都能播放哪些音頻:
MP3 格式是 Flash 預設支持的音頻格式,WAVE 格式需要轉換可以播放,其他格式也是需要轉換的,因為先做的 Chrome 下播放聲音,對 WAVE 音頻多少有些瞭解,所 以決定從 WAVE 音頻入手,所以按照上述的套路來 ”屢思路“:
(1) 不管如何轉換,肯定要操作位元組數組,所以第一步把 AMR 格式的 base64 碼 轉換為 ByteArray 數組。
(2) 如何把 AMR 的 ByteArray 轉換成 WAVE 格式的 ByteArray 數組,毫無疑問 ,肯定需要解碼的過程。
按照這兩個小步驟逐一做,很快找到了 base64 的轉碼過程(開始是自己用 AS 實現了 JS 中的的 轉碼過程,可用但不完美,最終借鑒 github 上大牛的轉換過程),
但 AMR 轉換 WAVE 這個就沒有那麼容易了,最終確定,AS 解 AMR 比較費勁,需要 用 C 語言來解碼,然後用 CrossBirdge 生成可以供 Flash 調用的 SWC 文件。
ok,到這為止,第一步就完美解決了。
② 在 ActionScript 中AMR 是如何轉換成 Flash 可播放的音頻的:
上文中有提到,需要用 C 語言 進行對 AMR 解碼,下文中會給出 C 語言解碼和生成 SWC 的教程(借鑒大牛的)。
③ JS 中如何調用 ActionScript 中方法,如何交互,下文中會貼出完整代碼(一定要看註釋、註釋、註釋),此處寫出 JS 調用過程。
JS代碼:
function callFlashMethod() { // play 是 flash 代碼中定義的 ExternalInterface.addCallback("play",this.play); 下文中會有詳細介紹。 thisMovie("嵌入頁面上<object>的ID").play("base64str"); } function thisMovie(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName] } else { return document[movieName] } } document.getElementById("playId").onclick = function(){ callFlashMethod(); };
④ 如何把 SWF 文件嵌入到 HTML 頁面中:
使用 swfobject.js 可以將 swf 文件嵌入到 HTML 頁面中,參考資料 :http://www.cnblogs.com/Carpe-Diem/articles/2310831.html
⑤ 如何把 AMR(Audio) 和 Flash 播放AMR 兩種方式封裝起來:
有了上面的鋪墊,輕而易舉的就可以封裝啦(主要看 isIE 為 true 的情況):
var RongIMLib; (function (RongIMLib) { var RongIMVoice = (function () { function RongIMVoice() { } /** * 初始化聲音庫 */ RongIMVoice.init = function () { if (this.isIE) { var div = document.createElement("div"); div.setAttribute("id", "flashContent"); document.body.appendChild(div); var script = document.createElement("script"); script.src = "http://cdn.ronghub.com/swfobject-2.0.0.min.js"; var header = document.getElementsByTagName("head")[0]; header.appendChild(script); setTimeout(function () { var swfVersionStr = "11.4.0"; var flashvars = {}; var params = {}; params.quality = "high"; params.bgcolor = "#ffffff"; params.allowScriptAccess = "always"; params.allowfullscreen = "true"; var attributes = {}; attributes.id = "player"; attributes.name = "player"; attributes.align = "middle"; swfobject.embedSWF("http://cdn.ronghub.com/player-2.0.2.swf", "flashContent", "1", "1", swfVersionStr, null, flashvars, params, attributes); }, 200); } else { var list = ["http://cdn.ronghub.com/pcmdata-2.0.0.min.js", "http://cdn.ronghub.com/libamr-2.0.1.min.js"]; for (var i = 0, len = list.length; i < len; i++) { var script = document.createElement("script"); script.src = list[i]; document.head.appendChild(script); } } this.isInit = true; }; /** * 開始播放聲音 * @param data {string} amr 格式的 base64 碼 * @param duration {number} 播放大概時長 用 data.length / 1024 */ RongIMVoice.play = function (data, duration) { this.checkInit("play"); var me = this; if (me.isIE) { me.thisMovie().doAction("init", data); } else { me.palyVoice(data); me.onCompleted(duration); } }; /** * 停止播放聲音 */ RongIMVoice.stop = function () { this.checkInit("stop"); var me = this; if (me.isIE) { me.thisMovie().doAction("stop"); } else { if (me.element) { me.element.stop(); } } }; /** * 播放聲音時調用的方法 */ RongIMVoice.onprogress = function () { this.checkInit("onprogress"); }; RongIMVoice.checkInit = function (postion) { if (!this.isInit) { throw new Error("RongIMVoice not initialized,postion:" + postion); } }; RongIMVoice.thisMovie = function () { return eval("window['player']"); }; RongIMVoice.onCompleted = function (duration) { var me = this; var count = 0; var timer = setInterval(function () { count++; me.onprogress(); if (count >= duration) { clearInterval(timer); } }, 1000); if (me.isIE) { me.thisMovie().doAction("play"); } }; RongIMVoice.base64ToBlob = function (base64Data, type) { var mimeType; if (type) { mimeType = { type: type }; } base64Data = base64Data.replace(/^(.*)[,]/, ''); var sliceSize = 1024; var byteCharacters = atob(base64Data); var bytesLength = byteCharacters.length; var slicesCount = Math.ceil(bytesLength / sliceSize); var byteArrays = new Array(slicesCount); for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) { var begin = sliceIndex * sliceSize; var end = Math.min(begin + sliceSize, bytesLength); var bytes = new Array(end - begin); for (var offset = begin, i = 0; offset < end; ++i, ++offset) { bytes[i] = byteCharacters[offset].charCodeAt(0); } byteArrays[sliceIndex] = new Uint8Array(bytes); } return new Blob(byteArrays, mimeType); }; RongIMVoice.palyVoice = function (base64Data) { var reader = new FileReader(), blob = this.base64ToBlob(base64Data, "audio/amr"), me = this; reader.onload = function () { var samples = new AMR({ benchmark: true }).decode(reader.result); me.element = AMR.util.play(samples); }; reader.readAsBinaryString(blob); }; RongIMVoice.isIE = /Trident/.test(navigator.userAgent); RongIMVoice.isInit = false; return RongIMVoice; })(); RongIMLib.RongIMVoice = RongIMVoice; //相容AMD CMD if ("function" === typeof require && "object" === typeof module && module && module.id && "object" === typeof exports && exports) { module.exports = RongIMVoice; } else if ("function" === typeof define && define.amd) { define("RongIMVoice", [], function () { return RongIMVoice; }); } })(RongIMLib || (RongIMLib = {}));
截止到這裡,Flash 播放 AMR 格式 base64 碼 就說完了,主要是說說思路,覺得demo地址,可以再“Web 播放聲音 — 介紹篇”下載。