Vue+ElementUi实现录音播放上传及处理getUserMedia报错问题

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/766257.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

密码学及其应用 —— 密码学的经典问题

1. 古典密码学问题 1.1 问题1&#xff1a;破解凯撒密码 1.1.1 问题 凯撒密码是最简单的单字母替换加密方案。这是一种通过将字母表中的字母固定向右移动几位来实现的加密方法。解密下面的文本&#xff0c;该文本通过对一个去除了空格的法语文本应用凯撒密码获得&#xff1a; …

layui-按钮

1.用法 使用 用button标签 type"button" class"layui-button" 效果&#xff1a; 2.主题设置 前面都要加上layui-bin 3.尺寸设置 可以叠加使用&#xff01; 4.圆角设置 加一个layui-bin-radius 5.按钮图标设置 里面加一个i标签 加class"layui-…

借教室(题解)

P1083 [NOIP2012 提高组] 借教室 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路&#xff1a;二分前缀和 我们将和质检员那题差不多&#xff0c;只需要将候选人二分即可 #include<bits/stdc.h> using namespace std; #define int long long int n,m; int r[100000…

【操作与配置】VSCode配置Python

Python环境配置 可以参见&#xff1a;【操作与配置】Python&#xff1a;CondaPycharm_pycharmconda-CSDN博客 官网下载Python&#xff1a;http://www.python.org/download/官网下载Conda&#xff1a;Miniconda — Anaconda documentation VSCode插件安装 插件安装后需重启V…

disql使用

进入bin目录&#xff1a;cd /opt/dmdbms/bin 启动disql&#xff1a;./disql&#xff0c;然后输入用户名、密码 sh文件直接使用disql&#xff1a; 临时添加路径到PATH环境变量&#xff1a;在当前会话中临时使用disql命令而无需每次都写完整路径&#xff0c;可以在执行脚本之前…

Eclipse + GDB + J-Link 的单片机程序调试实践

Eclipse GDB J-Link 的调试实践 本文介绍如何创建Eclipse的调试配置&#xff0c;如何控制调试过程&#xff0c;如何查看修改各种变量。 对 Eclipse 的要求 所用 Eclipse 应当安装了 Eclipse Embedded CDT 插件。从 https://www.eclipse.org/downloads/packages/ 下载 Ecli…

20240628模拟赛总结

cf好了 让我们开始 T1 Two Regular Polygons 判断能不能构造出题中要求的正多边形 关键是n%m0 Two Regular Polygons #include<bits/stdc.h> using namespace std; int t; int n,m; int main() {cin>>t;for(int i1;i<t;i){cin>>n>>m;if(n%m0)co…

MySQL 代理层:ProxySQL

文章目录 说明安装部署1.1 yum 安装1.2 启停管理1.3 查询版本1.4 Admin 管理接口 入门体验功能介绍3.1 多层次配置系统 读写分离将实例接入到代理服务定义主机组之间的复制关系配置路由规则事务读的配置延迟阈值和请求转发 ProxySQL 核心表mysql_usersmysql_serversmysql_repli…

【C++】相机标定源码笔记- 标定工具库测试

标定工具库测试 一、计算相机内参&#xff1a;对两个相机进行内参标定&#xff0c;并将标定结果保存到指定的文件中 采集图像&#xff1a;相机1-16张 相机2-17张 定义保存相机1/2内参的文件(.yml)路径。 定义相机1/2采集的图片文件夹路径。定义相机1/2存储文件名的向量获取文件…

作为图形渲染API,OpenGL和Direct3D的全方位对比。

当你在网页看到很多美轮美奂的图形效果&#xff0c;3D交互效果&#xff0c;你知道是如何实现的吗&#xff1f;当然是借助图形渲染API了&#xff0c;说起这个不就不得说两大阵营&#xff0c;OpenGL和Direct3D&#xff0c;贝格前端工场在本文对二者做个详细对比。 一、什么是图形…

