WhisperLiveKit移动应用集成:React Native中实现实时语音识别

WhisperLiveKit移动应用集成:React Native中实现实时语音识别

【免费下载链接】WhisperLiveKit Real-time, Fully Local Speech-to-Text and Speaker Diarization. FastAPI Server & Web Interface 【免费下载链接】WhisperLiveKit 项目地址: https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit

你是否在开发移动应用时遇到过实时语音识别延迟高、依赖云端服务导致隐私问题等痛点?本文将详细介绍如何在React Native应用中集成WhisperLiveKit,实现全本地化的实时语音识别功能,无需依赖云端服务,保护用户隐私的同时确保低延迟响应。读完本文,你将能够掌握从服务端部署到客户端集成的完整流程,轻松实现移动应用中的实时语音转文字功能。

WhisperLiveKit简介

WhisperLiveKit是一个开源项目,提供实时、全本地化的语音转文字(Speech-to-Text)和说话人分离(Speaker Diarization)功能。它包含一个FastAPI服务器和Web界面,支持多种模型和语言,可在本地环境高效运行。

WhisperLiveKit的核心功能包括:

  • 实时语音识别:将音频流实时转换为文字
  • 说话人分离:区分不同说话人
  • 多语言支持:支持多种语言的识别和翻译
  • 全本地化部署:无需依赖云端服务,保护用户隐私

项目的核心模块结构如下:

准备工作

在开始集成前,需要完成以下准备工作:

1. 部署WhisperLiveKit服务器

首先,需要在本地或服务器上部署WhisperLiveKit服务。可以通过以下步骤进行部署:

# 克隆仓库
git clone https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit.git
cd WhisperLiveKit

# 安装依赖
pip install -r requirements.txt

# 启动服务器
python -m whisperlivekit.basic_server --model_size small --host 0.0.0.0 --port 8000

上述命令将启动一个使用"small"模型的服务器,监听所有网络接口的8000端口。可以根据需要调整模型大小和端口号。

2. React Native项目设置

确保你的React Native项目已正确设置。如果还没有项目,可以通过以下命令创建:

npx react-native init WhisperLiveKitDemo
cd WhisperLiveKitDemo

安装必要的依赖:

# 安装WebSocket客户端
npm install react-native-websocket

# 安装音频录制库
npm install react-native-audio-recorder-player

# 安装权限管理库
npm install react-native-permissions

实现音频录制与WebSocket通信

1. 音频录制模块

使用react-native-audio-recorder-player库实现音频录制功能。创建一个AudioRecorder.js组件:

import React, { useState, useEffect } from 'react';
import { View, Button, Text } from 'react-native';
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
import Permissions from 'react-native-permissions';

const audioRecorderPlayer = new AudioRecorderPlayer();

const AudioRecorder = ({ onAudioData }) => {
  const [isRecording, setIsRecording] = useState(false);
  const [recordSecs, setRecordSecs] = useState(0);
  
  useEffect(() => {
    // 请求录音权限
    Permissions.request('microphone').then(result => {
      if (result !== 'granted') {
        alert('需要麦克风权限才能使用语音识别功能');
      }
    });
  }, []);
  
  const startRecording = async () => {
    try {
      const audioSessionId = await audioRecorderPlayer.startRecorder({
        sampleRate: 16000,
        channels: 1,
        bitsPerSample: 16,
        audioSource: 6, // 麦克风
        wavFileCreatedCallback: (path) => {
          console.log('音频文件路径: ', path);
        }
      });
      
      setIsRecording(true);
      
      // 监听录音数据
      audioRecorderPlayer.addRecordBackListener((e) => {
        setRecordSecs(e.currentPosition);
        // 将PCM数据传递给父组件
        onAudioData(e.rawData);
      });
    } catch (error) {
      console.error('开始录音失败: ', error);
    }
  };
  
  const stopRecording = async () => {
    try {
      const result = await audioRecorderPlayer.stopRecorder();
      audioRecorderPlayer.removeRecordBackListener();
      setIsRecording(false);
      setRecordSecs(0);
    } catch (error) {
      console.error('停止录音失败: ', error);
    }
  };
  
  return (
    <View style={{ margin: 10 }}>
      <Button 
        title={isRecording ? "停止录音" : "开始录音"} 
        onPress={isRecording ? stopRecording : startRecording} 
      />
      <Text>录音时长: {Math.floor(recordSecs / 60)}:{(recordSecs % 60).toString().padStart(2, '0')}</Text>
    </View>
  );
};

