使用ExoPlayer播放录制的PCM字节数组遇问题,求技术建议
问题分析与解决方案
核心问题:你录制的是原始PCM音频数据,但播放时错误使用了Mp3Extractor解析,ExoPlayer无法识别无格式头的PCM数据,导致播放失败。
解决方案步骤
1. 修正MediaSource创建逻辑,适配PCM格式
替换createMediaSource函数,使用PcmExtractor并明确指定与录制一致的音频参数:
fun createMediaSource(bytes: ByteArray): MediaSource { // 匹配录制时的音频格式参数 val audioFormat = AudioFormat.Builder() .setSampleRate(RECORDER_SAMPLE_RATE) .setChannelMask(RECORDER_CHANNELS) .setEncoding(RECORDER_AUDIO_ENCODING) .build() val byteArrayDataSource = ByteArrayDataSource(bytes) val dataSourceFactory = DataSource.Factory { byteArrayDataSource } // 使用PCM提取器替代MP3提取器 val extractorsFactory = ExtractorsFactory { arrayOf(PcmExtractor(audioFormat)) } return ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory) .createMediaSource(MediaItem.fromUri(Uri.EMPTY)) }
2. 确保录制的音频数据完整
你的录制函数目前是分块回调数据,需要将所有录制片段拼接为完整的ByteArray,避免播放时数据不完整:
suspend fun recordVoice(audioRecord: AudioRecord?): ByteArray = withContext(Dispatchers.IO) { Log.i("LOG", "BUFFER SIZE: $BUFFER_SIZE_RECORDING") audioRecord ?: return@withContext ByteArray(0) audioRecord.startRecording() val outputStream = ByteArrayOutputStream() val buf = ByteArray(BUFFER_SIZE_RECORDING) try { do { val byteRead = audioRecord.read(buf, 0, buf.size) if (byteRead <= 0) break // 读取完成或出错时终止 outputStream.write(buf, 0, byteRead) } while (true) } catch (e: Exception) { e.printStackTrace() } finally { audioRecord.stop() audioRecord.release() outputStream.close() } outputStream.toByteArray() }
3. 检查ExoPlayer初始化与状态管理
确保播放器初始化正确,且调用playAudio时播放器处于可用状态:
// 示例初始化逻辑(根据你的实际场景调整) private fun initPlayer() { player = ExoPlayer.Builder(requireContext()) .build() // 绑定生命周期(如果是Fragment/Activity) lifecycle.addObserver(player!!) }
内容的提问来源于stack exchange,提问作者Mistelo
相关产品推荐
相关产品推荐

