使用 React 實現語音識別并轉換功能

在現代 Web 開發中,語音識別技術的應用越來越廣泛。它為用戶提供了更加便捷、自然的交互方式,例如語音輸入、語音指令等。本文將介紹如何使用 React 實現一個簡單的語音識別并轉換的功能。

功能概述

我們要實現的功能是一個語音識別測試頁面,用戶可以選擇不同的語言,錄制音頻,然后將錄制的音頻轉換為文本。整個過程使用了 React 作為前端框架,RecordRTC?庫用于錄制音頻,以及一個自定義的?CallAsr?函數用于調用語音識別服務。

注意??:CallAsr?函數在博客已有相應的描述:前端 AI 開發實戰:基于自定義工具類的大語言模型與語音識別調用指南_音頻理解類大模型調用-CSDN博客

實現步驟

1.導入必要的模塊

首先,我們需要導入 React 的鉤子?useState?和?useRef,以及?RecordRTC?庫和自定義的?CallAsr?函數和?AsrLanguage?枚舉。

import { useState, useRef } from "react";
import { CallAsr, AsrLanguage } from "../../util/AIUtil";
import RecordRTC from "recordrtc";
  • useState?和?useRef?是 React 的鉤子,useState?用于管理組件的狀態,useRef?用于引用 DOM 元素或在組件重新渲染時保存值。
  • CallAsr?和?AsrLanguage?從?../../util/AIUtil?導入(AI工具類),CallAsr?是用于調用語音識別服務的函數,AsrLanguage?是一個枚舉類型,用于表示支持的語言。
  • RecordRTC?是一個用于錄制音頻和視頻的庫。

2.定義接口?

為了更好地處理語音識別服務的返回數據,我們定義了一個?AsrResponse?接口。

interface AsrResponse {code: number;msg: string;data?: {text_arr: string[];detail_arr?: Array<{text: string;time_from: number;time_end: number;}>;};
}

3.定義組件和狀態管理?

我們創建了一個名為?ASRTest?的函數式組件,并使用?useState?鉤子來管理組件的狀態,例如是否正在錄制、音頻數據、識別結果等。

const ASRTest = () => {const [recording, setRecording] = useState<boolean>(false);const [audioBlob, setAudioBlob] = useState<Blob | null>(null);const [transcription, setTranscription] = useState<string>("");const [loading, setLoading] = useState<boolean>(false);const [selectedLanguage, setSelectedLanguage] = useState<AsrLanguage>(AsrLanguage.ZH_CN);const [error, setError] = useState<string | null>(null);const recorderRef = useRef<RecordRTC | null>(null);// ...
};
  • recording:表示是否正在錄制音頻。
  • audioBlob:存儲錄制的音頻數據。
  • transcription:存儲語音識別的結果。
  • loading:表示是否正在進行語音識別。
  • selectedLanguage:表示用戶選擇的語言。
  • error:存儲可能出現的錯誤信息。
  • recorderRef:用于引用?RecordRTC?實例。

4.處理語言選擇

用戶可以通過下拉框選擇不同的語言,我們使用?handleLanguageChange?函數來處理語言選擇事件。

const handleLanguageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {setSelectedLanguage(e.target.value as AsrLanguage);
};

5. 錄制音頻

用戶可以點擊 “開始錄制” 按鈕開始錄制音頻,點擊 “停止錄制” 按鈕停止錄制。我們使用?navigator.mediaDevices.getUserMedia?方法請求用戶的麥克風權限,并使用?RecordRTC?庫進行音頻錄制。

