Browse Source

测试录音

liushengqiang 1 year ago
parent
commit
6c42541366
4 changed files with 99 additions and 61 deletions
  1. 11 0
      package-lock.json
  2. 1 0
      package.json
  3. 2 0
      src/view/evaluating/index.tsx
  4. 85 61
      src/view/evaluating/recordAudio.ts

+ 11 - 0
package-lock.json

@@ -15,6 +15,7 @@
         "eventemitter3": "^5.0.0",
         "howler": "^2.2.3",
         "html2canvas": "^1.4.1",
+        "js-audio-recorder": "^1.0.7",
         "lodash": "^4.17.21",
         "plyr": "^3.7.8",
         "query-string": "^8.1.0",
@@ -3389,6 +3390,11 @@
         "whatwg-fetch": ">=0.10.0"
       }
     },
+    "node_modules/js-audio-recorder": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/js-audio-recorder/-/js-audio-recorder-1.0.7.tgz",
+      "integrity": "sha512-JiDODCElVHGrFyjGYwYyNi7zCbKk9va9C77w+zCPMmi4C6ix7zsX2h3ddHugmo4dOTOTCym9++b/wVW9nC0IaA=="
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -6991,6 +6997,11 @@
         "whatwg-fetch": ">=0.10.0"
       }
     },
+    "js-audio-recorder": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/js-audio-recorder/-/js-audio-recorder-1.0.7.tgz",
+      "integrity": "sha512-JiDODCElVHGrFyjGYwYyNi7zCbKk9va9C77w+zCPMmi4C6ix7zsX2h3ddHugmo4dOTOTCym9++b/wVW9nC0IaA=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "eventemitter3": "^5.0.0",
     "howler": "^2.2.3",
     "html2canvas": "^1.4.1",
+    "js-audio-recorder": "^1.0.7",
     "lodash": "^4.17.21",
     "plyr": "^3.7.8",
     "query-string": "^8.1.0",

+ 2 - 0
src/view/evaluating/index.tsx

@@ -215,6 +215,8 @@ export const handleStartBegin = async () => {
 	} catch (error) {}
 	const res = await startEvaluating(evaluatingData.contentData);
 	startRecordingAudio();
+	playMusic()
+	evaluatingData.backtime = Date.now();
 	evaluatingData.startBegin = true
 	// if (res?.api !== "startEvaluating") {
 	// 	Snackbar.error("请在APP端进行评测");

+ 85 - 61
src/view/evaluating/recordAudio.ts

@@ -1,68 +1,94 @@
-import Recorder from 'recorder-core/recorder.mp3.min'
-// let mediaRecorder: Recorder | null;
-// let chunks: Blob[] = [];
+import JsRecorder from 'js-audio-recorder'
+import Recorder from "recorder-core/recorder.mp3.min";
+let mediaRecorder: JsRecorder | null;
+let chunks: Blob[] = [];
 
+/**
+ * 下载录音文件
+ * @private
+ * @param {*} blob      blob数据
+ * @param {string} name 下载的文件名
+ * @param {string} type 下载的文件后缀
+ */
+function _download(blob: Blob, name: string, type: string): void {
+    let oA = document.createElement('a');
+
+    oA.href = window.URL.createObjectURL(blob);
+    oA.download = `${ name }.${ type }`;
+    oA.click();
+}
 
-var rec : typeof Recorder | null;
+let rec: typeof Recorder | null;
 /**调用open打开录音请求好录音权限**/
-var recOpen=function(success?:any){//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
-    rec=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){
-			console.log(buffers,powerLevel,bufferDuration,bufferSampleRate,newBufferIdx,asyncEnd)
-            //录音实时回调,大约1秒调用12次本回调,buffers为开始到现在的所有录音pcm数据块(16位小端LE)
-            //可实时绘制波形(extensions目录内的waveview.js、wavesurfer.view.js、frequency.histogram.view.js插件功能)
-            //可利用extensions/sonic.js插件实时变速变调,此插件计算量巨大,onProcess需要返回true开启异步模式
-            //可实时上传(发送)数据,配合Recorder.SampleData方法,将buffers中的新数据连续的转换成pcm上传,或使用mock方法将新数据连续的转码成其他格式上传,可以参考文档里面的:Demo片段列表 -> 实时转码并上传-通用版;基于本功能可以做到:实时转发数据、实时保存数据、实时语音识别(ASR)等
-        }
-    });
+var recOpen = function (success?: any) {
+	//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
+	rec = 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) {
+			console.log(buffers, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd);
+			//录音实时回调,大约1秒调用12次本回调,buffers为开始到现在的所有录音pcm数据块(16位小端LE)
+			//可实时绘制波形(extensions目录内的waveview.js、wavesurfer.view.js、frequency.histogram.view.js插件功能)
+			//可利用extensions/sonic.js插件实时变速变调,此插件计算量巨大,onProcess需要返回true开启异步模式
+			//可实时上传(发送)数据,配合Recorder.SampleData方法,将buffers中的新数据连续的转换成pcm上传,或使用mock方法将新数据连续的转码成其他格式上传,可以参考文档里面的:Demo片段列表 -> 实时转码并上传-通用版;基于本功能可以做到:实时转发数据、实时保存数据、实时语音识别(ASR)等
+		},
+	});
 