26.5 Django模板层

1. 模版介绍 在Django中, 模板(Templates)主要用于动态地生成HTML页面. 当需要基于某些数据(如用户信息, 数据库查询结果等)来动态地渲染HTML页面时, 就会使用到模板.以下是模板在Django中使用的几个关键场景: * 1. 动态内容生成: 当需要根据数据库中的数据或其他动态数据来生…

推动能源绿色低碳发展,风机巡检进入国产超高清+AI时代

全球绿色低碳能源数字转型发展正在进入一个重要窗口期。风电作为一种清洁能源&#xff0c;在碳中和过程中扮演重要角色&#xff0c;但风电场运维却是一件十足的“苦差事”。 传统的风机叶片人工巡检方式主要依靠巡检人员利用高倍望远镜检查、高空绕行下降目测检查(蜘蛛人)、叶…

校园水质信息化监管系统——水质监管物联网系统

随着物联网技术的发展越来越成熟&#xff0c;它不断地与人们的日常生活和工作深入融合&#xff0c;推动着社会的进步。其中物联网系统集成在高校实践课程中可以应用到许多项目&#xff0c;如环境气象检测、花卉种植信息化监管、水质信息化监管、校园设施物联网信息化改造、停车…

Qt6 qcustomplot在图表上画一条直线

完整代码如下: 主要注意的是Qt中的QHBoxLayout等Qt类对象在被引用的情况下是可以使用局部变量的,典型的如setLayout这类型的函数接口,都可以使用局部变量,而不是new对象。 另外一点就是qcustomplot中的replot就相当于Qt中的update,由于qcustomplot是属于绘图类的接口库,…

如何用Python向PPT中批量插入图片

办公自动化办公中&#xff0c;Python最大的优势是可以批量操作&#xff0c;省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道&#xff0c;把图片插入到PPT当中的固定位置是一个非常繁琐的操作&#xff0c;往往调整图片时耗费大量的时间和精力。如何能省时省力插…

新型200V预稳压器可简化故障容受型电源的设计

讨论几种设计故障容受型电源的方法&#xff0c;其中包括新的预稳压器拓扑结构&#xff0c;该结构可简化电路设计及元件选择。 对抗相位故障 如果交流电源到电表之间出现错误连接故障&#xff0c;或是像空调或电磁炉等采用三相电源工作的大功率负载在两个相位之间的连接错误&a…

微信小程序 canvas 处理图片的缩放移动旋转问题

这里使用到了一个插件&#xff0c;canvas-drag&#xff0c;来实现大部分功能的 上效果 直接上代码吧~ wxml <div class"container"><canvas-drag id"canvas-drag" graph"{{graph}}" width"700" height"750" ena…

[漏洞分析] CVE-2024-6387 OpenSSH核弹核的并不是很弹

文章目录 漏洞简介漏洞原理补丁分析漏洞原理 漏洞利用漏洞利用1: SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, from 2005) [无ASLR无NX]漏洞利用原理漏洞利用关键点 漏洞利用2: SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, from 2006) [无ASLR…

[C++][设计模式][组合模式]详细讲解

目录 1.动机(Motivation)2.模式定义3.要点总结4.代码感受 1.动机(Motivation) 软件在某些情况下&#xff0c;客户代码过多地依赖于对象容器复杂的内部实现结构&#xff0c;对象容器内部实现结构(而非抽象结构)的变化引起客户代码的频繁变化&#xff0c;带来了代码的维护性、扩…

Hi3861 OpenHarmony嵌入式应用入门--wifi sta

鸿蒙WiFi STA模式相关的API接口文件路径 foundation/communication/interfaces/kits/wifi_lite/wifiservice/wifi_device.h 所使用的API接口有&#xff1a; API 接口说明 WifiErrorCode EnableWifi(void); 开启STA WifiErrorCode DisableWifi(void); 关闭STA int IsWif…