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

Android14下用RecognizerIntent的EXTRA_AUDIO_SOURCE实现PCM转文字遇阻

Android 14下PCM音频转文字:EXTRA_AUDIO_SOURCE使用异常及相关API疑问

环境与需求

  • 设备系统:Android 14
  • 开发需求:将存放在res/raw目录下的自有PCM音频文件转换为文字

问题详情

参考API 33的RecognizerIntent.EXTRA_AUDIO_SOURCE文档说明,需传入音频源的ParcelFileDescriptor,但实际运行时设备未识别自定义音频资源,反而调用麦克风进行语音识别。相关实现代码如下:

private var audioPfd : ParcelFileDescriptor? = null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val testFilePath = copyFiletoStorage(R.raw.test, "test.pcm")
    val testFile = File(testFilePath)
    testFile.setReadable(true)

    audioPfd = ParcelFileDescriptor.open(testFile, ParcelFileDescriptor.MODE_READ_ONLY)
    println("audioPfd size:${audioPfd?.statSize}")
    startSpeechToText(audioPfd)
}

private fun copyFiletoStorage(resourceId: Int, resourceName: String): String? {
    val filePath = filesDir.path + "/" + resourceName
    try {
        println("openRawResource")
        val `in` = resources.openRawResource(resourceId)
        var out: FileOutputStream? = null
        out = FileOutputStream(filePath)
        val buff = ByteArray(1024)
        var read = 0
        try {
            while (`in`.read(buff).also { read = it } > 0) {
                out.write(buff, 0, read)
            }
        } finally {
            `in`.close()
            out.close()
        }
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return filePath
}

private fun startSpeechToText(pcmFile: ParcelFileDescriptor?) {
    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault().toLanguageTag())
    intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
    intent.putExtra(RecognizerIntent.EXTRA_AUDIO_SOURCE_CHANNEL_COUNT, 1)
    intent.putExtra(RecognizerIntent.EXTRA_AUDIO_SOURCE_ENCODING, AudioFormat.ENCODING_PCM_16BIT)
    intent.putExtra(RecognizerIntent.EXTRA_AUDIO_SOURCE_SAMPLING_RATE, 16000)
    intent.putExtra(RecognizerIntent.EXTRA_AUDIO_SOURCE, pcmFile)

    speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this, ComponentName("com.google.android.tts",
        "com.google.android.apps.speech.tts.googletts.service.GoogleTTSRecognitionService"))

    speechRecognizer?.setRecognitionListener(object : RecognitionListener {
        override fun onReadyForSpeech(p0: Bundle?) {
            println("onReadyForSpeech")
        }

        override fun onBeginningOfSpeech() {
            println("onBeginningOfSpeech")
        }

        override fun onRmsChanged(p0: Float) {
            println("onRmsChanged sound: $p0")
        }

        override fun onBufferReceived(p0: ByteArray?) {
            println("onBufferReceived")
        }

        override fun onEndOfSpeech() {
            println("onEndOfSpeech")
        }

        override fun onError(p0: Int) {
            println("onError:$p0")
            stopRecognizer()
        }

        override fun onResults(p0: Bundle?) {
            println("onResults: $p0")
            val matches = p0?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
            if (matches != null && matches.isNotEmpty()) {
                val text = matches[0]
                Toast.makeText(applicationContext, "Recognized Text: $text", Toast.LENGTH_LONG).show()
                textResult?.setText(text)
            }
        }

        override fun onPartialResults(p0: Bundle?) {
            val matches = p0?.getStringArrayList(SpeechRecognizer.RECOGNITION_PARTS)
            println("onPartialResults:${matches?.get(0)}")
        }

        override fun onEvent(p0: Int, p1: Bundle?) {
            println("onEvent")
        }
    })

    speechRecognizer?.startListening(intent)
}

核心疑问

  1. Android是否支持通过EXTRA_AUDIO_SOURCE实现自有PCM音频转文字的需求?若支持,求实现指引(目前未找到该API的使用示例)。
  2. 在Android S(API 31)模拟器中尝试使用EXTRA_AUDIO_INJECT_SOURCE传入音频Uri的用法是否正确?示例代码如下:
val url = Uri.parse("android.resource://" + getPackageName() + "/" + "raw" + "/" + "test.pcm")
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
intent.putExtra(RecognizerIntent.EXTRA_AUDIO_INJECT_SOURCE, url)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:52:49