react项目实现语音识别功能

需要调用后端接口将录音文件传给后端,由后端将录音内容转换成文字返回给前端,当然也有一些插件可以实现语音转文字功能,可以自行查找使用插件实现方法

有注释版本,下面还有 一个无注释版本。

import React, { useState, useEffect, useRef } from "react";
import { getTextByAudio } from "./api/audio";

const AudioRecorder = () => {
  const [recording, setRecording] = useState(false); // 是否正在录音
  const audioData = useRef<MediaStream | null>(null); // 创建一个ref,存储媒体流数据
  const mediaRecorderRef = useRef<MediaRecorder | null>(null); // 创建一个ref,用于存储媒体记录器实例
  const chunksRef = useRef<Blob[]>([]); // 创建一个ref,用于存储音频数据块

  useEffect(() => {
    const init = async () => {
      try {
        // 获取用户媒体设备(麦克风)的媒体流
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        // 将获取到的媒体流存储到audioData ref中
        audioData.current = stream;
      } catch (error) {
        console.error("Error accessing microphone:", error);
        // 如果获取媒体流失败,打印错误信息
        // 这里可以设置一个错误状态,用于显示给用户
      }
    };

    init();

    // 组件卸载时清理资源
    return () => {
      if (audioData.current) {
        audioData.current.getTracks().forEach((track) => track.stop());
      }
    };
  }, []);

  const startRecording = () => {
    if (audioData.current) {
      chunksRef.current = [];// 重置chunks数组,用于新的录音
      mediaRecorderRef.current = new MediaRecorder(audioData.current);// 创建一个新的MediaRecorder实例
      // 当有数据可用时触发的事件
      mediaRecorderRef.current.ondataavailable = (event) => {
        if (event.data && event.data.size > 0) {
          chunksRef.current.push(event.data);// 将数据块添加到chunks数组中
        }
      };
      mediaRecorderRef.current.start();// 开始录音
      setRecording(true);// 更新录音状态为正在录音
    }
  };

  const stopRecording = () => {
    if (
      mediaRecorderRef.current &&
      mediaRecorderRef.current.state === "recording"
    ) {
      mediaRecorderRef.current.stop();// 停止录音
      setRecording(false);// 更新录音状态为未录音

      // 当录音停止时触发的事件
      mediaRecorderRef.current.onstop = async () => {
        // 将chunks数组中的数据合并成一个Blob对象
        const blob = new Blob(chunksRef.current, { type: "audio/wav" });

        const formData = new FormData(); // 创建一个FormData对象,用于上传音频文件
        formData.append("file", blob, "recording.wav");

        getTextByAudio(formData)
          .then((res: any) => {
            console.log(res, 999);
          })
          .catch((error) => {
            console.error("Error converting audio to text:", error);
            // 这里可以设置一个错误状态,用于显示给用户
          });
      };
    }
  };

  return (
    <div>
      <button
        onClick={recording ? stopRecording : startRecording}
        style={{ backgroundColor: recording ? "red" : "white" }}
      >
        {recording ? "停止录音" : "开始录音"}
      </button>
    </div>
  );
};

export default AudioRecorder;

无注释版

import React, { useState, useEffect, useRef } from "react";
import { getTextByAudio } from "./api/audio";