-    //var dialog=createDelayDialog(); 我们可以选择性的弹一个对话框:为了防止移动端浏览器存在第三种情况:用户忽略,并且(或者国产系统UC系)浏览器没有任何回调,此处demo省略了弹窗的代码
-    rec.open(function(){//打开麦克风授权获得相关资源
-        //dialog&&dialog.Cancel(); 如果开启了弹框,此处需要取消
-        //rec.start() 此处可以立即开始录音,但不建议这样编写,因为open是一个延迟漫长的操作,通过两次用户操作来分别调用open和start是推荐的最佳流程
-        
-        success&&success();
-    },function(msg:any,isUserNotAllow:any){//用户拒绝未授权或不支持
-        //dialog&&dialog.Cancel(); 如果开启了弹框,此处需要取消
-        console.log((isUserNotAllow?"UserNotAllow,":"")+"无法录音:"+msg);
-    });
+	//var dialog=createDelayDialog(); 我们可以选择性的弹一个对话框:为了防止移动端浏览器存在第三种情况:用户忽略,并且(或者国产系统UC系)浏览器没有任何回调,此处demo省略了弹窗的代码
+	rec.open(
+		function () {
+			//打开麦克风授权获得相关资源
+			//dialog&&dialog.Cancel(); 如果开启了弹框,此处需要取消
+			//rec.start() 此处可以立即开始录音,但不建议这样编写,因为open是一个延迟漫长的操作,通过两次用户操作来分别调用open和start是推荐的最佳流程
+			success && success();
+		},
+		function (msg: any, isUserNotAllow: any) {
+			//用户拒绝未授权或不支持
+			//dialog&&dialog.Cancel(); 如果开启了弹框,此处需要取消
+			console.log((isUserNotAllow ? "UserNotAllow," : "") + "无法录音:" + msg);
+		}
+	);
 };
 
 /**开始录音**/
-function recStart(){//打开了录音后才能进行start、stop调用
-    rec.start();
-};
+function recStart() {
+	//打开了录音后才能进行start、stop调用
+	rec.start();
+}
 
 /**结束录音**/
-function recStop(){
-    rec.stop(function(blob:any,duration:any){
-        
-        //简单利用URL生成本地文件地址,注意不用了时需要revokeObjectURL,否则霸占内存
-        //此地址只能本地使用,比如赋值给audio.src进行播放,赋值给a.href然后a.click()进行下载(a需提供download="xxx.mp3"属性)
-        var localUrl=(window.URL||webkitURL).createObjectURL(blob);
-        console.log(blob,localUrl,"时长:"+duration+"ms");
-        rec.close();//释放录音资源,当然可以不释放,后面可以连续调用start;但不释放时系统或浏览器会一直提示在录音,最佳操作是录完就close掉
-        // rec=null;
-        
-        //已经拿到blob文件对象想干嘛就干嘛:立即播放、上传、下载保存
-        
-        /*** 【立即播放例子】 ***/
-        var audio=document.createElement("audio");
-        audio.controls=true;
-		audio.style.position="fixed";
-		audio.style.top="0px";
-		audio.style.zIndex= '99999'
-        document.body.appendChild(audio);
-        audio.src=localUrl;
-        audio.play();
-    },function(msg:any){
-        console.log("录音失败:"+msg);
-        // rec.close();//可以通过stop方法的第3个参数来自动调用close
-        // rec=null;
-    });
-};
+function recStop() {
+	rec.stop(
+		function (blob: any, duration: any) {
+			//简单利用URL生成本地文件地址,注意不用了时需要revokeObjectURL,否则霸占内存
+			//此地址只能本地使用,比如赋值给audio.src进行播放,赋值给a.href然后a.click()进行下载(a需提供download="xxx.mp3"属性)
+			var localUrl = (window.URL || webkitURL).createObjectURL(blob);
+            _download(blob, 'test', 'mp3')
+			console.log(blob, localUrl, "时长:" + duration + "ms");
+			rec.close(); //释放录音资源,当然可以不释放,后面可以连续调用start;但不释放时系统或浏览器会一直提示在录音,最佳操作是录完就close掉
+			// rec=null;
+
+			//已经拿到blob文件对象想干嘛就干嘛:立即播放、上传、下载保存
 
+			/*** 【立即播放例子】 ***/
+			var audio = document.createElement("audio");
+			audio.controls = true;
+			audio.style.position = "fixed";
+			audio.style.top = "0px";
+			audio.style.zIndex = "99999";
+			document.body.appendChild(audio);
+			audio.src = localUrl;
+			audio.play();
+		},
+		function (msg: any) {
+			console.log("录音失败:" + msg);
+			// rec.close();//可以通过stop方法的第3个参数来自动调用close
+			// rec=null;
+		}
+	);
+}
 
 //我们可以选择性的弹一个对话框:为了防止移动端浏览器存在第三种情况:用户忽略,并且(或者国产系统UC系)浏览器没有任何回调
 /*伪代码:
@@ -81,7 +107,6 @@ function createDelayDialog(){
 };
 */
 
-
 //这里假设立即运行,只录3秒,录完后立即播放,本段代码copy到控制台内可直接运行
 // recOpen(function(){
 //     recStart();
@@ -100,25 +125,24 @@ export function createRecordAudio() {
 	// 	console.log("浏览器不支持录音");
 	// 	return;
 	// }
-	// mediaRecorder = new Recorder();
+	// mediaRecorder = new JsRecorder();
 	// mediaRecorder.onprogress = (payload: any) => {
 	// 	console.log(payload);
 	// };
 	// console.log("🚀 ~ mediaRecorder:", mediaRecorder);
 
-
-	recOpen()
+	recOpen();
 }
 
 // // 开始录制
 export function startRecordingAudio() {
 	// mediaRecorder?.start();
-	recStart()
+	recStart();
 }
 
 // // 停止录制
 export function stopRecordingAudio() {
-	recStop()
+	recStop();
 	// mediaRecorder?.stop();
 	// mediaRecorder?.downloadWAV("test.wav");
 	// setTimeout(() => {