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

React Native使用@aws-sdk/client-transcribe-streaming遇异步可迭代对象错误

在React Native中使用AWS Transcribe Streaming的问题

问题背景

尝试在React Native中通过设备麦克风采集音频流,传输到AWS Transcribe服务实现实时转录,但启动时触发错误:TypeError: Object is not async iterable。已使用异步生成器向TranscribeStreamingClient传递音频流,但问题仍存在。

目前找到的示例均为Web/浏览器环境,依赖Node.js的microphone-stream包,未找到React Native的适配方案。当前使用最接近的react-native-live-audio-stream库,但依旧报错,AWS官方文档未提供相关指引。

已排查情况

  • .send()函数返回200响应:
{"$metadata": {"attempts": 1, "cfId": undefined, "extendedRequestId": undefined, "httpStatusCode": 200, "requestId": undefined, "totalRetryDelay": 0}, "SessionId": "633592f0-8ce5-487d-a67e-6c05001f7b98", "TranscriptResultStream": {"options": {"deserializer": [Function anonymous], "messageStream": [MessageDecoderStream]}}}
  • 查看messageDecoderStream发现为空数组
  • 已确认音频数据已被捕获并推入audioPayloadStream数组中

代码实现

import 'react-native-get-random-values'; 
import 'react-native-url-polyfill/auto'; 
import { TranscribeStreamingClient, StartStreamTranscriptionCommand } from '@aws-sdk/client-transcribe-streaming'; 
import LiveAudioStream from 'react-native-live-audio-stream'; 
import { Buffer } from 'buffer'; 

const useTranscribeController = () => { 
  let isStarted = false; 
  let audioPayloadStream: any = []; 
  const audioStream = LiveAudioStream; 
  const client = new TranscribeStreamingClient({ 
    region: 'us-west-2', 
    credentials: { 
      accessKeyId: process.env.AWS_ACCESS_KEY_ID, 
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, 
      sessionToken: process.env.AWS_SESSION_TOKEN, 
    }, 
  }); 
  
  const audioGenerator = async function* () {
    for await (const chunk of audioPayloadStream) {
      yield { AudioEvent: { AudioChunk: chunk } };
    } 
  }; 

  const stop = () => {
    audioPayloadStream = [];
    audioStream.stop();
    client.destroy();
    isStarted = false;
  };

  const start = async () => {
    try {
      isStarted = true;
      const command = new StartStreamTranscriptionCommand({
        LanguageCode: 'en-US',
        MediaEncoding: 'pcm',
        MediaSampleRateHertz: 44100,
        AudioStream: audioGenerator(),
      });
      const response = await client.send(command);
      console.log(response);
      if (response.TranscriptResultStream) {
        for await (const event of response.TranscriptResultStream) {
          const message = event.TranscriptEvent;
          const results = event.TranscriptEvent?.Transcript?.Results;
          results?.map(result => {
            (result.Alternatives || []).map(alternative => {
              const transcript = alternative.Items?.map(item => item.Content).join(' '); 
              console.log({ transcript });
            });
          });
        }
      } else {
        console.log('the response is undefined');
      }
    } catch (e) {
      console.log(e);
      if (isStarted) {
        stop();
      }
    } 
  }; 

  const initialize = async () => {
    const options = {
      sampleRate: 44100, 
      channels: 1, 
      bitsPerSample: 16, 
      audioSource: 6, 
      bufferSize: 1024, 
      wavFile: 'pcm.wav', 
    }; 
    
    audioStream.init(options); 
    audioStream.start(); 
    audioStream.on('data', data => { 
      audioPayloadStream.push(Buffer.from(data, 'base64')); 
      if (!isStarted && audioPayloadStream.length !== 0) {
        start(); 
      }  
    }); 
  }; 
  return { initialize }; 
}; 

export default useTranscribeController; 

解决方案

1. 修复异步生成器核心问题

报错的根本原因是audioPayloadStream是普通数组,不是异步可迭代对象,无法用for await...of遍历。需要将其替换为异步队列,让生成器能持续获取新的音频chunk:

class AsyncAudioQueue {
  private queue: Buffer[] = [];
  private resolvers: ((value: IteratorResult<Buffer>) => void)[] = [];

  push(chunk: Buffer) {
    if (this.resolvers.length > 0) {
      const resolve = this.resolvers.shift()!;
      resolve({ value: chunk, done: false });
    } else {
      this.queue.push(chunk);
    }
  }

  [Symbol.asyncIterator]() {
    return {
      next: () => {
        if (this.queue.length > 0) {
          return Promise.resolve({ value: this.queue.shift()!, done: false });
        }
        return new Promise(resolve => this.resolvers.push(resolve));
      }
    };
  }
}

替换原audioPayloadStream定义:

let audioPayloadStream = new AsyncAudioQueue();

2. 调整音频数据处理逻辑

确认react-native-live-audio-stream返回的data类型:如果是原始PCM二进制数据(而非Base64),直接转Buffer即可:

audioStream.on('data', data => { 
  audioPayloadStream.push(Buffer.from(data)); 
  if (!isStarted) {
    start(); 
    isStarted = true;
  }  
});

3. 修复响应流的异步迭代兼容性

AWS Transcribe返回的TranscriptResultStream在React Native环境可能存在兼容性问题,可借助AWS工具包转换:

import { toAsyncIterable } from '@aws-sdk/util-stream-node';

// 在start函数中处理响应
if (response.TranscriptResultStream) {
  const stream = toAsyncIterable(response.TranscriptResultStream);
  for await (const event of stream) {
    const results = event.TranscriptEvent?.Transcript?.Results;
    results?.map(result => {
      (result.Alternatives || []).map(alternative => {
        const transcript = alternative.Items?.map(item => item.Content).join(' '); 
        console.log({ transcript });
      });
    });
  }
}

4. 校验参数与依赖版本

  • 确保MediaSampleRateHertz和react-native-live-audio-stream设置的sampleRate完全一致(均为44100)
  • 锁定@aws-sdk/client-transcribe-streaming到稳定版本(如3.x),避免版本兼容问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:27:53