前言:
最近遇到 要语音转文字 的需求,语音转文字肯定要先搞定录音功能,在网上找了好久没找到具体的 RecordRTC.js 插件的使用方法,最后只能对着 github 上开源代码小试了一下,录音功能好使所以就记录一下叭
一、RecordRTC.js 源码指路
https://github.com/muaz-khan/RecordRTC
二、功能逻辑分析
需求分析:用户点击语音按钮->请求麦克风权限,语音按钮编程文本按钮,文本输入框显示为“按住说话” ->用户按住输入框说话->显示语音录入的动画,同时文本输入框显示为“松开结束”->用户松开即结束录音,将录音文件传给后端,后端进行转文字
三、使用方法
1、从下载的源码中将RecordRTC.js 文件引入放在项目js文件中,并在项目中引用
2.新建js文件 audioRTC.js书写自己的功能逻辑代码
3、参照源码simple-demos->audio-recording.html 文件完成js代码
4、函数功能记录
captureMicrophone 获取麦克风权限
replaceAudio 释放麦克风(根据具体需求使用,我这里未释放)
recorder.startRecording() ->开始录音 (recorder 为实例对象)
recorder.stopRecording() ->结束录音
stopRecordingCallback 结束录音的回调函数
四、功能代码书写
1、准备 捕获麦克风函数
var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob);var recorder; // globally accessible
var microphone; // 麦克风
// 捕获麦克风
function captureMicrophone(callback) {console.log("捕获麦克风函数调用")if (microphone) {callback(microphone);return;}// 没有媒体设置告知版本低if (typeof navigator.mediaDevices === 'undefined' || !navigator.mediaDevices.getUserMedia) {var sys = isAndroidOrIOSOrPc();if (sys == "pc") {layer.msg("该浏览器不支持语音录入,<br>请使用谷歌、火狐等主流浏览器。", { area: ['320px', '80px'] });} else if (sys == "ios") {layer.msg("该浏览器不支持语音录入,<br>请将您的IOS操作系统升级最新版本,并使用safari浏览器打开使用。", { area: ['320px', '80px'] });} else if (sys == "android") {layer.msg("该浏览器不支持语音录入,<br>请使用系统自带浏览器打开使用。", { area: ['320px', '80px'] });} else {layer.msg("您当前的操作系统不支持语音录入。", { area: ['300px', '50px'] });}}// 获取设备的录音权限navigator.mediaDevices.getUserMedia({audio: isEdge ? true : { echoCancellation: false }}).then(function(mic) {console.log("获取麦克风成功回调",mic)callback(mic);}).catch(function(error) {console.log("获取麦克风失败回调",error)layer.msg("该浏览器不支持语音录入。<br>或您拒绝了语音授权", { area: ['300px', '60px'] });// 禁用麦克风走这里-》禁用语音按钮// 按钮背景换成语音$("#recordMess").css({"background":"url(images/noyuyin.png) no-repeat center","background-size":" 100% 100%",})$("#recordMess").attr('disabled',true);$('#chatform').children("#messCon").show();$('#chatform').children("#talkmess_btn").hide();})
}
2、按住输入框开始录音,封装录音函数
// 开始录音
function startRec() {var options = {type: 'audio',numberOfAudioChannels: 1,checkForInactiveTracks: false,bufferSize: 4096,recorderType: StereoAudioRecorder};if (recorder) {recorder.destroy();recorder = null;}// recordre 实例recorder = RecordRTC(microphone, options);recorder.startRecording(); //开始录音
};
3、停止录音回调
//停止录音的回调
function stopRecordingCallback() {// console.log("停止录音回调")var internalRecorder = recorder.getInternalRecorder();console.log("停止录音回调internalRecorder",internalRecorder)// 左声道var leftchannel = internalRecorder.leftchannel;// 右声道var rightchannel = internalRecorder.rightchannel;console.log("左声道",leftchannel)console.log(("啦啦啦",internalRecorder.blob,window.URL||webkitURL).createObjectURL(internalRecorder.blob))console.log("internalRecorderBlob",internalRecorder.blob)// 将录音文件 以文件对象形式传给后端var form = new FormData()form.append("upfile",internalRecorder.blob,"recorder.wav");console.log("form",form)$.ajax({url: '后端接口地址',type:'POST',cache: false,processData: false,contentType: false,data: form,success: function(data){console.log("后端返回数据对象",data)// 根据数据进行具体操作},error:function (err) { console.log("ajaxerr",err)}})}
4、按钮绑定监听事件,调用录音相关函数
4.1、语音按钮绑定点击事件
var flagvoice=false;
$("#recordMess").click(function() {if(flagvoice){$(this).css({"background":"url(images/yuyin.png) no-repeat center","background-size":" 100% 100%",})$('#chatform').children("#messCon").show();$('#chatform').children("#talkmess_btn").hide();flagvoice=false;}else{$(this).css({"background":"url(images/wenben.png) no-repeat center","background-size":" 100% 100%",})$('#chatform').children("#messCon").hide();$('#chatform').children("#talkmess_btn").show();flagvoice=true;}// ---------------获取麦克风权限 START--------if (!microphone) {captureMicrophone(function(mic) {console.log("获取语音权限",mic)microphone = mic;});return;}// ---------------获取麦克风权限 END--------})
4.2、输入框绑定触摸事件,触摸按开始录音
var posStart = 0;//初始化起点坐标
var posEnd = 0;//初始化终点坐标
//长按var btnElem=document.getElementById("talkmess_btn");//获取IDbtnElem.addEventListener("touchstart", function(event) {event.stopPropagation(); // 阻止冒泡event.preventDefault();//阻止浏览器默认行为posStart = 0;posStart = event.touches[0].pageY;//获取起点坐标// btnElem.value = '松开 结束';btnElem.innerText = '松开 结束';$("#audiobg").show();// $("#audiobg>p").hide();console.log("start");console.log(posStart+'---------开始坐标');// 开始录音startRec()});
4.3、输入框绑定触摸事件,触摸抬起结束录音
btnElem.addEventListener("touchend", function(event) {event.stopPropagation();event.preventDefault();posEnd = 0;posEnd = event.changedTouches[0].pageY;//获取终点坐标// btnElem.value = '按住 说话';btnElem.innerText = '按住 说话';console.log("End");console.log(posEnd+'---------结束坐标');if(posStart - posEnd < 100 ){// $("#audiobg>p").hide();console.log("发送成功");// recStop()recorder.stopRecording(stopRecordingCallback);}else{// $("#audiobg>p").show();console.log("取消发送");console.log("Cancel");};$("#audiobg").hide();});
4.4、为测试前端是否真的拿到用户语音输入的内容,可以加一个测试按钮用于下载用户语音
// 获取文件名的随机字符串
function getRandomString() {if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {var a = window.crypto.getRandomValues(new Uint32Array(3)),token = '';for (var i = 0, l = a.length; i < l; i++) {token += a[i].toString(36);}return token;} else {return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');}
}
// 文件名
function getFileName(fileExtension) {var d = new Date();var year = d.getFullYear();var month = d.getMonth();var date = d.getDate();return 'RecordRTC-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
}
// 下载录音
function downloadRecording(){console.log("下载录音")if(!recorder || !recorder.getBlob()) return;var blob = recorder.getBlob();var file = new File([blob], getFileName('wav'), {type: 'audio/wav'});invokeSaveAsDialog(file); // 该方法在recorderRTC.js中已有
}
// 下载按钮绑定点击事件
var download = document.getElementById("download")download.addEventListener("click",function(){downloadRecording()
})
五、存在问题
完成上述代码之后,经测试发现该功能在安卓手机上正常,但是在一些较老版本的ios系统上(如 iPhone 7Plus iphone xs)存在只能录音一次的问题,解决方案:在结束录音函数中判断设备是ios即释放麦克风,在开始录音中判断麦克风是否存在并再调用一次开始录音函数,具体代码如下:
// 释放麦克风
function releaseMicrophone(){if(microphone) {microphone.stop();microphone = null;}}
// 判断设备是否是ios
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
//停止录音的回调
function stopRecordingCallback() {// --------此处省略结束录音回调函数,代码同上,仅追加对于ios的判断--------------if(isSafari){releaseMicrophone()}
}
// 开始录音
function startRec() {
// -----------新增补充代码 start-------------if (!microphone) {captureMicrophone(function(mic) {microphone = mic;// click(btnStartRecording);startRec()});return;}
// -----------新增补充代码 end-------------var options = {type: 'audio',numberOfAudioChannels: 1,checkForInactiveTracks: false,bufferSize: 4096,sampleRate:48000,recorderType: StereoAudioRecorder};if (recorder) {recorder.destroy();recorder = null;}// recordre 实例recorder = RecordRTC(microphone, options);recorder.startRecording(); //开始录音
};