訊飛語音聽寫(流式版)開發指南

語音交互大模型的功能越來越受到重視。訊飛語音聽寫(流式版)為開發者提供了一種高效、準確的語音識別解決方案。本文將基于 Home.vueiat_xfyun.jssparkChat.js 這三個文檔,詳細闡述訊飛語音聽寫(流式版)的開發邏輯、涉及的代碼,并提供開發說明、文件結構和分析。

開發說明

頁面示例

在這里插入圖片描述

功能概述

訊飛語音聽寫(流式版)允許用戶通過麥克風輸入語音,實時將語音轉換為文字。在本項目中,該功能主要應用于聊天界面,用戶可以通過語音輸入問題,系統將語音轉換為文字后發送給后端進行處理。

環境配置

  • 開發環境:Vue.js 3.x、Vite
  • 依賴庫@muguilin/xf-voice-dictation 用于實現訊飛語音聽寫功能

配置步驟

  1. 安裝依賴:在項目根目錄下執行以下命令安裝 @muguilin/xf-voice-dictation
npm install @muguilin/xf-voice-dictation
  1. 配置訊飛 API 信息:在 iat_xfyun.js 文件中,配置訊飛語音聽寫的 API 信息,包括 APPIDAPIKeyAPISecret
// 訊飛語音識別配置
const xfConfig = {APPID: '6acb09d5',APIKey: '36fb21a7095db0bb***',APISecret: 'MmNhN2VkY2JkMj****',host: 'iat-api.xfyun.cn',path: '/v2/iat'
}

文件結構

主要文件

  • Home.vue:聊天界面組件,包含語音輸入按鈕和語音識別結果顯示區域。
  • iat_xfyun.js:封裝訊飛語音聽寫功能的工具文件,提供創建語音識別實例的工廠函數。
  • sparkChat.js:與后端進行 WebSocket 通信的工具文件,負責將語音識別結果發送給后端。

文件關系

Home.vue 組件引入 iat_xfyun.js 中創建的語音識別實例,當用戶點擊語音輸入按鈕時,調用語音識別實例的 start 方法開始錄音。識別結果通過 onTextChange 回調函數返回,將結果顯示在界面上,并通過 sparkChat.js 發送給后端。

開發邏輯

1. 創建語音識別實例

iat_xfyun.js 文件中,創建一個工廠函數 createVoiceInstance,用于創建語音識別實例。該函數接受一個回調對象作為參數,包含 onStatusChangeonTextChangeonError 三個回調函數。

文件 iat_xfyun.js
import { XfVoiceDictation } from '@muguilin/xf-voice-dictation'// 訊飛語音識別配置
const xfConfig = {APPID: '6acb09d5',APIKey: '36fb21a7095db0bb***',APISecret: 'MmNhN2VkY2JkMj****',host: 'iat-api.xfyun.cn',path: '/v2/iat'
}// 創建語音識別實例的工廠函數
export const createVoiceInstance = (callbacks) => {let instance = new XfVoiceDictation({...xfConfig,    onWillStatusChange: (oldStatus, newStatus) => {console.log('語音識別狀態變更:', { oldStatus, newStatus })          },onTextChange: (text) => {    console.log('語音識別結果:', {text: text,textLength: text ? text.length : 0 })callbacks.onTextChange?.(text)},onError: (error) => {console.error('語音識別錯誤:', error)callbacks.onError?.(error)}})return instance
}

2. 在 Home.vue 中使用語音識別實例

