智能面试——录音及播放下载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

相关文章

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

基于Python实现智能天气提醒助手

《基于Python实现智能天气提醒助手》这篇文章主要来和大家分享一个实用的Python天气提醒助手开发方案,这个工具可以方便地集成到青龙面板或其他调度框架中使用,有需要的小伙伴可以参考一下... 目录项目概述核心功能技术实现1. 天气API集成2. AI建议生成3. 消息推送环境配置使用方法完整代码项目特点

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

JavaScript实战:智能密码生成器开发指南

本文通过JavaScript实战开发智能密码生成器,详解如何运用crypto.getRandomValues实现加密级随机密码生成,包含多字符组合、安全强度可视化、易混淆字符排除等企业级功能。学习密码强度检测算法与信息熵计算原理,获取可直接嵌入项目的完整代码,提升Web应用的安全开发能力 目录

利用Python实现Excel文件智能合并工具

《利用Python实现Excel文件智能合并工具》有时候,我们需要将多个Excel文件按照特定顺序合并成一个文件,这样可以更方便地进行后续的数据处理和分析,下面我们看看如何使用Python实现Exce... 目录运行结果为什么需要这个工具技术实现工具的核心功能代码解析使用示例工具优化与扩展有时候,我们需要将

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

Spring Boot Controller处理HTTP请求体的方法

《SpringBootController处理HTTP请求体的方法》SpringBoot提供了强大的机制来处理不同Content-Type​的HTTP请求体,这主要依赖于HttpMessageCo... 目录一、核心机制:HttpMessageConverter​二、按Content-Type​处理详解1.

一文详解如何在Vue3中封装API请求

《一文详解如何在Vue3中封装API请求》在现代前端开发中,API请求是不可避免的一部分,尤其是与后端交互时,下面我们来看看如何在Vue3项目中封装API请求,让你在实现功能时更加高效吧... 目录为什么要封装API请求1. vue 3项目结构2. 安装axIOS3. 创建API封装模块4. 封装API请求

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指