const AudioRecorder = () => {
  const [recording, setRecording] = useState(false);
  const audioData = useRef<MediaStream | null>(null);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const chunksRef = useRef<Blob[]>([]);

  useEffect(() => {
    const init = async () => {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        audioData.current = stream;
      } catch (error) {
        console.error("Error accessing microphone:", error);
      }
    };

    init();
  }, []);

  const handleMouseDown = () => {
    if (audioData.current) {
      chunksRef.current = []; // Reset chunks array for new recording
      mediaRecorderRef.current = new MediaRecorder(audioData.current);
      mediaRecorderRef.current.ondataavailable = (event) => {
        if (event.data && event.data.size > 0) {
          chunksRef.current.push(event.data);
        }
      };
      mediaRecorderRef.current.start();
      setRecording(true);
    }
  };

  const handleMouseUp = () => {
    if (
      mediaRecorderRef.current &&
      mediaRecorderRef.current.state === "recording"
    ) {
      mediaRecorderRef.current.stop();
      setRecording(false);

      mediaRecorderRef.current.onstop = async () => {
        const blob = new Blob(chunksRef.current, { type: "audio/wav" });

        const formData = new FormData();
        formData.append("file", blob, "recording.wav");

        getTextByAudio(formData).then((res: any) => {
          console.log(res.Segments, 6666);
        });

        // 以下代码为下载录音
        // const url = URL.createObjectURL(blob);
        // console.log(url, 'y');
        // const a = document.createElement("a");
        // a.style.display = "none";
        // a.href = url;
        // a.download = "recording.wav";
        // document.body.appendChild(a);
        // a.click();
        // document.body.removeChild(a);
        // URL.revokeObjectURL(url);
      };
    }
  };

  return (
    <div>
      <button
        onMouseDown={handleMouseDown}
        onMouseUp={handleMouseUp}
        onMouseLeave={handleMouseUp}
        style={{ backgroundColor: recording ? "red" : "white" }}
      >
        {recording ? "正在录音..." : "开始录音"}
      </button>
    </div>
  );
};

export default AudioRecorder;

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

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

相关文章

【神经网络】CNN网络:深入理解卷积神经网络

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&#xff01; CNN网络&#xff1a;深入理解…

springboot集成达梦数据库,打包后,tomcat中启动报错

背景&#xff1a;springboot集成达梦数据库8&#xff0c;在工具idea中正常使用&#xff0c;但是打包后&#xff0c;无法启动&#xff0c;报错 pom引入的依赖 但是这种情况&#xff0c;只有在idea中启动没问题的解决方法 需要修改引入的依赖&#xff0c;再次打包就可以 <d…

PatchMixer:一种用于长时间序列预测的Patch混合架构

前言 《PatchMixer: A Patch-Mixing Architecture for Long-Term Time Series Forecasting》原文地址&#xff0c;Github开源代码地址GitHub项目地址Some-Paper-CN。本项目是译者在学习长时间序列预测、CV、NLP和机器学习过程中精读的一些论文&#xff0c;并对其进行了中文翻译…

苹果电脑压缩pdf文件,苹果电脑里如何压缩pdf文件

压缩PDF文件是现代办公和日常生活中经常需要处理的一项任务&#xff0c;无论是为了节省存储空间、方便网络传输&#xff0c;还是为了在移动设备上更流畅地阅读文档&#xff0c;学会有效地压缩PDF都显得尤为重要。在本文中&#xff0c;我们将详细探讨压缩PDF的方法&#xff0c;从…

Mac安装多版本node

Mac下使用n模块去安装多个指定版本的Node.js&#xff0c;并使用命令随时切换。 node中的n模块是&#xff0c;node专门用来管理node版本的模块&#xff0c;可以进行node版本的切换&#xff0c;下载&#xff0c;安装。 1.安装n npm install -g n 2.查看版本 n --version 3.展…

LeetCode题练习与总结:随机链表的复制--138

一、题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的…

IT入门知识第八部分《云计算》(8/10)

目录 云计算&#xff1a;现代技术的新篇章 1. 云计算基础 1.1 云计算的起源和发展 云计算的早期概念 云计算的发展历程 1.2 云计算的核心特点 按需自助服务 广泛的网络访问 资源池化 快速弹性 按使用量付费 1.3 云计算的优势和挑战 成本效益 灵活性和可扩展性 维…

日语培训日语等级考试柯桥小语种学习语言学校

什么是外来语 外来语是指在日本的国语中使用的来源于外国语言的词汇。但狭义上的外来语则是指来源于欧美国家语言的词汇&#xff0c;其中大部分是来源于英美语系的词汇。日语中的汉语词汇很多&#xff0c;大多是自古以来从中国引进的&#xff0c;从外来语的定义看&#xff0c;汉…

运算符重载详解(完全版)

1.运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数&#xff0c;也具有其返回值类型&#xff0c;函数名字和参数列表&#xff0c;其返回值类型与参数列表都与普通的函数类似 函数名&#xff1a;关键字operator后面接需要重载的…

记因hive配置文件参数运用不当导致 sqoop MySQL导入数据到hive 失败的案例