Home.vue 組件中,引入 createVoiceInstance 函數,創建語音識別實例,并綁定到語音輸入按鈕的點擊事件上。

 
<template><!-- ... 其他代碼 ... --><div class="input-bar"><input v-model="inputMessage" type="text" class="apple-input" placeholder="輸入咨詢內容(如:居住證續簽)"@keypress.enter="sendInputMessage(false)" autocapitalize="none" autocomplete="off" spellcheck="false"><svg class="input-icon" :class="{ 'recording': isRecording }" viewBox="0 0 24 24" aria-label="語音麥圖標"@mousedown="checkLoginBeforeAction(startRecording)" @mouseup="checkLoginBeforeAction(stopBtnRecording)"><pathd="M12 15c1.65 0 3-1.35 3-3V6c0-1.65-1.35-3-3-3S9 4.35 9 6v6c0 1.65 1.35 3 3 3zm5.91-4.56c.08.33.13.67.13 1.01 0 2.49-2.01 4.5-4.5 4.5H13v2.5h2c.55 0 1 .45 1 1s-.45 1-1 1H8c-.55 0-1-.45-1-1s.45-1 1-1h2V16H9.59c-2.49 0-4.5-2.01-4.5-4.5 0-.34.05-.68.13-1.01A2.999 2.999 0 0 1 3 9c0-1.66 1.34-3 3-3h3V4c0-.55.45-1 1-1s1 .45 1 1v2h3c1.66 0 3 1.34 3 3 0 1.28-.81 2.36-1.9 2.73l.01-.17z" /></svg><div v-show="isRecording" class="recording-tip">正在錄音...<span class="recording-dots"></span></div><svg class="input-icon sendTxtMsg" viewBox="0 0 24 24" aria-label="發送圖標"   @click="sendInputMessage(true)"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" /></svg></div><!-- ... 其他代碼 ... -->
</template><script setup>
import { ref, onBeforeUnmount } from 'vue'
import { createVoiceInstance } from '../utils/voice/iat_xfyun'
import { ElMessage } from 'element-plus'const isRecording = ref(false)
const recognizedText = ref('')
let times = null// 創建語音識別實例
const xfVoice = createVoiceInstance({onTextChange: (text) => {if (text && text.length > 0) {const currentTime = Date.now();// 防止操作過于頻繁if (currentTime - lastCallTime.value < 3000) {//只要無這段代碼message.value.push()會加入一條除了本身語言以外只多了問號或一個點的消息//如:你好 //message數組內會有兩條消息://1.你好//2.你好?//如果有這段代碼,message數組內只會有一條消息:console.log('操作過于頻繁,請等待10秒后再試');                 return;}lastCallTime.value = currentTime;clearTimeout(times);             xfVoice.stop();// 發送識別結果到服務器inputMessage.value = text;user_message.value = text;  tmpMsgArr.value = [];sendInputMessage(true);}},onError: (error) => {if (error.includes('WebSocket')) {ElMessage.error('語音識別連接失敗,請檢查網絡');} else if (error.includes('authorization')) {ElMessage.error('語音識別授權失敗,請檢查配置');} else {ElMessage.error('語音識別發生錯誤:' + error);}isRecording.value = false;}
});const startRecording = () => {if (!isRecording.value) {recognizedText.value = '';xfVoice.start();isRecording.value = true;}
}const stopBtnRecording = () => {isRecording.value = false;xfVoice.stop();
}onBeforeUnmount(() => {clearTimeout(times);if (isRecording.value) {xfVoice.stop();}
});
</script>

3. 處理語音識別結果

onTextChange 回調函數中,處理語音識別結果。當識別到有效文本時,停止錄音,并將識別結果發送給后端。

4. 錯誤處理

onError 回調函數中,處理語音識別過程中可能出現的錯誤,如網絡連接失敗、授權失敗等,并通過 ElMessage 提示用戶。

代碼分析

iat_xfyun.js

  • 優點:將訊飛語音聽寫功能封裝在一個獨立的文件中,提高了代碼的可維護性和可復用性。
  • 缺點:配置信息硬編碼在文件中,不利于配置的修改和管理。可以考慮將配置信息提取到環境變量中。

Home.vue

  • 優點:在組件中使用語音識別實例,實現了語音輸入功能的集成。通過回調函數處理識別結果和錯誤,代碼結構清晰。
  • 缺點:語音輸入按鈕的樣式和交互邏輯可以進一步優化,提高用戶體驗。

sparkChat.js

// 訊飛星火大模型WebSocket通信模塊
import axios from 'axios'
import getSparkConfig from '../sparkConfig'class SparkChatService {constructor(callbacks) {this.websocket = nullthis.isReconnecting = falsethis.reconnectAttempts = 0this.MAX_RECONNECT_ATTEMPTS = 3this.RECONNECT_INTERVAL = 2000// 獲取配置const sparkConfig = getSparkConfig()this.APPID = sparkConfig.APPIDthis.APISecret = sparkConfig.APISecretthis.APIKey = sparkConfig.APIKeythis.host = sparkConfig.hostthis.path = sparkConfig.paththis.sparkBaseUrl = sparkConfig.getWebSocketUrl()// 回調函數this.callbacks = callbacks || {}}// 生成鑒權URL所需的日期getAuthorizationDate() {return new Date().toUTCString()}// 生成鑒權URLasync getAuthUrl() {const date = this.getAuthorizationDate()const tmp = `host: ${this.host}\ndate: ${date}\nGET ${this.path} HTTP/1.1`const encoder = new TextEncoder()const key = await window.crypto.subtle.importKey('raw',encoder.encode(this.APISecret),{ name: 'HMAC', hash: 'SHA-256' },false,['sign'])const signature = await window.crypto.subtle.sign('HMAC',key,encoder.encode(tmp))const signatureBase64 = btoa(String.fromCharCode(...new Uint8Array(signature)))const authorization_origin = `api_key="${this.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signatureBase64}"`const authorization = btoa(authorization_origin)return `${this.sparkBaseUrl}?authorization=${encodeURIComponent(authorization)}&date=${encodeURIComponent(date)}&host=${encodeURIComponent(this.host)}`}// 檢查WebSocket連接狀態checkWebSocketConnection() {return this.websocket && this.websocket.readyState === WebSocket.OPEN}// 重連WebSocketasync reconnectWebSocket() {if (this.isReconnecting || this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) returnthis.isReconnecting = truethis.reconnectAttempts++console.log(`嘗試重新連接WebSocket (第${this.reconnectAttempts}次)...`)try {await this.connect()this.isReconnecting = falsethis.reconnectAttempts = 0console.log('WebSocket重連成功')} catch (error) {console.error('WebSocket重連失敗:', error)this.isReconnecting = falseif (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {setTimeout(() => this.reconnectWebSocket(), this.RECONNECT_INTERVAL)} else {console.error('WebSocket重連次數達到上限')this.callbacks.onError?.('網絡連接異常,請刷新頁面重試')}}}// 建立WebSocket連接async connect() {try {const url = await this.getAuthUrl()this.websocket = new WebSocket(url)this.websocket.onopen = () => {console.log('WebSocket連接已建立')this.isReconnecting = falsethis.reconnectAttempts = 0this.callbacks.onOpen?.()}this.websocket.onmessage = (event) => {const response = JSON.parse(event.data)if (response.header.code === 0) {if (response.payload.choices.text[0].content) {const content = response.payload.choices.text[0].content.replace(/\r?\n/g, '')this.callbacks.onMessage?.(content)}if (response.header.status === 2) {this.callbacks.onComplete?.()}} else {this.callbacks.onError?.(`抱歉,發生錯誤:${response.header.message}`)}}this.websocket.onerror = (error) => {console.error('WebSocket錯誤:', error)if (!this.isReconnecting) {this.reconnectWebSocket()}this.callbacks.onError?.(error)}this.websocket.onclose = () => {console.log('WebSocket連接已關閉')if (!this.isReconnecting) {this.reconnectWebSocket()}this.callbacks.onClose?.()}} catch (error) {console.error('連接WebSocket失敗:', error)throw error}}// 發送消息async sendMessage(message) {if (!this.checkWebSocketConnection()) {try {await this.reconnectWebSocket()} catch (error) {console.error('重連失敗,無法發送消息')throw new Error('網絡連接異常,請稍后重試')}}const requestData = {header: {app_id: this.APPID,uid: 'user1'},parameter: {chat: {domain: 'generalv3',temperature: 0.5,max_tokens: 4096}},payload: {message: {text: [{ role: 'user', content: message }]}}}try {this.websocket.send(JSON.stringify(requestData))} catch (error) {console.error('發送消息失敗:', error)throw new Error('發送消息失敗,請重試')}}// 關閉連接close() {if (this.websocket) {this.websocket.close()}}
}export default SparkChatService

雖然該文件主要負責與后端進行 WebSocket 通信,但在語音聽寫功能中起到了將識別結果發送給后端的重要作用。可以考慮對該文件進行進一步的封裝,提高代碼的可維護性。

AIChat

語音聽寫(流式版)WebAPI 文檔幫助文檔:

https://www.xfyun.cn/doc/asr/voicedictation/API.html#%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E
缺點:

語音聽寫流式接口,用于1分鐘內的即時語音轉文字技術,支持實時返回識別結果,達到一邊上傳音頻一邊獲得識別文本的效果。
整個會話時長最多持續60s,或者超過10s未發送數據,服務端會主動斷開連接

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

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

相關文章

基于kotlin native的C與kotlin互相調用

本文測試環境為ubuntu&#xff0c;沒有使用IDE&#xff1b;從基本層面了解kotlin native環境中&#xff0c;C和kotlin的編譯&#xff0c;互相調用。 1. kotlin 動態庫 1.1 動態庫編譯 源碼文件libktest.kt&#xff1a; //file name:libktest.kt OptIn(kotlin.experimental.…

【教學類-102-02】自制剪紙圖案(留白邊、沿線剪)02——Python+PS自動化添加虛線邊框

背景需求: 01版本實現了對透明背景png圖案邊界線的擴展,黑線實線描邊 【教學類-102-01】自制剪紙圖案(留白邊、沿線剪)01-CSDN博客文章瀏覽閱讀974次,點贊15次,收藏7次。【教學類-102-01】自制剪紙圖案(留白邊、沿線剪)01https://blog.csdn.net/reasonsummer/article…

Python-函數參數

1. 參數基礎 函數參數是向函數傳遞數據的主要方式&#xff0c;Python 提供了多種參數傳遞機制。 基本用法 def greet(name): # name 是形式參數print(f"Hello, {name}!")greet("Alice") # "Alice" 是實際參數使用場景&#xff1a;當函數需要…

《在 Ubuntu 22.04 上安裝 CUDA 11.8 和 Anaconda,并配置環境變量》

安裝 CUDA 11.8 和 Anaconda 并配置環境變量 在本教程中&#xff0c;我們將介紹如何在 Ubuntu 22.04 上安裝 CUDA 11.8 和 Anaconda&#xff0c;并配置相應的環境變量。我們還將配置使用 阿里云鏡像源 來加速軟件包更新。以下是具體步驟。 步驟 1&#xff1a;更新軟件源 首先…

Ubuntu環境基于Ollama部署DeepSeek+Open-Webui實現本地部署大模型-無腦部署

Ollama介紹 Ollama是一款簡單好用的模型部署工具,不僅可以部署DeepSeek,市面上開源模型大部分都可以一鍵部署,這里以DeepSeek為例 官網 DeepSeek 版本硬件要求 安裝Ollama 環境 sudo apt update sudo apt install curl sudo apt install lsof1.命令一鍵安裝 在官網點擊…

Angular 項目 PDF 批注插件庫在線版 API 示例教程

本文章介紹 Angular 項目中 PDF 批注插件庫 ElasticPDF 在線版 API 示例教程&#xff0c;API 包含 ① 導出批注后PDF數據&#xff1b;② 導出純批注 json 數據&#xff1b;③ 加載舊批注&#xff1b;④ 切換文檔&#xff1b;⑤ 切換用戶&#xff1b;⑥ 清空批注 等數據處理功能…

Spring Boot 中利用 Jasypt 實現數據庫字段的透明加密解密

1. 引言 1.1 什么是 Jasypt Jasypt(Java Simplified Encryption)是一個用于簡化 Java 應用程序中加密操作的庫。 1.2 為什么使用 Jasypt 簡化加密操作:提供簡單的 API 進行加密和解密。透明加密:自動處理加密和解密過程,無需手動干預。多種加密算法:支持多種加密算法,…

Linux的: /proc/sys/net/ipv6/conf/ 筆記250405

Linux的: /proc/sys/net/ipv6/conf/ /proc/sys/net/ipv6/conf/ 是 Linux 系統中用于 動態配置 IPv6 網絡接口參數 的核心目錄。它允許針對不同網絡接口&#xff08;如 eth0、wlan0&#xff09;或全局設置&#xff08;all&#xff09;調整 IPv6 協議棧的行為。 它通過虛擬文件系…

Spring Cloud 框架為什么能處理高并發

Spring Cloud框架能夠有效處理高并發場景&#xff0c;核心在于其微服務架構設計及多組件的協同作用&#xff0c;具體機制如下&#xff1a; 一、分布式架構設計支撐高擴展性 服務拆分與集群部署 Spring Cloud通過微服務拆分將單體系統解耦為獨立子服務&#xff0c;每個服務可獨…

無人機智慧路燈桿:智慧城市的‘全能助手’

在城市發展的進程中&#xff0c;智慧路燈桿作為智慧城市建設的關鍵載體&#xff0c;正逐步從傳統的照明設備轉型為集多種功能于一體的智能基礎設施。無人機與智慧路燈桿的創新性融合&#xff0c;為城市管理和服務帶來了全新的變革與機遇。 一、無人機智慧路燈桿的功能概述 照…

Libevent UDP開發指南

UDP 與 TCP 的核心區別 無連接:不需要建立/維護連接 不可靠:不保證數據包順序和到達 高效:頭部開銷小,沒有連接管理負擔 支持廣播/多播:可以向多個目標同時發送數據 一、基礎UDP服務器實現 1. 創建 UDP 套接字 #include <event2/event.h> #include <event2/lis…

基于阿里云可觀測產品構建企業級告警體系的通用路徑與最佳實踐

前言 1.1 日常生活中的告警 任何連續穩定運行的生產系統都離不開有效的監控與報警機制。通過監控&#xff0c;我們可以實時掌握系統和業務的運行狀態&#xff1b;而報警則幫助我們及時發現并響應監控指標及業務中的異常情況。 在日常生活中&#xff0c;我們也經常遇到各種各樣…

智能多媒體處理流水線——基于虎躍辦公API的自動化解決方案

在內容爆炸的時代&#xff0c;多媒體文件處理&#xff08;圖片壓縮、視頻轉碼、音頻降噪&#xff09;已成為內容生產者的日常挑戰。本文將演示如何基于虎躍辦公的多媒體處理API&#xff0c;構建自動化處理流水線&#xff0c;實現&#xff1a; 批量文件智能分類格式自動轉換質量…

01-STM32(介紹、工具準備、新建工程)p1-4

文章目錄 工具準備和介紹硬件設備stm32簡介和arm簡介stm32簡介STM32命名規則STM32選型STM32F103C8T6最小系統板引腳定義STM32啟動配置STM32最小系統電路ARM簡介 軟件安裝注冊器件支持包安裝ST-LINK驅動安裝USB轉串口驅動 新建工程創建stm32工程STM32工程編譯和下載型號分類及縮…

【ABAP】REST/HTTP技術(一)

1、概念 1.1、SAP 如何提供 Http Service 如果要將 SAP 應用程序服務器 &#xff08;application server&#xff09;作為 http 服務提供者&#xff0c;需要定義一個類&#xff0c;這個類必須實現 IF_HTTP_EXTENSION 接口。IF_HTTP_EXTENSION 接口只有一個方法 HANDLE_REQUEST。…

[實戰] linux驅動框架與驅動開發實戰

linux驅動框架與驅動開發實戰 Linux驅動框架與驅動開發實戰一、Linux驅動框架概述1.1 Linux驅動的分類1.2 Linux驅動的基本框架 二、Linux驅動關鍵API詳解2.1 模塊相關API2.2 字符設備驅動API2.3 內存管理API2.4 中斷處理API2.5 PCI設備驅動API 三、Xilinx XDMA驅動開發詳解3.1…

1. hadoop 集群的常用命令

1.上傳文件 1)hadoop fs -put words.txt /path/to/input/ 2)hdfs dfs -put words.txt /path/wc/input/ 2.獲取hdfs中的文件 hadoop fs -get /path/wc/input/words.txt 3.合并下載多個文件 hadoop fs -getmerge /path/wc/input/words.txt /path/wc/input/words2.txt 4.查…

Keepalived+LVS+nginx高可用架構

注明&#xff1a;所有軟件已經下載好&#xff0c;防火墻和SELinux已經全部關閉 一.搭建NFS 1.服務端 1.創建文件 [rootnfs ~]# mkdir -p /nfs/data 2、修改權限 [rootnfs ~]# chmod orw /nfs/data 3、寫配置文件 [rootnfs ~]# cat /etc/exports /nfs/data 192.168.111.118(r…

深度學習處理文本(13)

我們使用基于GRU的編碼器和解碼器來在Keras中實現這一方法。選擇GRU而不是LSTM&#xff0c;會讓事情變得簡單一些&#xff0c;因為GRU只有一個狀態向量&#xff0c;而LSTM有多個狀態向量。首先是編碼器&#xff0c;如代碼清單11-28所示。 代碼清單11-28 基于GRU的編碼器 fro…

HashMap 底層原理詳解

1. 核心數據結構 JDK 1.7 及之前&#xff1a;數組 鏈表 JDK 1.8 及之后&#xff1a;數組 鏈表/紅黑樹&#xff08;鏈表長度 ≥8 時轉紅黑樹&#xff0c;≤6 時退化為鏈表&#xff09; // JDK 1.8 的 Node 定義&#xff08;鏈表節點&#xff09; static class Node<K,V&g…