欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React實(shí)現(xiàn)語(yǔ)音識(shí)別并轉(zhuǎn)換功能

 更新時(shí)間:2025年05月13日 10:53:47   作者:打小就很皮...  
在現(xiàn)代 Web 開(kāi)發(fā)中,語(yǔ)音識(shí)別技術(shù)的應(yīng)用越來(lái)越廣泛,本文將介紹如何使用 React 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的語(yǔ)音識(shí)別并轉(zhuǎn)換的功能,有需要的小伙伴可以了解下

在現(xiàn)代 Web 開(kāi)發(fā)中,語(yǔ)音識(shí)別技術(shù)的應(yīng)用越來(lái)越廣泛。它為用戶提供了更加便捷、自然的交互方式,例如語(yǔ)音輸入、語(yǔ)音指令等。本文將介紹如何使用 React 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的語(yǔ)音識(shí)別并轉(zhuǎn)換的功能。

功能概述

我們要實(shí)現(xiàn)的功能是一個(gè)語(yǔ)音識(shí)別測(cè)試頁(yè)面,用戶可以選擇不同的語(yǔ)言,錄制音頻,然后將錄制的音頻轉(zhuǎn)換為文本。整個(gè)過(guò)程使用了 React 作為前端框架,RecordRTC 庫(kù)用于錄制音頻,以及一個(gè)自定義的 CallAsr 函數(shù)用于調(diào)用語(yǔ)音識(shí)別服務(wù)。

注意:CallAsr 函數(shù)在文末有相應(yīng)的知識(shí)補(bǔ)充

實(shí)現(xiàn)步驟

1.導(dǎo)入必要的模塊

首先,我們需要導(dǎo)入 React 的鉤子 useState 和 useRef,以及 RecordRTC 庫(kù)和自定義的 CallAsr 函數(shù)和 AsrLanguage 枚舉。

import { useState, useRef } from "react";
import { CallAsr, AsrLanguage } from "../../util/AIUtil";
import RecordRTC from "recordrtc";

useState 和 useRef 是 React 的鉤子,useState 用于管理組件的狀態(tài),useRef 用于引用 DOM 元素或在組件重新渲染時(shí)保存值。

CallAsr 和 AsrLanguage 從 ../../util/AIUtil 導(dǎo)入(AI工具類),CallAsr 是用于調(diào)用語(yǔ)音識(shí)別服務(wù)的函數(shù),AsrLanguage 是一個(gè)枚舉類型,用于表示支持的語(yǔ)言。
RecordRTC 是一個(gè)用于錄制音頻和視頻的庫(kù)。

2.定義接口 

為了更好地處理語(yǔ)音識(shí)別服務(wù)的返回?cái)?shù)據(jù),我們定義了一個(gè) AsrResponse 接口。

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

3.定義組件和狀態(tài)管理 

我們創(chuàng)建了一個(gè)名為 ASRTest 的函數(shù)式組件,并使用 useState 鉤子來(lái)管理組件的狀態(tài),例如是否正在錄制、音頻數(shù)據(jù)、識(shí)別結(jié)果等。

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:存儲(chǔ)錄制的音頻數(shù)據(jù)。
  • transcription:存儲(chǔ)語(yǔ)音識(shí)別的結(jié)果。
  • loading:表示是否正在進(jìn)行語(yǔ)音識(shí)別。
  • selectedLanguage:表示用戶選擇的語(yǔ)言。
  • error:存儲(chǔ)可能出現(xiàn)的錯(cuò)誤信息。
  • recorderRef:用于引用 RecordRTC 實(shí)例。

4.處理語(yǔ)言選擇

用戶可以通過(guò)下拉框選擇不同的語(yǔ)言,我們使用 handleLanguageChange 函數(shù)來(lái)處理語(yǔ)言選擇事件。

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

5. 錄制音頻