sqoop MySQL导入数据到hive报错 ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: Hive exited with status 64 报错解释&#xff1a; 这个错误表明Sqoop在尝试导入数据到Hive时遇到了问题&#xff0c;导致Hive进程异常退出。状态码…

Lua网站开发之文件表单上传

这个代码示例演示如何上传文件或图片&#xff0c;获取上传信息及保存文件到本地。 local fw require("fastweb") local request require("fastweb.request") local response require("fastweb.response") local cjson require("cjson&q…

windterm多窗口同时操作多台服务器

在配置k8s等多服务器环境时&#xff0c;我们要对多台服务器进行相同的操作&#xff0c;使用多窗口同步输入实现一次命令多段执行 初始配置&#xff0c;服务器都已连好 分屏窗口&#xff0c;按下altw->alth水平分屏&#xff0c;按下altw->altv,垂直分屏 按下ctrlshiftm,…

SAP消息号 VF028

客户在VF11冲销发票之后&#xff0c;没有生成正式的财务凭证&#xff0c;然后VF02的时候出现如下报错&#xff1a; “自动清算出具发票凭证XXXXXXX&#xff08;被冲销凭证号&#xff09;且不可能取消凭证XXXXXXX&#xff08;冲销凭证号&#xff09; 原因&#xff1a;销售订单2…

小程序下拉刷新,加载更多数据,移动端分页

文章目录 页面结构图WXML页面代码js代码wxss代码总结备注 参考&#xff1a;https://juejin.cn/post/7222855604406796346 页面结构图 一般页面就4个结构&#xff1a;最外滚动层、数据展示层、暂无数据层、没有更多数据层。 如图&#xff1a; WXML页面代码 <scroll-view …

[吃瓜教程]南瓜书第3章对数几率回归

第三章 对数几率回归 3.1 算法原理 对数几率回归&#xff08;Logistic Regression&#xff09;是一种统计方法&#xff0c;主要用于二分类问题。它通过拟合一个对数几率函数&#xff08;logit function&#xff09;&#xff0c;即对数几率&#xff08;log-odds&#xff09;与…

oracle 11g rac创建实例时发现只给一节点创建了实例 二节点没创建的处理方法

由于操作失误没有在二节点创建实例 删除数据库重新dbca建库 [oracleracdg1-1 dbs]$ dbca -silent -deleteDatabase -sourceDB rac11dg1 -sysDBAUserName sys -sysDBAPassword oracle_4U Connecting to database 4% complete 9% complete 14% complete 19% complete 23% …

常见网络攻击威胁分享

今天我来分享一下比较常见的网络攻击形式&#xff0c; ARP 欺骗攻击、CC 攻击和 DDoS 流量攻击是较为常见且危害巨大的攻击方式。 一、ARP欺骗攻击 ARP&#xff08;AddressResolutionProtocol&#xff0c;地址解析协议&#xff09;是用于将IP地址转换为MAC地址的协议。ARP欺骗…

ActiViz集成到WPF中的空域问题

文章目录 一、场景1、WPF控件2、集成ActiViz或者VTK 二、问题1、需求2、空域问题 三、解决方案1、用WindowsFormsHost包裹住ElementHost&#xff0c;然后将WPF的控件放在ElementHost职中&#xff1a;2、用Window或者Popup去悬浮3、使用第三方库Microsoft.DwayneNeed&#xff08…

springcloud-gateway 路由加载流程

问题 Spring Cloud Gateway版本是2.2.9.RELEASE&#xff0c;原本项目中依赖服务自动发现来自动配置路由到微服务的&#xff0c;但是发现将spring.cloud.gateway.discovery.locator.enabledfalse 启动之后Gateway依然会将所有微服务自动注册到路由中&#xff0c;百思不得其解&a…

NineData和华为云在一起!提供一站式智能数据库DevOps平台

以GuassDB数据库为底座 NineData和华为云一起 为企业提供 一站式智能数据库DevOps平台 帮助开发者 高效、安全地完成 数据库SQL审核 访问控制、敏感数据保护等 日常数据库相关开发任务 NineData 智能数据管理平台 NineData 作为新一代的云原生智能数据管理平台&#xf…