export default AudioRecorder;

2. WebSocket客户端实现

创建一个WhisperClient.js组件,负责与WhisperLiveKit服务器建立WebSocket连接并发送音频数据:

import React, { useState, useEffect, useRef } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import WebSocket from 'react-native-websocket';
import AudioRecorder from './AudioRecorder';

const WhisperClient = () => {
  const [transcripts, setTranscripts] = useState([]);
  const [isConnected, setIsConnected] = useState(false);
  const ws = useRef(null);
  
  // 连接WebSocket服务器
  useEffect(() => {
    ws.current = new WebSocket('ws://your-server-ip:8000/asr');
    
    ws.current.onopen = () => {
      console.log('WebSocket连接已建立');
      setIsConnected(true);
    };
    
    ws.current.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        handleTranscriptUpdate(data);
      } catch (error) {
        console.error('解析WebSocket消息失败: ', error);
      }
    };
    
    ws.current.onerror = (error) => {
      console.error('WebSocket错误: ', error);
    };
    
    ws.current.onclose = () => {
      console.log('WebSocket连接已关闭');
      setIsConnected(false);
    };
    
    return () => {
      if (ws.current) {
        ws.current.close();
      }
    };
  }, []);
  
  // 处理转录结果更新
  const handleTranscriptUpdate = (data) => {
    console.log('转录结果: ', data);
    
    if (data.type === 'transcript_update' && data.segments) {
      setTranscripts(prev => {
        // 合并新的转录结果
        const updatedTranscripts = [...prev];
        
        data.segments.forEach(segment => {
          const index = updatedTranscripts.findIndex(item => item.id === segment.id);
          
          if (index >= 0) {
            // 更新现有片段
            updatedTranscripts[index] = {
              ...updatedTranscripts[index],
              ...segment
            };
          } else {
            // 添加新片段
            updatedTranscripts.push(segment);
          }
        });
        
        return updatedTranscripts;
      });
    }
  };
  
  // 发送音频数据到服务器
  const sendAudioData = (rawData) => {
    if (isConnected && ws.current) {
      try {
        // 将原始PCM数据转换为ArrayBuffer
        const buffer = new ArrayBuffer(rawData.length);
        const view = new Uint8Array(buffer);
        for (let i = 0; i < rawData.length; i++) {
          view[i] = rawData.charCodeAt(i);
        }
        
        // 发送二进制数据
        ws.current.send(buffer);
      } catch (error) {
        console.error('发送音频数据失败: ', error);
      }
    }
  };
  
  // 渲染转录文本
  const renderTranscript = ({ item }) => (
    <View style={styles.transcriptItem}>
      <Text style={styles.speaker}>说话人 {item.speaker}:</Text>
      <Text style={styles.text}>{item.text}</Text>
      {item.buffer?.transcription && (
        <Text style={styles.bufferText}>{item.buffer.transcription}</Text>
      )}
    </View>
  );
  
  return (
    <View style={styles.container}>
      <Text style={styles.status}>
        连接状态: {isConnected ? "已连接" : "未连接"}
      </Text>
      
      <AudioRecorder onAudioData={sendAudioData} />
      
      <View style={styles.transcriptContainer}>
        <Text style={styles.title}>转录结果:</Text>
        <FlatList
          data={transcripts}
          renderItem={renderTranscript}
          keyExtractor={item => item.id.toString()}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
  },
  status: {
    fontSize: 16,
    marginBottom: 10,
    color: '#333',
  },
  transcriptContainer: {
    flex: 1,
    marginTop: 10,
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  transcriptItem: {
    marginBottom: 15,
    padding: 10,
    backgroundColor: '#f5f5f5',
    borderRadius: 5,
  },
  speaker: {
    fontWeight: 'bold',
    color: '#0066cc',
    marginBottom: 5,
  },
  text: {
    fontSize: 16,
    color: '#333',
  },
  bufferText: {
    fontSize: 16,
    color: '#666',
    fontStyle: 'italic',
  },
});

