android - Speech-To-Text api 错误通过 AudioRecorder 解析 pcm 文件的编码
问题描述
我在我的应用程序中使用 AudioRecord 来录制语音,然后我用 Firebase 调用语音到文本的 api,但它总是返回“编码”不正确。
val DEFAULT_AUDIO_SOURCE: Int = MediaRecorder.AudioSource.UNPROCESSED
val DEFAULT_SAMPLE_RATE_HZ: Int = 16_000
val DEFAULT_CHANNEL_CONFIG: Int = AudioFormat.CHANNEL_IN_MONO
val DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
val BUFFER_SIZE: Int = 2*AudioRecord.getMinBufferSize(DEFAULT_SAMPLE_RATE_HZ, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT)
mAudioRecord = AudioRecord(
DEFAULT_AUDIO_SOURCE,
DEFAULT_SAMPLE_RATE_HZ,
DEFAULT_CHANNEL_CONFIG,
DEFAULT_AUDIO_FORMAT,
DEFAULT_BUFFER_SIZE)
val data = ByteArray(file.length().toInt())
val input = DataInputStream(FileInputStream(file));
input.read(data);
input.close();
val audioContent: String = Base64.encodeToString(data, Base64.NO_WRAP);
val resp =
mApi.transcribe(FirebaseCloudFunctionsModel.Transcribe("LINEAR16", CloudTranslate.DEFAULT_SAMPLE_RATE_HZ, Locale.getDefault().toString(), audioContent)).execute()
解决方案
由于您使用的是 PCM 16 位,因此将音频记录在 ShortArray 缓冲区中(它的大小应该是缓冲区大小的一半,因为 short 是 16 位或 2 个字节)并使用此函数将缓冲区转换为 ByteArray:
private fun short2byte(sData:ShortArray):ByteArray {
val shortArrsize = sData.size
val bytes = ByteArray(shortArrsize * 2)
for (i in 0 until shortArrsize)
{
bytes[i * 2] = (sData[i] and 0x00FF).toByte()
bytes[(i * 2) + 1] = (sData[i] shr 8).toByte()
sData[i] = 0
}
return bytes
}
Google Cloud API 使用 URL 安全 Base64 编码,因此将其作为标志之一添加到 encodeString 函数。
val audioContent: String = Base64.encodeToString(data, Base64.URL_SAFE | Base64.NO_WRAP);
如果音频很小,您可以直接将其写入内存中的 ByteArrayOutputStream,而不是将音频写入文件。
推荐阅读
- sql - 将具有唯一值的列转置到行的 SQL 查询
- angular - CloudMQTT 的握手问题 - Angular
- python - 关于共享内存如何在 Python 的多编程库中工作的问题
- docker - VSCode 远程容器 - 错误:ENOSPC:设备上没有剩余空间
- sql - R dbplyr 是否足够“智能”来确定 SQL 数据库类型并应用适当的语法?
- asynchronous - 只有在 Dart 中完成上一次执行后,如何定期调用函数?
- javascript - 您可以使用变量名来引用对象而不使用 eval()
- javascript - 我不能在函数调用中使用之前通过 AJAX 请求加载的对象
- typescript - 使用对象的键作为联合类型
- django - 使用 django-extra-views 应用程序中的 UpdateWithInlinesView 更新自定义用户密码