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
相关产品推荐
相关产品推荐

