You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加速Google Cloud Speech转写?流式API使用求助

实现Google Cloud Speech流式转写的完整指南

我来帮你一步步搞定这个流式语音转写的提速问题——之前我做过类似的实现,刚好能解决你的几个核心疑问:浏览器端的流式捕获、JS到Java服务器的可靠流传输,以及Java端对接Google Cloud Speech的流式API。

一、浏览器端:捕获并流式发送音频到Java服务器

首先澄清:浏览器端没有直接暴露Google Cloud Speech的流式JS API(主要是为了避免API密钥泄露),但我们可以用原生的MediaRecorder API捕获麦克风流,再通过WebSocket实现低延迟的流式传输,完全不会破坏音频数据:

  1. 捕获麦克风流并配置传输

    async function startRecording() {
      // 获取麦克风权限并捕获流,强制指定16kHz单声道(匹配Speech API要求)
      const stream = await navigator.mediaDevices.getUserMedia({ 
        audio: { sampleRate: 16000, channelCount: 1 } 
      });
      // 配置MediaRecorder为Google Speech兼容的格式:16kHz单声道,Opus编码
      const mediaRecorder = new MediaRecorder(stream, {
        mimeType: 'audio/webm;codecs=opus',
        audioBitsPerSecond: 16000
      });
    
      // 建立WebSocket连接到Java服务器的流式接口
      const socket = new WebSocket('ws://your-java-server-domain:8080/speech-stream');
    
      // 每300ms发送一次音频块(可根据延迟需求调整,200-500ms是平衡延迟和请求量的区间)
      mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0 && socket.readyState === WebSocket.OPEN) {
          socket.send(event.data);
        }
      };
    
      // 录音结束时发送明确的结束标记
      mediaRecorder.onstop = () => {
        if (socket.readyState === WebSocket.OPEN) {
          socket.send(JSON.stringify({ type: 'RECORDING_END' }));
        }
        socket.close();
      };
    
      // 开始录音
      mediaRecorder.start(300);
      return { mediaRecorder, socket };
    }
    

    用WebSocket的原因是它天生支持双向实时流,比HTTP Chunked更适合这种场景,而且能轻松传递结束信号。

  2. 实时接收转写结果
    要实现类似官方Demo的实时更新,监听WebSocket的消息即可:

    // 在startRecording函数里添加
    socket.onmessage = (event) => {
      const transcript = event.data;
      // 更新页面上的转写区域
      document.getElementById('live-transcript').textContent = transcript;
    };
    

二、Java服务器:接收流并调用Google Cloud Speech的streamingRecognize

Java端的核心是用Google Cloud Speech的SDK处理流式请求,同时通过WebSocket接收浏览器的音频块:

  1. 添加依赖
    确保Maven的pom.xml里包含最新版的Speech SDK:

    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-speech</artifactId>
      <version>2.32.0</version> <!-- 替换为最新版本 -->
    </dependency>
    
  2. WebSocket端点实现
    这里用Spring Boot的WebSocket示例(也可以用Java EE标准的WebSocket API):

    @Component
    @ServerEndpoint("/speech-stream")
    public class SpeechStreamingEndpoint {
    
      private SpeechClient speechClient;
      private StreamObserver<StreamingRecognizeRequest> requestObserver;
    
      @OnOpen
      public void onOpen(Session session) throws IOException {
        // 初始化Speech客户端
        speechClient = SpeechClient.create();
        // 配置识别参数:和浏览器端的音频格式完全匹配
        RecognitionConfig config = RecognitionConfig.newBuilder()
            .setEncoding(RecognitionConfig.AudioEncoding.OGG_OPUS)
            .setSampleRateHertz(16000)
            .setLanguageCode("zh-CN") // 替换成你需要的语言代码
            .build();
        StreamingRecognitionConfig streamingConfig = StreamingRecognitionConfig.newBuilder()
            .setConfig(config)
            .setInterimResults(true) // 开启实时中间结果(关键!实现Demo的实时转写)
            .build();
    
        // 构建结果观察者:把识别结果发回浏览器
        StreamObserver<StreamingRecognizeResponse> responseObserver = new StreamObserver<>() {
          @Override
          public void onNext(StreamingRecognizeResponse response) {
            // 取第一个结果的最优转录文本
            String transcript = response.getResultsList().get(0)
                .getAlternativesList().get(0).getTranscript();
            try {
              session.getBasicRemote().sendText(transcript);
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
    
          @Override
          public void onError(Throwable t) {
            t.printStackTrace();
          }
    
          @Override
          public void onCompleted() {
            try {
              session.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        };
    
        // 获取流式请求的观察者
        requestObserver = speechClient.streamingRecognizeCallable().call(responseObserver);
        // 发送第一个请求:必须包含流式配置
        requestObserver.onNext(StreamingRecognizeRequest.newBuilder()
            .setStreamingConfig(streamingConfig)
            .build());
      }
    
      @OnMessage
      public void onMessage(Session session, ByteBuffer message) {
        // 判断是否是录音结束标记
        try {
          String signal = new String(message.array());
          if (signal.contains("RECORDING_END")) {
            // 通知Google API结束识别
            requestObserver.onCompleted();
            speechClient.close();
            return;
          }
        } catch (Exception ignored) {
          // 如果是二进制音频数据,会抛出异常,直接处理音频块
        }
    
        // 发送音频块到Google Speech API
        requestObserver.onNext(StreamingRecognizeRequest.newBuilder()
            .setAudioContent(ByteString.copyFrom(message))
            .build());
      }
    
      @OnClose
      public void onClose(Session session) {
        if (requestObserver != null) {
          requestObserver.onCompleted();
        }
        if (speechClient != null) {
          try {
            speechClient.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
    
  3. 关键细节

    • 格式匹配:浏览器的音频编码、采样率、声道数必须和Java端的RecognitionConfig完全一致,否则API会返回错误或识别失败。
    • 初始请求:第一个StreamingRecognizeRequest必须携带streamingConfig,后续请求只需要发送音频数据。
    • 结束标记:收到浏览器的结束信号后,必须调用requestObserver.onCompleted(),否则Google API会一直等待数据,不会返回最终结果。

三、优化提速的小技巧

  • 调整浏览器发送音频块的间隔(比如从300ms改成200ms),减少识别延迟,但注意不要太小导致请求过载。
  • 开启setInterimResults(true)后,Google API会返回实时的中间结果,用户能看到“打字式”的转写效果,体验和官方Demo一致。
  • 确保Java服务器和Google Cloud Speech API的区域一致(比如都用asia-east1),减少网络延迟。

内容的提问来源于stack exchange,提问作者DeepProblems

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:00:53