const startRecording = async () => {try {const stream = await navigator.mediaDevices.getUserMedia({audio: {sampleRate: 16000,echoCancellation: false,noiseSuppression: false,autoGainControl: false,},});const recorder = new RecordRTC(stream, {type: "audio",mimeType: "audio/wav",recorderType: RecordRTC.StereoAudioRecorder,numberOfAudioChannels: 1,desiredSampRate: 16000,disableLogs: true,// @ts-ignoresampleBits: 16,bufferSize: 16384,});recorder.startRecording();recorderRef.current = recorder;setRecording(true);} catch (error) {console.error("獲取麥克風權限失敗:", error);setError("無法訪問麥克風,請確保您已授予麥克風權限。");}
};const stopRecording = () => {if (recorderRef.current && recording) {recorderRef.current.stopRecording(() => {const blob = recorderRef.current!.getBlob();setAudioBlob(blob);// 停止并釋放音頻流const mediaStream =recorderRef.current!.getInternalRecorder().mediaStream;if (mediaStream) {mediaStream.getTracks().forEach((track) => track.stop());}setRecording(false);});}
};

6. 語音識別

用戶可以點擊 “轉換” 按鈕將錄制的音頻轉換為文本。我們使用?CallAsr?函數調用語音識別服務,并根據返回結果更新識別結果或錯誤信息。

const handleTranscribe = async () => {if (!audioBlob) {setError("請先錄制音頻");return;}setLoading(true);setError(null);try {// 創建一個帶有適當后綴名的文件對象const audioFile = new File([audioBlob], "recording.wav", {type: "audio/wav",});const response = await CallAsr(audioFile, selectedLanguage);const result: AsrResponse = await response.json();if (result.code === 0 && result.data) {setTranscription(result.data.text_arr.join(" "));} else {setError(`識別失敗: ${result.msg || "未知錯誤"}`);}} catch (error) {console.error("語音識別錯誤:", error);setError(`識別過程中發生錯誤: ${error instanceof Error ? error.message : String(error)}`);} finally {setLoading(false);}
};

7. 渲染組件

最后,我們將所有的功能組合在一起,渲染出一個包含語言選擇、錄制按鈕、音頻預覽、錯誤信息和識別結果的 UI。

return (<div className="container mx-auto p-4 max-w-2xl"><h1 className="text-2xl font-bold mb-6 text-center">ASR 語音識別測試</h1><div className="mb-4"><labelhtmlFor="language-select"className="block mb-2 text-sm font-medium">選擇語言:</label><selectid="language-select"value={selectedLanguage}onChange={handleLanguageChange}className="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"><option value={AsrLanguage.ZH_CN}>簡體中文</option><option value={AsrLanguage.YUE_CN}>粵語</option><option value={AsrLanguage.EN_US}>美式英語</option><option value={AsrLanguage.EN_UK}>英式英語</option><option value={AsrLanguage.FR}>法語</option><option value={AsrLanguage.JA}>日語</option><option value={AsrLanguage.ES}>西班牙語</option><option value={AsrLanguage.DE}>德語</option></select></div><div className="flex flex-col items-center gap-4 mb-6"><div className="flex gap-4"><buttononClick={recording ? stopRecording : startRecording}className={`px-6 py-2 rounded focus:outline-none focus:ring-2 ${recording? "bg-red-500 hover:bg-red-600 text-white focus:ring-red-500": "bg-blue-500 hover:bg-blue-600 text-white focus:ring-blue-500"}`}>{recording ? "停止錄制" : "開始錄制"}</button><buttononClick={handleTranscribe}disabled={!audioBlob || loading}className={`px-6 py-2 rounded focus:outline-none focus:ring-2 focus:ring-green-500 ${!audioBlob || loading? "bg-gray-300 text-gray-500 cursor-not-allowed": "bg-green-500 hover:bg-green-600 text-white"}`}>{loading ? "轉換中..." : "轉換"}</button></div>{audioBlob && (<div className="w-full mt-4"><p className="text-sm text-gray-600 mb-2">錄音預覽:</p><audio controls className="w-full"><source src={URL.createObjectURL(audioBlob)} type="audio/wav" />您的瀏覽器不支持音頻標簽。</audio></div>)}</div>{loading && (<div className="text-center py-4"><div className="loader">轉換中...</div></div>)}{error && (<div className="mt-4 p-4 bg-red-100 text-red-700 rounded-lg">{error}</div>)}{transcription && (<div className="mt-6 border-t pt-4"><h2 className="font-semibold text-lg mb-2">識別結果:</h2><div className="bg-gray-100 p-4 rounded whitespace-pre-wrap">{transcription}</div></div>)}</div>
);

整體實現效果?

總結

通過以上步驟,我們成功實現了一個簡單的語音識別并轉換的功能。這個功能不僅可以幫助用戶更方便地輸入文本,還可以為 Web 應用增加更多的交互性。在實際應用中,我們可以根據需要對代碼進行擴展,例如添加更多的語言支持、優化音頻錄制的質量等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80601.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80601.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80601.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ 雙峰高斯函數擬合

C 雙峰高斯函數擬合 一維高斯函數二維高斯函數多維高斯函數一維雙峰高斯函數代碼實現 二維雙峰高斯函數代碼實現 多維多峰高斯函數 在數據分析與清洗中經常遇到這樣的數據&#xff1a;數據不僅僅向單個中心靠攏&#xff0c;而是類似分段的向兩個甚至多個中心靠攏。數據向單個中…

【RP2350】香瓜樹莓派RP2350之LED

本文最后修改時間&#xff1a;2025年05月10日 01:57 一、本節簡介 本節以樹莓派pico2開發板為例&#xff0c;舉例如何寫一個LED驅動加進工程里。 二、實驗平臺 1、硬件平臺 1&#xff09;樹莓派pico2開發板 ①樹莓派pico2開發板&#xff08;作為仿真器&#xff09; ②micr…

機器人運動控制原理淺析-UC Berkeley超視覺模態模型

加州伯克利發布的超視覺多感知模態融合(FuSe, Fuse Heterogeneous Sensory Data)模型&#xff0c;基于視覺、觸覺、聽覺、本體及語言等模態&#xff0c;利用自然語言跨模態對齊(Cross-Modal Grounding)優調視覺語言動作等通用模型&#xff0c;提高模型任務成功率。 總體框架 …

【Bootstrap V4系列】學習入門教程之 組件-媒體對象(Media object)

Bootstrap V4系列 學習入門教程之 組件-媒體對象&#xff08;Media object&#xff09; 媒體對象&#xff08;Media object&#xff09;一、Example二、Nesting 嵌套三、Alignment 對齊四、Order 順序五、Media list 媒體列表 媒體對象&#xff08;Media object&#xff09; B…

解決VirtualBox中虛擬機(ubuntu)與主機(windows)之間互相復制粘貼(文本)

一.開始的設置 1.在VirtualBox中打開設置&#xff0c;常規中修改主機與虛擬機交互設置 2.虛擬機關閉狀態下&#xff0c;存儲中選中控制器SATA&#xff0c;勾選‘使用主機輸入輸出’ 3.選中操作系統對應的虛擬文件&#xff0c;.vdi文件&#xff0c;勾選右邊的固態驅動器。 4.啟…

java 多核,多線程,分布式 并發編程的現狀 :從本身的jdk ,到 spring ,到其它第三方。

Java 在多核、多線程和高性能編程領域提供了豐富的現成框架和工具&#xff0c;既有標準庫中的并發組件&#xff0c;也有第三方框架。以下是一些關鍵框架及其應用場景的總結&#xff1a;便于后面我們站在巨人的肩膀上&#xff0c;繼續前行 一、Java 標準庫中的多線程框架 Execut…

Nodejs核心機制

文章目錄 前言 前言 結合 Node.js 的核心機制進行說明&#xff1a; 解釋事件循環的各個階段。 答案 Node.js 事件循環分為 6 個階段&#xff0c;按順序執行&#xff1a; Timers&#xff1a;執行 setTimeout 和 setInterval 的回調。 Pending I/O Callbacks&#xff1a;處理系…

C++筆記6:數字字面量后綴和前綴總結

在C中&#xff0c;可以在數字字面量后面添加字母后綴&#xff08;或前綴&#xff09;來表示特定的數據類型。這些后綴能夠明確指定字面量的類型&#xff0c;避免類型轉換帶來的潛在問題。以下是常見的幾種類型后綴及其含義&#xff1a; 1. 整數后綴 u 或 U&#xff1a;表示 u…

50.輻射抗擾RS和傳導抗擾CS測試環境和干擾特征分析

輻射抗擾RS和傳到抗擾CS測試環境和干擾特征分析 1. 輻射抗擾RS2. 傳導抗擾CS 1. 輻射抗擾RS 輻射抗擾RS考察對外界電磁場干擾得抗擾能力&#xff0c;測試頻段為80MHz~2000MHz&#xff0c;用1KHz得正弦波進行調幅&#xff0c;在電波暗室內進行。測試標準&#xff1a;IEC 61000-…

Java多態詳解

Java多態詳解 什么是多態&#xff1f; 比如我們說&#xff1a;“駕駛一輛車”&#xff0c;有人開的是自行車&#xff0c;有人開的是摩托車&#xff0c;有人開的是汽車。雖然我們都說“開車”&#xff0c;但“怎么開”是由具體的車類型決定的&#xff1a;“開”是統一的動作&a…

問題及解決01-面板無法隨著窗口的放大而放大

在MATLAB的App Designer中&#xff0c;默認情況下&#xff0c;組件的位置是固定的&#xff0c;不會隨著父容器的大小變化而改變。問題圖如下圖所示。 解決&#xff1a; 為了讓Panel面板能夠隨著UIFigure父容器一起縮放&#xff0c;需要使用布局管理器&#xff0c;我利用 MATLA…

【GESP真題解析】第 20 集 GESP 二級 2025 年 3 月編程題 2:時間跨越

大家好,我是莫小特。 這篇文章給大家分享 GESP 二級 2025 年 3 月編程題第 2 題:時間跨越。 題目鏈接 洛谷鏈接:B4260 時間跨越 一、完成輸入 根據題意,輸入包含五行,每行一個正整數,分別代表 y,m,d,h,k。 注意到數據范圍:對于全部數據,保證有 2000≤y≤3000,1≤m≤…

GTS-400 系列運動控制器板卡介紹(二十一)---電子齒輪跟隨

運動控制器函數庫的使用 運動控制器驅動程序、dll 文件、例程、Demo 等相關文件請通過固高科技官網下載,網 址為:www.googoltech.com.cn/pro_view-3.html 1 Windows 系統下動態鏈接庫的使用 在 Windows 系統下使用運動控制器,首先要安裝驅動程序。在安裝前需要提前下載運動…

軟件工程之需求分析涉及的圖與工具

需求分析與規格說明書是一項十分艱巨復雜的工作。用戶與分析員之間需要溝通的內容非常的多&#xff0c;在雙方交流信息的過程中很容易出現誤解或遺漏&#xff0c;也可能存在二義性。如何才能更加準確的表達雙方的意思&#xff0c;且清楚明了&#xff0c;繪制各類圖形就顯得非常…

藍橋杯14屆 數三角

問題描述 小明在二維坐標系中放置了 n 個點&#xff0c;他想在其中選出一個包含三個點的子集&#xff0c;這三個點能組成三角形。然而這樣的方案太多了&#xff0c;他決定只選擇那些可以組成等腰三角形的方案。請幫他計算出一共有多少種選法可以組成等腰三角形&#xff1f; 輸…

在Fiddler中添加自定義HTTP方法列并高亮顯示

在Fiddler中添加自定義HTTP方法列并高亮顯示 Fiddler 是一款強大的 Web 調試代理工具&#xff0c;允許開發者檢查和操作 HTTP 流量。一個常見需求是自定義 Web Sessions 列表&#xff0c;添加顯示 HTTP 方法&#xff08;GET、POST 等&#xff09;的列&#xff0c;并通過顏色區…

數據庫分庫分表實戰指南:從原理到落地

1. 為什么要分庫分表&#xff1f; 1.1 單庫瓶頸表現 存儲瓶頸&#xff1a;單表數據超過5000萬行&#xff0c;查詢性能急劇下降性能瓶頸&#xff1a;單庫QPS超過5000后響應延遲顯著增加可用性風險&#xff1a;單點故障導致全系統不可用 1.2 突破性優勢 --------------------…

Selenium的driver.get_url 和 手動輸入網址, 并點擊的操作,有什么不同?

我在搞爬取的時候&#xff0c;發現有些網站直接用driver.get(url) 跳轉到目標特定的網址的時候&#xff0c;會被強制跳轉到其他的網址上&#xff0c;但是如果是自己手動&#xff0c;在網址欄那里輸入網址&#xff0c;并點回車&#xff0c;卻能完成跳轉。 這是在使用 Selenium …

Java【06】數組查找(二分查找)、排序(冒泡排序、簡單選擇排序)

1. 數組的操作 1.1 數組的反轉 int[] arrs{3,5,7,8,9}; 編寫程序&#xff0c;讓arrs中的數據進行反轉{9,8,7,5,3} 1.2數組的查找 ① 順序查找 從頭到尾一個一個的找&#xff01; ② 二分查找 對數組有一個要求&#xff1a;數組必須是有序(大小)的&#xff01; int num3; int[]…

Redis 基礎詳解:從入門到精通

在當今互聯網應用開發領域&#xff0c;數據存儲與處理的性能和效率至關重要。Redis&#xff08;Remote Dictionary Server&#xff09;作為一款開源的、基于內存的鍵值存儲系統&#xff0c;憑借其出色的性能和豐富的功能&#xff0c;被廣泛應用于數據庫、緩存、消息中間件等場景…