AWS Transcribe Streaming BadRequestException:“无法解码音频流...”

2024-01-21

我正在使用 Websockets 在 Dart/Flutter 中构建一个 Transcribe Streaming 应用程序。当我流式传输测试音频(从单声道、16kHz、16 位签名的小端 WAV 文件中提取)时,我得到...

BadRequestException:无法解码您提供的音频流。检查音频流是否有效并重试您的请求。

作为测试,我使用一个文件来传输音频。我每秒发送 32k 数据字节(大致模拟实时麦克风流)。如果我流式传输所有 0x00 或所有 0xFF 或随机字节,我什至会收到错误。如果我将块大小划分为 16k 并将间隔时间划分为 0.5 秒,那么在出错之前它会再进行一帧...

就数据而言,我只是将字节按字面意思打包在 EventStream 帧的数据部分中,就像它们在文件中一样。显然,事件流打包是正确的(字节布局、CRC),否则我会收到一条错误消息,不是吗?

什么向 AWSTrans 表明它不可解码?关于如何进行此操作还有其他想法吗?

谢谢你的帮助...

这是进行打包的代码。完整版在这里(如果你敢的话……现在有点乱)https://pastebin.com/PKTj5xM2 https://pastebin.com/PKTj5xM2

Uint8List createEventStreamFrame(Uint8List audioChunk) {
  final headers = [
    EventStreamHeader(":content-type", 7, "application/octet-stream"),
    EventStreamHeader(":event-type", 7, "AudioEvent"),
    EventStreamHeader(":message-type", 7, "event")
  ];
  final headersData = encodeEventStreamHeaders(headers);
 
  final int totalLength = 16 + audioChunk.lengthInBytes + headersData.lengthInBytes;
  // final prelude = [headersData.length, totalLength];
  // print("Prelude: " + prelude.toString());
 
  // Convert a 32b int to 4 bytes
  List<int> int32ToBytes(int i) { return [(0xFF000000 & i) >> 24, (0x00FF0000 & i) >> 16, (0x0000FF00 & i) >> 8, (0x000000FF & i)]; }
 
  final audioBytes = ByteData.sublistView(audioChunk);
  var offset = 0;
  var audioDataList = <int>[];
  while (offset < audioBytes.lengthInBytes) {
    audioDataList.add(audioBytes.getInt16(offset, Endian.little));
    offset += 2;
  }
 
  final crc = CRC.crc32();
  final messageBldr = BytesBuilder();
  messageBldr.add(int32ToBytes(totalLength));
  messageBldr.add(int32ToBytes(headersData.length));
 
  // Now we can calc the CRC. We need to do it on the bytes, not the Ints
  final preludeCrc = crc.calculate(messageBldr.toBytes());
 
  // Continue adding data
  messageBldr.add(int32ToBytes(preludeCrc));
  messageBldr.add(headersData.toList());
  // messageBldr.add(audioChunk.toList());
  messageBldr.add(audioDataList);
  final messageCrc = crc.calculate(messageBldr.toBytes().toList());
  messageBldr.add(int32ToBytes(messageCrc));
  final frame = messageBldr.toBytes();
  //print("${frame.length} == $totalLength");
  return frame;
}

BadRequestException,至少在我的例子中,是指帧编码不正确,而不是音频数据错误。

AWS事件流编码详细信息是here https://docs.aws.amazon.com/transcribe/latest/dg/event-stream.html.

我在字节序和字节大小方面遇到了一些问题。您需要非常熟悉消息编码和音频缓冲区。音频需要是 16 位/有符号 (int)/little-endian (See here https://docs.aws.amazon.com/transcribe/latest/dg/input.html)。消息包装器中的那些长度参数是 32 位(4 字节)BIG endian。ByteData是你在 Dart 的朋友。这是我更新的代码的片段:

final messageBytes = ByteData(totalLength);

...

for (var i=0; i<audioChunk.length; i++) {
  messageBytes.setInt16(offset, audioChunk[i], Endian.little);
  offset += 2;
}

请注意,16 位 int 实际上占用了 2bytes职位。如果您没有指定 Endian 样式,那么它将默认为您的系统,这将导致 header int 编码或音频数据出错......输了!

确保一切正确的最佳方法是编写 AWS 响应所需的解码函数,然后解码编码帧并查看结果是否相同。使用 audo 的测试数据,如 [-32000, -100, 0, 200 31000] 或类似的数据,这样你就可以测试字节顺序等是否正确。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AWS Transcribe Streaming BadRequestException:“无法解码音频流...” 的相关文章

随机推荐