调用方法
var url = "https://xxxx.mp3"
DownloadAndConvertTask(context.cacheDir.path).execute(url)
代码实现
class DownloadAndConvertTask constructor(cacheDirPath: String): AsyncTask<String?, Void?, Void?>() {
//缓存路径
var cacheDir = File(cacheDirPath)
override fun doInBackground(vararg params: String?): Void? {
if (params.isNotEmpty()) {
val audioUrl = params[0]
if (audioUrl != null) {
val path = downloadAudioFile(audioUrl)
val pcmPath = decodeAudioToPcm(path)
if(!pcmPath.isNullOrBlank()){
// TODO ... 这里拿到pcm文件路径
}
}
}
return null
}
/**
* 下載音频文件到本地
* @param audioUrl 要下载的音频链接
* @return 下载到本地的文件路径
*/
private fun downloadAudioFile(audioUrl: String): String{
Log.d("downloadAndConvert", "audioUrl = "+audioUrl)
var urlConnection: HttpURLConnection?
var outputStream: FileOutputStream?
// Open a connection to the audio file URL
val url = URL(audioUrl)
urlConnection = url.openConnection() as HttpURLConnection
urlConnection.connect()
// Create a temporary file to store the downloaded audio data
val tempFile: File = File.createTempFile("temp_audio", null, cacheDir)
outputStream = FileOutputStream(tempFile)
// Write the downloaded audio data to the temporary file
val buffer = ByteArray(1024)
var bytesRead: Int
while (urlConnection.inputStream.read(buffer).also { bytesRead = it } != -1) {
outputStream.write(buffer, 0, bytesRead)
}
outputStream.close()
urlConnection.inputStream.close()
urlConnection.disconnect()
return tempFile.absolutePath
}
/**
* 音頻文件解码为pcm格式
* @param inputAudioFile 要转码的音频文件路径
* @return pcm文件路径
*/
private fun decodeAudioToPcm(inputAudioFile: String): String? {
Log.d(TAG, "decodeAudioToPcm start inputAudioFile = $inputAudioFile")
if(inputAudioFile.isEmpty()){
return null
}
if(inputAudioFile.endsWith(".pcm")){
return inputAudioFile
}
val timeStart = System.currentTimeMillis()
val mediaExtractor = MediaExtractor()
var mediaCodec: MediaCodec? = null
var outputStream: FileOutputStream? = null
val tempPcmFile: File = File.createTempFile("temp_audio_pcm", ".pcm", cacheDir)
try {
// 设置数据源为输入音频文件
mediaExtractor.setDataSource(inputAudioFile)
// 选择第一个默认轨道(多个音轨时,请注意选择音轨)
mediaExtractor.selectTrack(0)
// 获取音频轨道的格式
val inputFormat = mediaExtractor.getTrackFormat(0)
Log.d(TAG, "decodeAudioToPcm MediaFormat.KEY_MIME = "+inputFormat.getString(MediaFormat.KEY_MIME))
// 创建用于解码的 MediaCodec
mediaCodec = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME)!!)
mediaCodec.configure(inputFormat, null, null, 0)
mediaCodec.start()
// 开始解码并写入到 PCM 文件
val codecInputBuffers = mediaCodec.inputBuffers
val codecOutputBuffers = mediaCodec.outputBuffers
val bufferInfo = MediaCodec.BufferInfo()
// 输出 PCM 文件的路径
val pcmOutputFile = File(tempPcmFile.absolutePath)
outputStream = FileOutputStream(pcmOutputFile)
var isDone = false
while (!isDone) {
// 获取可用的输入缓冲区
val inputBufferIndex = mediaCodec.dequeueInputBuffer(10000)
if (inputBufferIndex >= 0) {
// 获取输入缓冲区
val inputBuffer = codecInputBuffers[inputBufferIndex]
// 读取音频数据到输入缓冲区
val sampleSize = mediaExtractor.readSampleData(inputBuffer, 0)
if (sampleSize < 0) {
// 如果没有更多数据,发送 EOS(End of Stream)标志
mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
isDone = true
} else {
// 将数据放入输入缓冲区,并前进到下一帧
mediaCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, mediaExtractor.sampleTime, 0 )
mediaExtractor.advance()
}
}
// 获取解码后的输出数据
val outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
if (outputBufferIndex >= 0) {
// 获取输出缓冲区
val outputBuffer = codecOutputBuffers[outputBufferIndex]
// 将 PCM 数据从输出缓冲区中读取到字节数组中
val chunk = ByteArray(bufferInfo.size)
outputBuffer.get(chunk)
outputBuffer.clear()
// 将 PCM 数据写入到输出文件
outputStream.write(chunk, 0, chunk.size)
// 释放输出缓冲区
mediaCodec.releaseOutputBuffer(outputBufferIndex, false)
}
}
} catch (e: IOException) {
Log.e(TAG, "Error decoding audio to PCM: " + e.message)
return null
} finally {
try {
// 关闭资源
if (mediaCodec != null) {
mediaCodec.stop()
mediaCodec.release()
}
mediaExtractor.release()
outputStream?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
Log.d(TAG, "decodeAudioToPcm end outputPcmFile = "+tempPcmFile.absolutePath)
Log.d(TAG, "decodeAudioToPcm end outputPcmFile.length = "+tempPcmFile.length())
Log.d(TAG, "decodeAudioToPcm time consuming (ms) = "+(System.currentTimeMillis()-timeStart))
return tempPcmFile.absolutePath
}
}
原文地址:https://blog.csdn.net/bailichun19901111/article/details/134711515
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_38004.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。