赵梦欢
赵梦欢
  • 发布:2016-08-17 13:37
  • 更新:2020-07-09 17:15
  • 阅读:57666

录音文件与Base64编码相互转换的方法

分类:HTML5+

前言

最近有几个朋友一直在问语音文件怎么转base64字符串进行发送上传,base64字符串又如何转成文件,论坛中已经有多篇问题的帖子有介绍,这里只是稍微整理,方便大家可以更加方便的使用,首先看效果:

录音文件转成base64字符串

hello mui 演示app中im-chat.html有演示案例,通过hold和release控制录音的长度,即长按按钮开始录音,释放就停止录音,上拉取消发送录音。

html部分

<button id="recorder" type="button" class="mui-btn mui-btn-blue mui-btn-block">录制语音文件转base64字符串</button>

js部分

mui.init中首先需要配置手势事件

mui.init({  
    gestureConfig: {  
        tap: true, //默认为true  
        doubletap: true, //默认为false  
        longtap: true, //默认为false  
        swipe: true, //默认为true  
        drag: true, //默认为true  
        hold: true, //默认为false,不监听  
        release: true //默认为false,不监听  
    }  
});

录音逻辑控制,按住按钮弹出录音提示框,并且对录音时长进行控制,录音时间太短取消操作,手指上划,取消发送。

var MIN_SOUND_TIME = 800;  
var recorder = null;  
var startTimestamp = null;  
var stopTimestamp = null;  
var stopTimer = null;  
var recordCancel = false;  

var soundAlert = document.getElementById("sound-alert");  
var audioTips = document.getElementById("audio-tips");  

// 控制录音弹出框是否播放  
var setSoundAlertVisable=function(show){  
    if(show){  
        soundAlert.style.display = 'block';  
        soundAlert.style.opacity = 1;  
    }else{  
        soundAlert.style.opacity = 0;  
        //  完成再真正隐藏  
        setTimeout(function(){  
            soundAlert.style.display = 'none';  
        },200);  
    }  
};  

mui.plusReady(function () {  
    /**  
     * 录制语音文件转base64字符串  
     */  
    // 按住录音(长按开始录音)  
    document.querySelector('#recorder').addEventListener('hold',function () {  
        recordCancel = false;  
    if(stopTimer)clearTimeout(stopTimer);  

    audioTips.innerHTML = "手指上划,取消发送";  
    soundAlert.classList.remove('rprogress-sigh');  
    setSoundAlertVisable(true);  

    // 获取当前设备的录音对象  
        recorder = plus.audio.getRecorder();  
        startTimestamp = (new Date()).getTime();  
        recorder.record({  
            filename:"_doc/audio/",  
            format:"amr" //iOS平台支持"wav"、"aac"、"amr"格式,默认为"wav"  
        }, function (path) {  
            if (recordCancel) return;  
            console.log("path:"+path);  
            Audio2dataURL(path);  
        }, function ( e ) {  
            mui.toast("录音出现异常: " + e.message );  
        });  
    })  

    // 释放保存(松手保存)  
    document.querySelector('#recorder').addEventListener('release',function () {  
        if (audioTips.classList.contains("cancel")) {  
            audioTips.classList.remove("cancel");  
            audioTips.innerHTML = "手指上划,取消发送";  
        }  
        // 判断录音时间  
        stopTimestamp = (new Date()).getTime();  
        if (stopTimestamp - startTimestamp < 800) {  
            audioTips.innerHTML = "录音时间太短";  
            soundAlert.classList.add('rprogress-sigh');  
            recordCancel = true;  
            stopTimer=setTimeout(function(){  
                setSoundAlertVisable(false);  
            },800);  
        }else{  
            setSoundAlertVisable(false);  
        }  
        recorder.stop();  
    })  

    // 拖动屏幕(手指上划,取消发送)  
    document.body.addEventListener('drag', function(event) {  
        if (Math.abs(event.detail.deltaY) > 50) {  
            if (!recordCancel) {  
                recordCancel = true;  
                if (!audioTips.classList.contains("cancel")) {  
                    audioTips.classList.add("cancel");  
                }  
                audioTips.innerHTML = "松开手指,取消发送";  
            }  
        } else {  
            if (recordCancel) {  
                recordCancel = false;  
                if (audioTips.classList.contains("cancel")) {  
                    audioTips.classList.remove("cancel");  
                }  
                audioTips.innerHTML = "手指上划,取消发送";  
            }  
        }  
      }, false);  
})

当录音成功后,我们可以将录音文件转成base64字符串,用于网络传输。

/**  
 * 录音语音文件转base64字符串  
 * @param {Object} path  
 */  
function Audio2dataURL (path) {  
    plus.io.resolveLocalFileSystemURL(path, function(entry){  
        entry.file(function(file){  
            var reader = new plus.io.FileReader();  
            reader.onloadend = function (e) {  
                console.log(e.target.result);  
            };  
            reader.readAsDataURL(file);  
        },function(e){  
            mui.toast("读写出现异常: " + e.message );  
        })  
    })  
}

