1.Vue安装插件
npm install --registry=https://registry.npmmirror.com
2.Vue页面使用
<template>
<div class="app-container">
<!-- header -->
<el-header class="procedureHeader" style="height: 20px;">
<el-divider content-position="left">
<h3>
<el-link type="primary" style="background-color: rgba(255, 255, 255, 0.5);">语音识别</el-link>
</h3>
</el-divider>
</el-header>
<el-row>
<!-- 左侧语音录制区域-->
<el-col :span="12">
<div class="asr-left">
<el-input v-model="asrName" placeholder="请输入内容" size="small"
style="width: 192px;margin-left: 20px;margin-top: 20px;"></el-input>
<el-input type="textarea" :rows="34" placeholder="请开始录音" v-model="asrData" size="small" :readonly="true"
style="margin-left: 20px;margin-top: 20px;width: 94%;">
</el-input>
<div style="display: -webkit-box;">
<div style="margin-left: 18px;margin-top: 20px;margin-bottom: 10px;width: 82%;">
<span style="color: #303133;">时长:</span>
<span style="color: #303133;">{{convertSecondsToHMS(recorder.duration.toFixed(4))}}</span>
<span title="开始录音" class="asr-btn" style="margin-left: 67%;" v-if="startRecord" @click="handleStartRecord">
<i class="el-icon-microphone"></i>
</span>
<span title="录音中" class="asr-btn" style="color: #1890ff;margin-left: 67%;" v-if="recordIng" @click="handleRecordIng">
<i class="el-icon-mic"></i>
</span>
<span title="播放录音" class="asr-btn" v-if="playRecord" @click="handlePlayRecord">
<i class="el-icon-video-play"></i>
</span>
<span title="播放中" class="asr-btn" v-if="playRecordIng" @click="handlePlayRecordIng">
<i class="el-icon-video-pause"></i>
</span>
<span title="结束录音" class="asr-btn" style="color: red;" @click="handleStopRecord">
<i class="el-icon-switch-button" style="font-weight: 600;"></i>
</span>
</div>
<el-button type="primary" size="mini" style="margin-top: 17px;" @click="handleRecord">开始识别</el-button>
</div>
</div>
</el-col>
<!-- 右侧语音识别结果展示区域 -->
<el-col :span="12" class="asr-right">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px" style="margin-top: 20px;">
<el-form-item label="标题" prop="title">
<el-input
v-model="queryParams.title"
placeholder="请输入标题"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="asrList" height="675">
<el-table-column label="名称" align="center" prop="title" width="340" />
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="状态" align="center" width="100" prop="flag" :formatter="flagFormat"/>
<el-table-column label="操作" align="center" width="100" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
v-if="scope.row.flag == 2"
@click="handleOpen(scope.row)"
>查看</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 查看语音识别信息弹窗 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-input type="textarea" :rows="34" placeholder="" v-model="asrCallbackData" size="small" :readonly="true" >
</el-input>
</el-dialog>
</el-col>
</el-row>
</div>
</template>
<script>
import { listAsr,upload,getAsr } from "@/api/mam/asr";
import Recorder from 'js-audio-recorder';
let recorder = new Recorder();
export default {
name: "asr",
data() {
return {
recorder: new Recorder({
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
numChannels: 1, // 声道,支持 1 或 2, 默认是1
compiling: false //(0.x版本中生效,1.x增加中) 是否边录边转换,默认是false
}),
// 语音识别任务名称
asrName: "",
// 语音识别结果
asrData: "",
// 录音时长
recordTime: "00:00:00",
// 开始录音
startRecord: true,
// 录音中
recordIng: false,
// 播放录音
playRecord: true,
// 播放中
playRecordIng: false,
// 倒计时播放
countdownTimer: null,
// 任务轮询定时器
taskTimer: null,
// 总条数
total: 0,
// 语音识别表格数据
asrList: [],
// 遮罩层
loading: true,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
taskid: null,
assetid: null,
fileid: null,
title: null,
content: null,
createtime: null,
creator: null,
flag: null
},
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 弹出层数据
asrCallbackData: ""
}
},
created() {
this.asrName= this.getNowTime();
this.getList();
},
methods: {
/** 查询语音识别列表 */
getList() {
this.loading = true;
listAsr(this.queryParams).then(response => {
this.asrList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 表单重置
reset() {
this.form = {
id: null,
taskid: null,
assetid: null,
fileid: null,
title: null,
content: null,
createtime: null,
creator: null,
flag: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//任务状态格式化
flagFormat(row, column){
if(row.flag == 0){
return "未开始";
}else if(row.flag == 1){
return "进行中";
}else if(row.flag == 2){
return "已完成";
}else if(row.flag == 3){
return "出错";
}else{
return "未知状态";
}
},
// 打开弹出层
handleOpen(row){
this.title = row.title;
this.open = true;
this.asrCallbackData = row.content;
},
// 开始录音
handleStartRecord(){
Recorder.getPermission().then(
() => {
if(this.asrData == "正在转写中..."){
this.$message.warning('正在转写中...');
}else{
//开始录音时关闭录音播放
this.playRecordIng = false;
this.playRecord = true;
this.recorder.pausePlay();
this.recorder.start();; // 开始录音
this.startRecord = false;
this.recordIng = true;
this.asrData = "信息采集中...";
}
},
(error) => {
this.$message({
message: "请先允许该网页使用麦克风",
type: "info",
});
console.log(`${error.name} : ${error.message}`);
}
);
},
// 录音中
handleRecordIng(){
// this.recordIng = false;
// this.startRecord = true;
},
// 播放录音
handlePlayRecord(){
if(this.recordIng ){
this.$message.warning('信息采集中,请先结束录音后,再播放录音!');
}else{
if(this.recorder.size > 0){
this.playRecord = false;
this.playRecordIng = true;
this.recorder.play();
this.asrData = "正在播放采集信息...";
//倒计时播放自动关闭
this.countdown(this.recorder.duration);
}else{
this.$message.warning('请先录制音频!');
}
}
},
// 播放中
handlePlayRecordIng(){
this.playRecordIng = false;
this.playRecord = true;
this.recorder.pausePlay();
},
// 结束录音
handleStopRecord(){
if(this.asrData == "正在转写中..."){
this.$message.warning('正在转写中...');
}else{
this.recordIng = false;
this.startRecord = true;
this.asrData = "信息采集结束...";
this.recorder.stop();
}
},
// 开始识别
handleRecord(){
//关闭录音
this.recordIng = false;
this.startRecord = true;
this.recorder.stop();
//关闭录音播放
this.playRecordIng = false;
this.playRecord = true;
this.recorder.pausePlay();
//识别
console.log(this.recorder.size);
if(this.recorder.size > 0){
// 获取 WAV 数据(Blob)
let blob =this.recorder.getWAVBlob()
console.log(blob);
let formData = new FormData()
formData.append('file', blob)
formData.append("asrTitle",this.asrName)
upload(formData).then(response => {
if(response.code == 200){
this.asrData = "正在转写中...";
//销毁实例
this.recorder.destroy();
this.msgSuccess('任务创建成功');
this.asrName= this.getNowTime();
this.taskPolling(response.msg);
}
});
}else{
this.$message.warning('请先录制音频!');
}
},
// 任务轮询
taskPolling(id){
this.taskTimer = setInterval(
() => {
//任务列表
listAsr(this.queryParams).then(response => {
this.asrList = response.rows;
this.total = response.total;
});
//列表详情
getAsr(id).then(response => {
if(response.code == 200){
if(response.data.flag == 2){
this.asrData = response.data.content;
clearInterval(this.taskTimer);
this.msgSuccess('任务已完成');
}
}
});
}
, 1000);
},
// 获取当前时间
getNowTime() {
const now = new Date();
const year = now.getFullYear();
const month = this.padNumber(now.getMonth() + 1);
const day = this.padNumber(now.getDate());
const hours = this.padNumber(now.getHours());
const minutes = this.padNumber(now.getMinutes());
const seconds = this.padNumber(now.getSeconds());
return "语音识别-"+`${year}${month}${day}${hours}${minutes}${seconds}`;
},
padNumber(num) {
return num < 10 ? '0' + num : num;
},
//秒数转为时分秒
convertSecondsToHMS(seconds) {
var date = new Date(null);
date.setSeconds(seconds);
var timeString = date.toISOString().substr(11, 8);
return timeString;
},
//倒计时播放
countdown(currentSeconds) {
this.countdownTimer = setInterval(() => {
currentSeconds--; // 每次间隔1秒,将秒数减少1
if (currentSeconds < 0) {
clearInterval(this.countdownTimer); // 当秒数小于等于0时清除定时器
// console.log("倒计时结束");
this.playRecordIng = false;
this.playRecord = true;
this.asrData = "采集信息播放结束...";
} else {
// console.log(`还有 ${seconds} 秒`);
}
}, 1000); // 设置定时器间隔为1秒(1000毫秒)
}
}
}
</script>
<style scoped lang="less">
/* 左侧语音录制区域 */
.asr-left {
/*border: 1px solid #ebebeb;*/
margin-left: 20px;
}
/* header */
::v-deep .el-divider__text {
background-color: unset;
}
/* 右侧语音识别结果展示区域 */
.asr-right {
}
/* 按钮 */
.asr-btn {
cursor: pointer;
margin-left: 15px;
font-size: 20px;
}
</style>
3.效果图
4.注意使用127.0.0.1或者localhost与线上地址用Ip或者域名访问时不一样,因为getUserMedia在高版本的chrome下需要使用https。若仍需要使用,按下面步骤使用。
浏览器地址栏输入:
chrome://flags/#unsafely-treat-insecure-origin-as-secure
5.详细参考博主地址
https://www.cnblogs.com/badaoliumangqizhi/p/16711777.html