写点什么

融云 Web 播放声音 — Flash 篇 (播放 AMR、WAV)

发布于: 2021 年 03 月 16 日

本文主要介绍 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 码 就说完了,主要是介绍下大概思路


以上是融云 SDK 里的源码,不过最近推出了直接使用 Audio 方式播放 AAC 格式的音频文件


原始文章连接:https://www.cnblogs.com/yuhongda0315/p/5224450.html


融云官网:https://www.rongcloud.cn


融云文档:https://docs.rongcloud.cn/v4


用户头像

还未添加个人签名 2021.01.26 加入

还未添加个人简介

评论

发布
暂无评论
融云 Web 播放声音 — Flash 篇 (播放 AMR、WAV)