//====================引入Recorder=====================
// 必须引入的核心,recorder-core会自动往window下挂载名称为Recorder对象,全局可调用window.Recorder
import Recorder from 'recorder-core'; //注意如果未引用Recorder变量,可能编译时会被优化删除(如vue3 tree-shaking),请改成 import 'recorder-core',或随便调用一下 Recorder.a=1 保证强引用
//需要使用到的音频格式编码引擎的js文件统统加载进来
import 'recorder-core/src/engine/mp3';
import 'recorder-core/src/engine/mp3-engine';
//以上三个也可以合并使用压缩好的recorder.xxx.min.js
//import Recorder from 'recorder-core/recorder.mp3.min' //已包含recorder-core和mp3格式支持
//import Recorder from 'recorder-core/recorder.wav.min' //已包含recorder-core和wav格式支持
//可选的插件支持项,把需要的插件按需引入进来即可
import 'recorder-core/src/extensions/waveview';
//====================End=====================
// copy 的 QuickStart.html 代码,统统any,这些代码和普通js代码没有区别,主要用途是验证上面的import能正常引入和打包就完成目的了,对于ts 这些代码并没有什么特殊的地方
var win=window as any;
var doc=document as any;
var reclog=function(...args:any):void{ win.reclog.apply(null, args); }
var rec : any,wave : any, recBlob: any;
/**调用open打开录音请求好录音权限**/
win.recOpen=function(){//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
rec=null;
wave=null;
recBlob=null;
var newRec=Recorder({
type:"mp3",sampleRate:16000,bitRate:16 //mp3格式,指定采样率hz、比特率kbps,其他参数使用默认配置;注意:是数字的参数必须提供数字,不要用字符串;需要使用的type类型,需提前把格式支持文件加载进来,比如使用wav格式需要提前加载wav.js编码引擎
,onProcess:function(buffers:any,powerLevel:any,bufferDuration:any,bufferSampleRate:any,newBufferIdx:any,asyncEnd:any){
//录音实时回调,大约1秒调用12次本回调
doc.querySelector(".recpowerx").style.width=powerLevel+"%";
doc.querySelector(".recpowert").innerText=formatMs(bufferDuration,1)+" / "+powerLevel;
//可视化图形绘制
wave.input(buffers[buffers.length-1],powerLevel,bufferSampleRate);
}
});
newRec.open(function(){//打开麦克风授权获得相关资源
rec=newRec;
//此处创建这些音频可视化图形绘制浏览器支持妥妥的
wave=Recorder.WaveView({elem:".recwave"});
reclog("已打开录音,可以点击录制开始录音了",2);
},function(msg:any,isUserNotAllow:any){//用户拒绝未授权或不支持
reclog((isUserNotAllow?"UserNotAllow,":"")+"打开录音失败:"+msg,1);
});
};
/**关闭录音,释放资源**/
win.recClose=function(){
if(rec){
rec.close();
reclog("已关闭");
}else{
reclog("未打开录音",1);
};
};
/**开始录音**/
win.recStart=function(){//打开了录音后才能进行start、stop调用
if(rec&&Recorder.IsOpen()){
recBlob=null;
rec.start();
reclog("已开始录音...");
}else{
reclog("未打开录音",1);
};
};
/**暂停录音**/
win.recPause=function(){
if(rec&&Recorder.IsOpen()){
rec.pause();
}else{
reclog("未打开录音",1);
};
};
/**恢复录音**/
win.recResume=function(){
if(rec&&Recorder.IsOpen()){
rec.resume();
}else{
reclog("未打开录音",1);
};
};
/**结束录音,得到音频文件**/
win.recStop=function(){
if(!(rec&&Recorder.IsOpen())){
reclog("未打开录音",1);
return;
};
rec.stop(function(blob:any,duration:any){
console.log(blob,(win.URL||webkitURL).createObjectURL(blob),"时长:"+duration+"ms");
recBlob=blob;
reclog("已录制mp3:"+formatMs(duration)+"ms "+blob.size+"字节,可以点击播放、上传了",2);
},function(msg:any){
reclog("录音失败:"+msg,1);
});
};
/**播放**/
win.recPlay=function(){
if(!recBlob){
reclog("请先录音,然后停止后再播放",1);
return;
};
var cls=("a"+Math.random()).replace(".","");
reclog('播放中: ');
var audio=doc.createElement("audio");
audio.controls=true;
doc.querySelector("."+cls).appendChild(audio);
//简单利用URL生成播放地址,注意不用了时需要revokeObjectURL,否则霸占内存
audio.src=(win.URL||webkitURL).createObjectURL(recBlob);
audio.play();
setTimeout(function(){
(win.URL||webkitURL).revokeObjectURL(audio.src);
},5000);
};
/**上传**/
win.recUpload=function(){
var blob=recBlob;
if(!blob){
reclog("请先录音,然后停止后再上传",1);
return;
};
//本例子假设使用原始XMLHttpRequest请求方式,实际使用中自行调整为自己的请求方式
//录音结束时拿到了blob文件对象,可以用FileReader读取出内容,或者用FormData上传
var api="http://127.0.0.1:9528";
var onreadystatechange=function(xhr:any,title:any){
return function(){
if(xhr.readyState==4){
if(xhr.status==200){
reclog(title+"上传成功"+' response: '+xhr.responseText+'',2);
}else{
reclog(title+"没有完成上传,演示上传地址无需关注上传结果,只要浏览器控制台内Network面板内看到的请求数据结构是预期的就ok了。", "#d8c1a0");
console.error(title+"上传失败",xhr.status,xhr.responseText);
};
};
};
};
reclog("开始上传到"+api+",请稍候... (你可以先到源码 /assets/node-localServer 目录内执行 npm run start 来运行本地测试服务器)");
/***方式一:将blob文件转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传***/
var reader=new win.FileReader();
reader.onloadend=function(){
var postData="";
postData+="mime="+encodeURIComponent(blob.type);//告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
postData+="&upfile_b64="+encodeURIComponent((/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result)||[])[1]) //录音文件内容,后端进行base64解码成二进制
//...其他表单参数
var xhr=new XMLHttpRequest();
xhr.open("POST", api+"/uploadBase64");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.onreadystatechange=onreadystatechange(xhr,"上传方式一【Base64】");
xhr.send(postData);
};
reader.readAsDataURL(blob);
/***方式二:使用FormData用multipart/form-data表单上传文件***/
var form=new FormData();
form.append("upfile",blob,"recorder.mp3"); //和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3
//...其他表单参数
var xhr=new XMLHttpRequest();
xhr.open("POST", api+"/upload");
xhr.onreadystatechange=onreadystatechange(xhr,"上传方式二【FormData】");
xhr.send(form);
};
/**本地下载 Local download**/
win.recLocalDown=function(){
if(!recBlob){
reclog("请先录音,然后停止后再下载",1);
return;
};
var cls=("a"+Math.random()).replace(".","");
win.recdown64.lastCls=cls;
reclog('点击 下载,或复制文本'
+'');
var fileName="recorder-"+Date.now()+".mp3";
var downA=doc.createElement("A");
downA.innerHTML="下载 "+fileName;
downA.href=(win.URL||webkitURL).createObjectURL(recBlob);
downA.download=fileName;
doc.querySelector("."+cls).appendChild(downA);
if(/mobile/i.test(navigator.userAgent)){
alert("因移动端绝大部分国产浏览器未适配Blob Url的下载,所以本demo代码在移动端未调用downA.click()。请尝试点击日志中显示的下载链接下载");
}else{
downA.click();
}
//不用了时需要revokeObjectURL,否则霸占内存
//(win.URL||webkitURL).revokeObjectURL(downA.href);
};
win.recdown64=function(cls:any){
var el=doc.querySelector("."+cls+"_b64");
if(win.recdown64.lastCls!=cls){
el.innerHTML='老的数据没有保存,只支持最新的一条';
return;
}
var reader = new FileReader();
reader.onloadend = function() {
el.innerHTML='';
el.querySelector("textarea").value=reader.result;
};
reader.readAsDataURL(recBlob);
};
var formatMs=function(ms:any,all?:any){
var f=Math.floor(ms/60000),m=Math.floor(ms/1000)%60;
var s=(all||f>0?(f<10?"0":"")+f+":":"")
+(all||f>0||m>0?("0"+m).substr(-2)+"″":"")
+("00"+ms%1000).substr(-3);
return s;
};