智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参

本文主要是介绍智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

录音插件 js-audio-recorder

image.png

bug:本地调试调取不起来麦克风

  • 浏览器配置安全域名 chrome://flags/
  • Insecure origins treated as secure
  • 输入域名即可
  • 电脑需要连接上耳机
<template><div class="BaseRecorder"><div class="BaseRecorder-record"><el-button @click="startRecorder()">开始录音</el-button><el-button @click="pauseRecorder()">暂停录音</el-button><el-button @click="resumeRecorder()">继续录音</el-button><el-button @click="stopRecorder()">结束录音</el-button></div><div class="BaseRecorder-play"><el-button @click="playRecorder()">录音播放</el-button><el-button @click="pausePlayRecorder()">暂停录音播放</el-button><el-button @click="resumePlayRecorder()">恢复录音播放</el-button><el-button @click="stopPlayRecorder()">停止录音播放</el-button></div><div class="BaseRecorder-download"><el-button @click="downPCM()">下载PCM</el-button><el-button @click="downWAV()">下载WAV</el-button></div><div class="BaseRecorder-destroy"><el-button type="error" @click="destroyRecorder()">销毁录音</el-button></div><div class="BaseRecorder-wave"><canvas ref="record"></canvas><canvas ref="play"></canvas></div></div>
</template><script>
import Recorder from "js-audio-recorder";export default {name: "home",data() {return {recorder: null,// 波浪图-录音drawRecordId: null,// 波浪图-播放drawPlayId: null,};},mounted() {this.init();},methods: {// 初始化init() {this.recorder = new Recorder({// 采样位数,支持 8 或 16,默认是16sampleBits: 16,// 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值sampleRate: 48000,// 声道,支持 1 或 2, 默认是1numChannels: 1,// 是否边录边转换,默认是falsecompiling: false,});},// 开始录音startRecorder() {this.recorder.start().then(() => {console.log("开始录音", this.recorder);this.drawRecord();this.recorder.onprogress = (params) => {console.log(params);// 此处控制数据的收集频率if (this.recorder.config.compiling) {console.log("音频总数据:", params.data);}};// 定时获取录音的数据并播放this.recorder.config.compiling &&(playTimer = setInterval(() => {let newData = this.recorder.getNextData();if (!newData.length) {return;}let byteLength = newData[0].byteLength;let buffer = new ArrayBuffer(newData.length * byteLength);let dataView = new DataView(buffer);// 数据合并for (let i = 0, iLen = newData.length; i < iLen; ++i) {for (let j = 0, jLen = newData[i].byteLength; j < jLen; ++j) {dataView.setInt8(i * byteLength + j, newData[i].getInt8(j));}}// 将录音数据转成WAV格式,并播放let a = encodeWAV(dataView,config.sampleRate,config.sampleRate,config.numChannels,config.sampleBits);let blob = new Blob([a], { type: "audio/wav" });blob.arrayBuffer().then((arraybuffer) => {console.log(arraybuffer);// Player.play(arraybuffer);});}, 3000));},(error) => {// 出错了console.log(`${error.name} : ${error.message}`);});},// 继续录音resumeRecorder() {this.recorder.resume();},// 暂停录音pauseRecorder() {this.recorder.pause();this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 结束录音stopRecorder() {this.recorder.stop();this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 录音播放playRecorder() {this.recorder.play();this.drawPlay(); // 绘制波浪图},// 暂停录音播放pausePlayRecorder() {this.recorder.pausePlay();},// 恢复录音播放resumePlayRecorder() {this.recorder.resumePlay();this.drawPlay(); // 绘制波浪图},// 停止录音播放stopPlayRecorder() {this.recorder.stopPlay();},// 销毁录音destroyRecorder() {this.recorder.destroy().then(() => {this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;this.drawPlayId && cancelAnimationFrame(this.drawPlayId);this.drawPlayId = null;this.recorder = null;});},/***  下载录音文件* */// 下载pcmdownPCM() {console.log("pcm: ", this.recorder.getPCMBlob());// 这里传参进去的时文件名this.recorder.downloadPCM("新文件");},// 下载wavdownWAV() {console.log("wav: ", this.recorder.getWAVBlob());// 这里传参进去的时文件名this.recorder.downloadWAV("新文件");},/*** 绘制波浪图-录音* */drawRecord() {this.drawRecordId = requestAnimationFrame(this.drawRecord);this.drawWave({canvas: this.$refs.record,dataArray: this.recorder.getRecordAnalyseData(),bgcolor: "rgb(255, 128, 200)",lineWidth: 1,lineColor: "rgb(0, 128, 255)",});},/*** 绘制波浪图-播放* */drawPlay() {this.drawPlayId = requestAnimationFrame(this.drawPlay);this.drawWave({canvas: this.$refs.play,dataArray: this.recorder.getPlayAnalyseData(),});},drawWave({canvas,dataArray,bgcolor = "rgb(200, 200, 200)",lineWidth = 2,lineColor = "rgb(0, 0, 0)",}) {if (!canvas) return;const ctx = canvas.getContext("2d");const bufferLength = dataArray.length;// 一个点占多少位置,共有bufferLength个点要绘制const sliceWidth = canvas.width / bufferLength;// 绘制点的x轴位置let x = 0;// 填充背景色ctx.fillStyle = bgcolor;ctx.fillRect(0, 0, canvas.width, canvas.height);// 设定波形绘制颜色ctx.lineWidth = lineWidth;ctx.strokeStyle = lineColor;ctx.beginPath();for (let i = 0; i < bufferLength; i++) {const v = dataArray[i] / 128;const y = (v * canvas.height) / 2;if (i === 0) {// 第一个点ctx.moveTo(x, y);} else {// 剩余的点ctx.lineTo(x, y);}// 依次平移,绘制所有点x += sliceWidth;}// 最后一个点ctx.lineTo(canvas.width, canvas.height / 2);ctx.stroke();},},
};
</script>
<style lang="scss" scoped>
.BaseRecorder {& > div {margin: 20px 0;}&-wave {canvas {width: 100%;border: 1px solid #ccc;}}
}
</style>

智能面试页面

image.png

<template><div class="flex1 w100 h100 bg"><div style="width: 300px" class="bg-white h100 flex-column center"><div class="blue size-30 mb-60">Java面试专场</div><div class="size-26">张三</div><div class="gray-2 mt-20 mb-100">18378562388</div><el-button type="success" round @click="start()">开始面试</el-button></div><div class="flex-1 h100 over-hidden"><divclass="h100 w65 flex1 flex-column"style="margin: 0 auto; min-width: 800px"><div class="flex-1 scroll w100 pt-30"><divv-for="(item, index) in list.filter((item) => item.show)":key="index"class="mb-30"><div class="flex_l mb-30"><i class="el-icon-question size-28 blue mr-10"></i><div class="">{{ item.topic }}</div></div><div class="flex_l" v-if="item.file"><el-avatarclass="mr-10"size="small"src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar><el-card class="flex-1"> 语音已发送 </el-card></div><div class="flex_l" v-if="item.answer"><el-avatarclass="mr-10"size="small"src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar><el-card class="flex-1">{{ item.answer }}</el-card></div></div></div><div class="w100 flex1 pb-30"><el-inputtype="textarea"placeholder="请输入内容"v-model="textarea"maxlength="500"show-word-limit:autosize="{ minRows: 4 }"></el-input><div class="w10 text-center"><el-buttontype="success"icon="el-icon-microphone"circleclass="size-16 mb-10"@click="startRecorder":disabled="disabled"></el-button><el-button:disabled="disabled"type="primary"round@click="submit(1)">提交</el-button></div></div></div></div><!-- 结果 --><el-dialog:close-on-click-modal="false":close-on-press-escape="false"title="面试结果":visible.sync="centerDialogVisible"width="600px"center:show-close="false"style="top: 16vh"><el-result:icon="score >= 80 ? 'success' : score >= 60 ? 'warning' : 'error'":title="score >= 80 ? '优秀' : score >= 60 ? '良好' : '不合格'"subTitle="面试结果"><template slot="extra"><el-button type="primary" size="medium" @click="back">返回</el-button></template></el-result></el-dialog><!-- 录音 --><el-dialog:close-on-click-modal="false":close-on-press-escape="false"title="正在录音...":visible.sync="audioVisible"width="600px"center:show-close="false"style="top: 16vh"><div class="mb-20 size-18" v-if="list[index]">{{ list[index].topic }}</div><div class="BaseRecorder-wave"><canvas ref="record"></canvas><!-- <canvas ref="play"></canvas> --></div><div class="center mt-20"><el-button type="primary" size="medium" @click="submit(2)">提交</el-button></div></el-dialog></div><!-- <div class="BaseRecorder"><div class="BaseRecorder-record"><el-button @click="startRecorder()">开始录音</el-button><el-button @click="pauseRecorder()">暂停录音</el-button><el-button @click="resumeRecorder()">继续录音</el-button><el-button @click="stopRecorder()">结束录音</el-button></div><div class="BaseRecorder-play"><el-button @click="playRecorder()">录音播放</el-button><el-button @click="pausePlayRecorder()">暂停录音播放</el-button><el-button @click="resumePlayRecorder()">恢复录音播放</el-button><el-button @click="stopPlayRecorder()">停止录音播放</el-button></div><div class="BaseRecorder-download"><el-button @click="downPCM()">下载PCM</el-button><el-button @click="downWAV()">下载WAV</el-button></div><div class="BaseRecorder-destroy"><el-button type="error" @click="destroyRecorder()">销毁录音</el-button></div><div class="BaseRecorder-wave"><canvas ref="record"></canvas><canvas ref="play"></canvas></div></div> -->
</template><script>
import Recorder from "js-audio-recorder";
// import { subText, subAudio } from "../api/test.js";
import axios from "axios";
export default {name: "home",data() {return {index: null,disabled: true,list: [{topic: "题目1:1+2等于几?",show: false,answer: "",result: "",file: "",},{topic: "题目2:2+2等于几?",show: false,answer: "",result: "",file: "",},{topic: "题目3:白日依山尽的下一句是什么?",show: false,answer: "",result: "",file: "",},],textarea: "",config: {headers: {"Content-Type": "multipart/form-data",},},centerDialogVisible: false, //结果弹窗score: "", //得分audioVisible: false, //录音弹窗recorder: null,// 波浪图-录音drawRecordId: null,// 波浪图-播放drawPlayId: null,};},mounted() {this.init();},beforeDestroy() {this.destroyRecorder();},methods: {start(i = 0) {this.index = i;this.list[this.index].show = true;this.disabled = false;},// type 1 文字  2 语音async submit(type) {if (type == 1) {if (!this.textarea.trim()) {this.$message({message: "请输入答案",type: "warning",});return;}this.list[this.index].answer = this.textarea;this.disabled = true;this.textarea = "";const formData = new FormData();formData.append("topic", this.list[this.index].topic);formData.append("answer", this.list[this.index].answer);const { data } = await axios.post("/ququ/recognize-text",formData,this.config);console.log(data.result, 99);this.list[this.index].result = data.result;this.index += 1;if (this.index == this.list.length) {this.centerDialogVisible = true;this.index = null;console.log(this.list, 88);this.score =(this.list.filter((item) => item.result == "对").length * 100) /this.list.length;} else {this.start(this.index);}} else {this.stopRecorder();this.audioVisible = false;this.list[this.index].file = this.recorder.getWAVBlob();this.disabled = true;const formData = new FormData();formData.append("topic", this.list[this.index].topic);formData.append("file", this.list[this.index].file);const { data } = await axios.post("/ququ/recognize-video",formData,this.config);console.log(data.result, 99);this.list[this.index].result = data.result;this.index += 1;if (this.index == this.list.length) {this.centerDialogVisible = true;this.index = null;console.log(this.list, 88);this.score =(this.list.filter((item) => item.result == "对").length * 100) /this.list.length;} else {this.start(this.index);}}},back() {this.centerDialogVisible = false;this.list = [{topic: "题目1:1+2等于几?",show: false,answer: "",result: "",file: "",},{topic: "题目2:2+2等于几?",show: false,answer: "",result: "",file: "",},{topic: "题目3:白日依山尽的下一句是什么?",show: false,answer: "",result: "",file: "",},];},// 初始化init() {this.recorder = new Recorder({// 采样位数,支持 8 或 16,默认是16sampleBits: 16,// 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值sampleRate: 48000,// 声道,支持 1 或 2, 默认是1numChannels: 1,// 是否边录边转换,默认是falsecompiling: false,});},// 开始录音startRecorder() {this.recorder.start().then(() => {console.log("开始录音", this.recorder);this.audioVisible = true;this.drawRecord();this.recorder.onprogress = (params) => {console.log(params);// 此处控制数据的收集频率if (this.recorder.config.compiling) {console.log("音频总数据:", params.data);}};// 定时获取录音的数据并播放this.recorder.config.compiling &&(playTimer = setInterval(() => {let newData = this.recorder.getNextData();if (!newData.length) {return;}let byteLength = newData[0].byteLength;let buffer = new ArrayBuffer(newData.length * byteLength);let dataView = new DataView(buffer);// 数据合并for (let i = 0, iLen = newData.length; i < iLen; ++i) {for (let j = 0, jLen = newData[i].byteLength; j < jLen; ++j) {dataView.setInt8(i * byteLength + j, newData[i].getInt8(j));}}// 将录音数据转成WAV格式,并播放let a = encodeWAV(dataView,config.sampleRate,config.sampleRate,config.numChannels,config.sampleBits);let blob = new Blob([a], { type: "audio/wav" });blob.arrayBuffer().then((arraybuffer) => {console.log(arraybuffer);// Player.play(arraybuffer);});}, 3000));},(error) => {// 出错了console.log(`${error.name} : ${error.message}`);});},// 继续录音resumeRecorder() {this.recorder.resume();},// 暂停录音pauseRecorder() {this.recorder.pause();this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 结束录音stopRecorder() {this.recorder.stop();this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 录音播放playRecorder() {this.recorder.play();this.drawPlay(); // 绘制波浪图},// 暂停录音播放pausePlayRecorder() {this.recorder.pausePlay();},// 恢复录音播放resumePlayRecorder() {this.recorder.resumePlay();this.drawPlay(); // 绘制波浪图},// 停止录音播放stopPlayRecorder() {this.recorder.stopPlay();},// 销毁录音destroyRecorder() {this.recorder.destroy().then(() => {this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;this.drawPlayId && cancelAnimationFrame(this.drawPlayId);this.drawPlayId = null;this.recorder = null;});},/***  下载录音文件* */// 下载pcmdownPCM() {console.log("pcm: ", this.recorder.getPCMBlob());// 这里传参进去的时文件名this.recorder.downloadPCM("新文件");},// 下载wavdownWAV() {console.log("wav: ", this.recorder.getWAVBlob());// 这里传参进去的时文件名this.recorder.downloadWAV("新文件");},/*** 绘制波浪图-录音* */drawRecord() {this.drawRecordId = requestAnimationFrame(this.drawRecord);this.drawWave({canvas: this.$refs.record,dataArray: this.recorder.getRecordAnalyseData(),bgcolor: "#a8e1fc",lineWidth: 1,lineColor: "rgb(255, 128, 200)",});},/*** 绘制波浪图-播放* */drawPlay() {this.drawPlayId = requestAnimationFrame(this.drawPlay);this.drawWave({canvas: this.$refs.play,dataArray: this.recorder.getPlayAnalyseData(),});},drawWave({canvas,dataArray,bgcolor = "rgb(200, 200, 200)",lineWidth = 2,lineColor = "rgb(0, 0, 0)",}) {if (!canvas) return;const ctx = canvas.getContext("2d");const bufferLength = dataArray.length;// 一个点占多少位置,共有bufferLength个点要绘制const sliceWidth = canvas.width / bufferLength;// 绘制点的x轴位置let x = 0;// 填充背景色ctx.fillStyle = bgcolor;ctx.fillRect(0, 0, canvas.width, canvas.height);// 设定波形绘制颜色ctx.lineWidth = lineWidth;ctx.strokeStyle = lineColor;ctx.beginPath();for (let i = 0; i < bufferLength; i++) {const v = dataArray[i] / 128;const y = (v * canvas.height) / 2;if (i === 0) {// 第一个点ctx.moveTo(x, y);} else {// 剩余的点ctx.lineTo(x, y);}// 依次平移,绘制所有点x += sliceWidth;}// 最后一个点ctx.lineTo(canvas.width, canvas.height / 2);ctx.stroke();},},
};
</script>
<style lang="scss" scoped>
.BaseRecorder {& > div {margin: 20px 0;}&-wave {canvas {width: 100%;border: 1px solid #ccc;}}
}
</style>

post请求,formdata传参

const formData = new FormData();
formData.append("topic", this.list[this.index].topic);
formData.append("answer", this.list[this.index].answer);
const { data } = await axios.post("/ququ/recognize-text",formData,{headers: {"Content-Type": "multipart/form-data",},});
console.log(data.result, 99);

这篇关于智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/891967

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费