用戶可以點(diǎn)擊 “開(kāi)始錄制” 按鈕開(kāi)始錄制音頻,點(diǎn)擊 “停止錄制” 按鈕停止錄制。我們使用 navigator.mediaDevices.getUserMedia 方法請(qǐng)求用戶的麥克風(fēng)權(quán)限,并使用 RecordRTC 庫(kù)進(jìn)行音頻錄制。

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-ignore
      sampleBits: 16,
      bufferSize: 16384,
    });
 
    recorder.startRecording();
    recorderRef.current = recorder;
    setRecording(true);
  } catch (error) {
    console.error("獲取麥克風(fēng)權(quán)限失敗:", error);
    setError("無(wú)法訪問(wèn)麥克風(fēng),請(qǐng)確保您已授予麥克風(fēng)權(quán)限。");
  }
};
 
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. 語(yǔ)音識(shí)別

用戶可以點(diǎn)擊 “轉(zhuǎn)換” 按鈕將錄制的音頻轉(zhuǎn)換為文本。我們使用 CallAsr 函數(shù)調(diào)用語(yǔ)音識(shí)別服務(wù),并根據(jù)返回結(jié)果更新識(shí)別結(jié)果或錯(cuò)誤信息。

const handleTranscribe = async () => {
  if (!audioBlob) {
    setError("請(qǐng)先錄制音頻");
    return;
  }
 
  setLoading(true);
  setError(null);
  try {
    // 創(chuàng)建一個(gè)帶有適當(dāng)后綴名的文件對(duì)象
    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(`識(shí)別失敗: ${result.msg || "未知錯(cuò)誤"}`);
    }
  } catch (error) {
    console.error("語(yǔ)音識(shí)別錯(cuò)誤:", error);
    setError(
      `識(shí)別過(guò)程中發(fā)生錯(cuò)誤: ${
        error instanceof Error ? error.message : String(error)
      }`
    );
  } finally {
    setLoading(false);
  }
};

7. 渲染組件

最后,我們將所有的功能組合在一起,渲染出一個(gè)包含語(yǔ)言選擇、錄制按鈕、音頻預(yù)覽、錯(cuò)誤信息和識(shí)別結(jié)果的 UI。

return (
  <div className="container mx-auto p-4 max-w-2xl">
    <h1 className="text-2xl font-bold mb-6 text-center">ASR 語(yǔ)音識(shí)別測(cè)試</h1>
 
    <div className="mb-4">
      <label
        htmlFor="language-select"
        className="block mb-2 text-sm font-medium"
      >
        選擇語(yǔ)言:
      </label>
      <select
        id="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}>簡(jiǎn)體中文</option>
        <option value={AsrLanguage.YUE_CN}>粵語(yǔ)</option>
        <option value={AsrLanguage.EN_US}>美式英語(yǔ)</option>
        <option value={AsrLanguage.EN_UK}>英式英語(yǔ)</option>
        <option value={AsrLanguage.FR}>法語(yǔ)</option>
        <option value={AsrLanguage.JA}>日語(yǔ)</option>
        <option value={AsrLanguage.ES}>西班牙語(yǔ)</option>
        <option value={AsrLanguage.DE}>德語(yǔ)</option>
      </select>
    </div>
 
    <div className="flex flex-col items-center gap-4 mb-6">
      <div className="flex gap-4">
        <button
          onClick={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 ? "停止錄制" : "開(kāi)始錄制"}
        </button>
 
        <button
          onClick={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 ? "轉(zhuǎn)換中..." : "轉(zhuǎn)換"}
        </button>
      </div>
 
      {audioBlob && (
        <div className="w-full mt-4">
          <p className="text-sm text-gray-600 mb-2">錄音預(yù)覽:</p>
          <audio controls className="w-full">
            <source src={URL.createObjectURL(audioBlob)} type="audio/wav" />
            您的瀏覽器不支持音頻標(biāo)簽。
          </audio>
        </div>
      )}
    </div>
 
    {loading && (
      <div className="text-center py-4">
        <div className="loader">轉(zhuǎn)換中...</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">識(shí)別結(jié)果:</h2>
        <div className="bg-gray-100 p-4 rounded whitespace-pre-wrap">
          {transcription}
        </div>
      </div>
    )}
  </div>
);

整體實(shí)現(xiàn)效果 

總結(jié)

