Post cover

使用 Socket.IO 和 Google Speech API 实现实时语音转录

Author AvatarYuhang
2025年3月1日

最近,需要一个将语音实时转换为文本的功能。在研究了 Socket 和 Google API 之后,动手构建一个简单的应用程序,可以直接通过麦克风进行语音输入,并将声音实时转换为文本显示在网页上,分享一些开发过程中的心得体会。

技术栈

  • 前端: React, Next.js, Socket.IO Client
  • 后端: Node.js, Express, Socket.IO, Google Cloud Speech-to-Text API

项目架构

  1. 客户端(浏览器):
    • 使用 navigator.mediaDevices.getUserMedia 获取用户的麦克风音频流。
    • 使用 MediaRecorder API 将音频流录制成数据块。
    • 通过 Socket.IO 将音频数据块发送到服务器。
  2. 服务器端 (Node.js):
    • 接收来自客户端的音频数据块。
    • 使用 Google Cloud Speech-to-Text API 对音频数据进行实时转录。
    • 通过 Socket.IO 将转录结果发送回客户端。
  3. 客户端(浏览器):
    • 接收来自服务器的转录结果。
    • 将转录结果实时显示在网页上。

代码实现

1. 服务器端 (server.js):

JS
1const path = require('path'); 2const express = require('express'); 3const http = require('http'); 4const socketIo = require('socket.io'); 5const { SpeechClient } = require('@google-cloud/speech'); 6 7const keyFilename = path.join(__dirname, '.', 'gen-lang-client.json'); // Google Cloud API 密钥文件路径 8 9const app = express(); 10const server = http.createServer(app); 11 12const io = socketIo(server, { 13 cors: { 14 origin: "http://localhost:3012", // 允许的前端地址 15 methods: ["GET", "POST"] 16 } 17}); 18 19const speechClient = new SpeechClient({ 20 keyFilename 21}); 22 23const encoding = 'WEBM_OPUS'; 24const sampleRateHertz = 48000; 25const languageCode = 'en-US'; // 可以根据需要修改语言代码 26 27const request = { 28 config: { 29 encoding: encoding, 30 sampleRateHertz: sampleRateHertz, 31 languageCode: languageCode, 32 }, 33 interimResults: true, // 获取中间转录结果 34}; 35 36io.on('connection', (socket) => { 37 console.log('New client connected'); 38 39 const recognizeStream = speechClient.streamingRecognize(request) 40 .on('error', console.error) 41 .on('data', (data) => { 42 if (data.results[0]) { 43 socket.emit('transcription', data.results[0]); 44 } 45 }); 46 47 socket.on('audio-data', (audioChunk) => { 48 recognizeStream.write(audioChunk); 49 }); 50 51 socket.on('disconnect', () => { 52 recognizeStream.end(); 53 console.log('Client disconnected'); 54 }); 55}); 56 57server.listen(4000, () => { 58 console.log('Listening on port 4000'); 59});

2. 客户端 (page.tsx):

JS
1"use client"; 2import React, { useEffect, useRef, useState } from "react"; 3import io from "socket.io-client"; 4 5const AudioRecorder = () => { 6 const [isRecording, setIsRecording] = useState(false); 7 const mediaRecorderRef = useRef(null); 8 const [transcription, setTranscription] = useState(""); 9 const socketRef = useRef(null); 10 11 const connectSocket = () => { 12 socketRef.current = io("http://localhost:4000"); 13 socketRef.current.on("transcription", (data) => { 14 setTranscription(data.alternatives[0].transcript); 15 }); 16 }; 17 18 const disconnectSocket = () => { 19 if (socketRef.current) { 20 socketRef.current.disconnect(); 21 } 22 }; 23 24 useEffect(() => { 25 return disconnectSocket; 26 }, []); 27 28 const startRecording = async () => { 29 connectSocket(); 30 const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); 31 mediaRecorderRef.current = new MediaRecorder(stream, { 32 // 可以根据需要设置音频编码格式 33 }); 34 mediaRecorderRef.current.ondataavailable = (event) => { 35 if (event.data.size > 0) { 36 socketRef.current.emit("audio-data", event.data); 37 } 38 }; 39 mediaRecorderRef.current.start(250); // 每250毫秒发送一次音频数据 40 setIsRecording(true); 41 }; 42 43 const stopRecording = () => { 44 mediaRecorderRef.current.stop(); 45 disconnectSocket(); 46 setIsRecording(false); 47 }; 48 49 return ( 50 <div> 51 <button onClick={isRecording ? stopRecording : startRecording}> 52 {isRecording ? "停止录音" : "开始录音"} 53 </button> 54 <div>{transcription}</div> 55 </div> 56 ); 57}; 58 59export default AudioRecorder;

需要注意的

  1. 确保已经创建了 Google Cloud Platform 帐户并启用了 Speech-to-Text API。
  2. 下载 API 密钥文件并将文件路径更新到 server.js 中的 keyFilename 变量。
  3. 安装项目依赖:
    Bash
    1pnpm install
  4. 启动服务器:
    Bash
    1node server.js
  5. 在浏览器中访问 http://localhost:3012 即可使用应用程序。

参考文档

Google Speech-to-Text API

socket.io

0

Likes

加载评论中...