export default WhisperClient;

3. 主应用组件

App.js中使用WhisperClient组件:

import React from 'react';
import { SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import WhisperClient from './WhisperClient';

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <StatusBar barStyle="dark-content" />
      <WhisperClient />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
});

export default App;

数据流程与优化

数据流程

WhisperLiveKit的实时语音识别流程如下:

  1. React Native应用通过麦克风录制音频,获取PCM格式的音频数据。
  2. 音频数据通过WebSocket实时发送到WhisperLiveKit服务器。
  3. 服务器端的whisperlivekit/audio_processor.py处理音频流:
    • 使用VAD(语音活动检测)检测语音片段
    • 将音频片段传递给ASR处理器
    • 进行说话人分离(如果启用)
    • 生成转录结果
  4. 转录结果通过WebSocket实时返回给客户端。
  5. 客户端渲染转录结果,包括已确认的文本和临时缓冲文本。

优化建议

为了提高实时性和用户体验,可以考虑以下优化措施:

  1. 音频数据压缩:在发送音频数据前进行压缩,减少网络传输带宽。
  2. 批量发送:不要每次获取到音频数据就立即发送,可以积累一定量后批量发送,减少WebSocket通信次数。
  3. 调整模型大小:根据设备性能选择合适的模型大小,平衡识别 accuracy 和速度。
  4. 本地预处理:在客户端进行简单的音频预处理,如降噪、音量归一化等。
  5. 连接状态管理:实现WebSocket连接的自动重连机制,提高稳定性。

常见问题与解决方案

1. 音频格式不兼容

问题:客户端发送的音频格式与服务器要求的格式不匹配,导致识别失败。

解决方案:确保客户端发送的音频格式符合服务器要求:

  • 采样率:16000 Hz
  • 位深:16位
  • 声道:单声道
  • 格式:PCM

2. 实时性差,延迟高

问题:转录结果延迟较高,影响用户体验。

解决方案

  • 使用更小的模型,如"tiny"或"base"模型
  • 调整服务器参数,减少音频缓冲
  • 优化网络连接,确保低延迟传输
  • whisperlivekit/core.py中调整min_chunk_size参数,减小音频块大小

3. 耗电问题

问题:持续录音和网络传输导致设备耗电过快。

解决方案

  • 实现语音活动检测,只在检测到语音时发送数据
  • 优化录音采样率和数据传输频率
  • 在应用后台时降低采样率或暂停录音

总结

本文详细介绍了如何在React Native应用中集成WhisperLiveKit实现实时语音识别功能。通过部署本地WhisperLiveKit服务器,并使用WebSocket与React Native客户端通信,可以实现全本地化的实时语音转文字功能,保护用户隐私的同时确保低延迟响应。

主要步骤包括:

  1. 部署WhisperLiveKit服务器
  2. 创建React Native项目并安装必要依赖
  3. 实现音频录制模块,捕获麦克风音频数据
  4. 通过WebSocket与服务器建立连接,发送音频数据
  5. 处理服务器返回的转录结果,实时更新UI

通过本文介绍的方法,你可以在移动应用中轻松集成高性能的实时语音识别功能,为用户提供更加自然和便捷的交互体验。

如果你想进一步扩展功能,可以考虑:

  • 添加多语言支持,参考docs/supported_languages.md
  • 实现离线语音识别,将模型部署到移动设备本地
  • 优化UI,添加实时语音可视化效果

希望本文对你有所帮助,祝你开发顺利!

【免费下载链接】WhisperLiveKit Real-time, Fully Local Speech-to-Text and Speaker Diarization. FastAPI Server & Web Interface 【免费下载链接】WhisperLiveKit 项目地址: https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值