通過(guò)以上步驟,我們成功實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的語(yǔ)音識(shí)別并轉(zhuǎn)換的功能。這個(gè)功能不僅可以幫助用戶更方便地輸入文本,還可以為 Web 應(yīng)用增加更多的交互性。在實(shí)際應(yīng)用中,我們可以根據(jù)需要對(duì)代碼進(jìn)行擴(kuò)展,例如添加更多的語(yǔ)言支持、優(yōu)化音頻錄制的質(zhì)量等。

知識(shí)補(bǔ)充

語(yǔ)音識(shí)別調(diào)用函數(shù)

export function CallAsr(file: File, language: AsrLanguage = AsrLanguage.ZH_CN) {
  const formData = new FormData();
  formData.append("audio_file", file);
  // 添加認(rèn)證和配置參數(shù)
  return fetch(ASR_BASE_URL, {
    method: "POST",
    body: formData,
  });
}

CallAsr函數(shù)接收音頻文件和識(shí)別語(yǔ)言(默認(rèn)為簡(jiǎn)體中文),通過(guò)FormData封裝文件和請(qǐng)求參數(shù),使用fetch向語(yǔ)音識(shí)別 API 發(fā)起請(qǐng)求,將音頻轉(zhuǎn)換為文字信息。

到此這篇關(guān)于React實(shí)現(xiàn)語(yǔ)音識(shí)別并轉(zhuǎn)換功能的文章就介紹到這了,更多相關(guān)React語(yǔ)音識(shí)別并轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React useEffect的理解與使用

    React useEffect的理解與使用

    useEffect是react v16.8新引入的特性。我們可以把useEffect hook看作是componentDidMount、componentDidUpdate、componentWillUnmounrt三個(gè)函數(shù)的組合
    2022-12-12
  • react中props 的使用及進(jìn)行限制的方法

    react中props 的使用及進(jìn)行限制的方法

    這篇文章主要介紹了react中的props 的使用及進(jìn)行限制的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • 深入了解React中的合成事件

    深入了解React中的合成事件

    React 中的事件,是對(duì)原生事件的封裝,叫做合成事件。這篇文章主要通過(guò)幾個(gè)簡(jiǎn)單的示例為大家詳細(xì)介紹一下React中的合成事件,感興趣的可以了解一下
    2023-02-02
  • 解決React報(bào)錯(cuò)Cannot assign to 'current' because it is a read-only property

    解決React報(bào)錯(cuò)Cannot assign to 'current'

    這篇文章主要為大家介紹了React報(bào)錯(cuò)Cannot assign to 'current' because it is a read-only property的解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React?中使用?RxJS?優(yōu)化數(shù)據(jù)流的處理方案

    React?中使用?RxJS?優(yōu)化數(shù)據(jù)流的處理方案

    這篇文章主要為大家介紹了React?中使用?RxJS?優(yōu)化數(shù)據(jù)流的處理方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • react-router-dom 嵌套路由的實(shí)現(xiàn)

    react-router-dom 嵌套路由的實(shí)現(xiàn)

    這篇文章主要介紹了react-router-dom 嵌套路由的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 三分鐘搞懂react-hooks及實(shí)例代碼

    三分鐘搞懂react-hooks及實(shí)例代碼

    React?Hooks是今年最勁爆的新特性真的毫不夸張。如果你也對(duì)react感興趣,或者正在使用react進(jìn)行項(xiàng)目開(kāi)發(fā),請(qǐng)抽出點(diǎn)時(shí)間閱讀下此文
    2022-03-03
  • React-redux?中useSelector使用源碼分析

    React-redux?中useSelector使用源碼分析

    在一個(gè) action 被分發(fā)(dispatch) 后,useSelector() 默認(rèn)對(duì) select 函數(shù)的返回值進(jìn)行引用比較 ===,并且僅在返回值改變時(shí)觸發(fā)重渲染,,這篇文章主要介紹了React-redux?中useSelector使用,需要的朋友可以參考下
    2023-10-10
  • React快速入門教程

    React快速入門教程

    本文主要介紹了React的相關(guān)知識(shí),具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • React Class組件生命周期及執(zhí)行順序

    React Class組件生命周期及執(zhí)行順序

    這篇文章主要介紹了React Class組件生命周期,包括react組件的兩種定義方式和class組件不同階段生命周期函數(shù)執(zhí)行順序,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08

最新評(píng)論