至此我们完成了录音语音文件转base64字符串,反过来我们需要将base64字符串转成语音文件。

base64字符串转成语音文件

我们可以封装如下方法:

/**  
 * base64字符串转成语音文件(参考http://ask.dcloud.net.cn/question/16935)  
 * @param {Object} base64Str  
 * @param {Object} callback  
 */  
function dataURL2Audio (base64Str, callback) {  
    var base64Str = base64Str.replace('data:audio/amr;base64,','');  
    var audioName = (new Date()).valueOf() + '.amr';  

    plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){  
        fs.root.getFile(audioName,{create:true},function(entry){  
            // 获得平台绝对路径  
            var fullPath = entry.fullPath;  
            if(mui.os.android){    
                // 读取音频  
                var Base64 = plus.android.importClass("android.util.Base64");  
                var FileOutputStream = plus.android.importClass("java.io.FileOutputStream");  
                try{  
                    var out = new FileOutputStream(fullPath);  
                    var bytes = Base64.decode(base64Str, Base64.DEFAULT);  
                    out.write(bytes);   
                    out.close();  
                    // 回调  
                    callback && callback(entry);  
                }catch(e){  
                    console.log(e.message);  
                }  
            }else if(mui.os.ios){  
                var NSData = plus.ios.importClass('NSData');  
                var nsData = new NSData();  
                nsData = nsData.initWithBase64EncodedStringoptions(base64Str,0);  
                if (nsData) {  
                    nsData.plusCallMethod({writeToFile: fullPath,atomically:true});  
                    plus.ios.deleteObject(nsData);  
                }  
                // 回调  
                callback && callback(entry);  
            }  
        })  
    })  
}

调用方法如下:

html部分:

<button id="player" type="button" class="mui-btn mui-btn-blue mui-btn-block">base64字符串转成语音文件播放</button>

js部分:

/**  
 * base64字符串转成语音文件播放  
 */  
document.querySelector('#player').addEventListener('tap',function () {  
        // 语音文件Base64编码(由于编码过长影响阅读体验,请查看工程验证)  
     var base64Str = ' '   

        // 转成.amr文件播放  
    dataURL2Audio(base64Str, function(entry){  
        var toURL = entry.toURL();  
        // 播放音频  
        playAudio(toURL);  
    })  
})  

/**  
 * 播放音频  
 * @param {Object} path  
 */  
function playAudio (path) {  
    var player = plus.audio.createPlayer(path);  
    player.play(function(){  
        mui.toast("播放成功");  
    }, function(e) {  
        mui.toast("播放失败");  
    });   
}

写在后面

本文以语音文件为例说明5+中语音文件与Base64编码的相互转换,对于图片与Base64编码的转换方法请参考nativeObj Bitmap: 原生图片对象,可以通过loadBase64Data方法加载Base64编码格式图片到Bitmap对象,通过toBase64Data方法获取图片的Base64编码数据。对于一般性文件,建议使用h5 File API,详细可以参考我这篇文章:
JavaScript进阶学习(三)—— 基于html5 File API的文件操作

本文详细代码请查看附件工程。

16 关注 分享
lhyh mfan hanni 小手真黑 5***@qq.com sdsdsdsds huangijn 1***@qq.com 崔大人 3***@qq.com l***@163.com 1***@163.com Mike132 菜鸡 5***@qq.com 木头哥

要回复文章请先登录注册

ali

ali

回复 赵梦欢 :
把你的QQ号留一下 我给你发我写的js 代码
2016-12-07 13:12
赵梦欢

赵梦欢 (作者)

回复 ali :
需要转成语音文件播放。
2016-12-07 13:07
ali

ali

我把语音转换成base64之后保存到input[hidden] 里面 单击播放时候 获取input值 播放了 可没有成功 求助 楼主 谢谢
2016-12-07 10:35
赵梦欢

赵梦欢 (作者)

回复 sine2 :
这个函数是将语音base64编码转文件的,图片自然不行。
2016-10-24 13:36
sine2

sine2

dataURL2Audio 方法在安卓真机上出错,e.message 的值为undefined,iOS 模拟器上没问题!我只是拿一个小图片(base64)试了下,没有用音频~
2016-10-20 11:44
freedemon

freedemon

回复 t***@163.com :
成功的
2016-09-26 09:49
t***@163.com

t***@163.com

回复 freedemon :
你ios播放成功了?
2016-09-22 19:30
t***@163.com

t***@163.com

demo中ios机(6s) 生成文件 的大小为0。播放失败。
2016-09-22 19:27
freedemon

freedemon

回复 赵梦欢 :
函数我在放在一个监听器里,一监听就使用输入编码来输出文件目录,我发现会存在一定几率是函数失效,因为监听器我放着一个控制台输出有没有执行到那里。
2016-08-30 10:25
赵梦欢

赵梦欢 (作者)

回复 freedemon :
第一个问题,base64转文件的函数你是怎么使用的呢?应该不会存在失效的问题吧,另外转换的效率没有经过测试,可能会存在同时转换多个base64编码为文件失效的问题。
2016-08-29 21:00