录音很简单,没有用apicloud自带的录音,它只能录制amr格式,所以用了一个叫“recMp3”的模块,它可以录mp3格式,代码如下:
//录音
var recMp3 = api.require('recMp3');
recMp3.start(function(ret, err) {
if (ret) {
if(ret.db!=undefined){
}
} else {
func.msg(err.message);
}
});
//停止录音
var that = this;
var recMp3 = api.require('recMp3');
recMp3.stop(function(ret,err) {
if(ret){
var duration = ret.duration;
//得到fs://格式的录音地址
var path = ret.path;
}
});
将mp3格式音乐转成base64也简单:
let fileReader = new FileReader();
fileReader.readAsDataURL(mp3文件)
fileReader.onload = function (e){
//得到mp3文件的base64
var base64Data = e.target.result;
};
最关键的来了,这个mp3文件如何得到,recMp3录音成功后,只返回了一个fs://格式的地址,而fileReader.readAsDataURL传地址是不行的。首先就想到了<input type="file" />的方法获取,但是这种方法不行,因为它必须要用户点击,然后弹窗,然后选择文件才可以。而浏览器也出于安全,是不会让开发者在避开用户的情况下,轻易得到本地文件。那只能另辟蹊径。于是想到了ajax,ajax可以用来下载文件,并且返回此文件的blob格式,只要在responseType设置为blob就行了,于是,我爱模板网写了下面的代码:
//通过原生ajax获取网络音乐,并转为base64
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://5.jimth.com/view/demomusic/niliuchenghe.mp3');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
let fileReader = new FileReader();
fileReader.readAsDataURL(xhr.response)
fileReader.onload = function (e){
//下面的代码成功得到了mp3格式文件的base64格式
console.log(e.target.result);
};
};
上面代码成功了!因为是apicloud项目,不用考虑跨域问题。现在的问题就变成了,请求fs或者widget格式的路径行不行。结果打脸了,这个ajax是js原生的,肯定不识别fs或者widget,因为那是app的路径。而apicloud提供的ajax又不支持返回blob。于是又换成相对路径试下,因为js原生应该是别相对路径,发现成功了:
//通过相对地址获取本地文件,并转为base64
var xhr = new XMLHttpRequest();
xhr.open('GET', '../../js/api.js');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
let fileReader = new FileReader();
fileReader.readAsDataURL(xhr.response)
fileReader.onload = function (e){
//下面的代码成功得到了api.js的base64格式
console.log(e.target.result);
};
};
现在的问题就是如何将录音的fs协议的地址转换成相对地址了,可以先将fs地址的文件用fs模块,剪切到项目根目录,然后就可以用相对路径了,代码如下:
var pathArr = path.split("/"); //这里的path是录音得到的fs协议的路径
var mp3Name = pathArr[pathArr.length-1];
var fs = api.require('fs');
fs.moveTo({
oldPath : path, //这里的path是录音得到的fs协议的路径
newPath : 'widget://mp3/'
}, function(ret, err) {
that.mp3Src = '../../mp3/'+mp3Name; //将mp3移动到widget以便于得到相对路径
});
通过上面的方法得到的mp3Src就是这个录音文件相对于当前文件的相对地址了(当前文件在widget://html/street,而移动后的mp3录音文件在widget://mp3/目录),再此使用上面的方法,就成功得到了!!耗费了一个多小时的时间终于解决了!下面是包含录音、转换base64等的完整代码:
//开始录音
startRecord(){
var recMp3 = api.require('recMp3');
recMp3.start(function(ret, err) {
if (ret) {
console.log('录音开始');
} else {
func.msg(err.message);
}
});
},
//结束录音
stopRecord(){
var that = this;
var recMp3 = api.require('recMp3');
recMp3.stop(function(ret,err) {
if(ret){
var duration = ret.duration;
var path = ret.path;
//得到mp3的名字
var pathArr = path.split("/");
var mp3Name = pathArr[pathArr.length-1];
if(duration>1){
var fs = api.require('fs');
//将mp3移动到widget以便于得到相对路径,只有相对路径才能进行本地ajax请求
fs.moveTo({
oldPath : path,
newPath : 'widget://mp3/'
}, function(ret, err) {
that.mp32Base64('../../mp3/'+mp3Name);
});
}else{
func.msg('录音时间太短,请重新录制!');
}
clearInterval(that.timer);
that.howLong = 0;
that.recordState = 3;
}
});
},
//mp3转base64
mp32Base64:function(path){
var that = this;
var xhr = new XMLHttpRequest();
xhr.open('GET', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
let fileReader = new FileReader();
fileReader.readAsDataURL(xhr.response)
fileReader.onload = function (e){
console.log(e.target.result);
//最终得到mp3的base64
that.mp3Base64 = e.target.result;
};
};
},
至此完成了!此方法不仅仅适用于apicloud,web端也可以。另外,如果不是因为外网被禁,我肯定直接传给后台转base64了,转完了,再发回来。此外,其实虽然使用ajax成功读取了本地文件,但是仅限于当前项目,如果想用ajax读取项目之外的文件,还是不好弄!
