【Android MediaCodec 将音频转换为 pcm 格式】

调用方法

	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 URLval url = URL(audioUrl)urlConnection = url.openConnection() as HttpURLConnectionurlConnection.connect()// Create a temporary file to store the downloaded audio dataval tempFile: File = File.createTempFile("temp_audio", null, cacheDir)outputStream = FileOutputStream(tempFile)// Write the downloaded audio data to the temporary fileval buffer = ByteArray(1024)var bytesRead: Intwhile (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? = nullvar outputStream: FileOutputStream? = nullval 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))// 创建用于解码的 MediaCodecmediaCodec = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME)!!)mediaCodec.configure(inputFormat, null, null, 0)mediaCodec.start()// 开始解码并写入到 PCM 文件val codecInputBuffers = mediaCodec.inputBuffersval codecOutputBuffers = mediaCodec.outputBuffersval bufferInfo = MediaCodec.BufferInfo()// 输出 PCM 文件的路径val pcmOutputFile = File(tempPcmFile.absolutePath)outputStream = FileOutputStream(pcmOutputFile)var isDone = falsewhile (!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}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/187315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【多线程】-- 07 线程礼让与线程强制执行

多线程 5 线程状态 5.3 线程礼让 Thread.yield()礼让线程&#xff0c;让当前正在执行的线程暂停&#xff0c;但不阻塞将线程从运行状态转为就绪状态让CPU重新调度&#xff0c;礼让不一定成功&#xff01;由CPU调度决定。 package com.duo.state;//测试礼让线程 public clas…

【2023CANN训练营第二季】——Ascend C算子调用及实验演示

自定义算子调用方式 完成自定义算子的开发部署后&#xff0c;可以通过单算子调用的方式来验证单算子的功能。单算子调用有API执行和模型执行两种方式&#xff1a; 单算子API执行&#xff1a;基于C语言的API执行算子&#xff0c;无需提供单算子描述文件进行离线模型的转换&…

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

我的往期文章&#xff1a; leetCode 647.回文子串 动态规划 优化空间 / 中心扩展法 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm1001.2014.3001.5501leetCode 131.分割回文串 回溯算法 图解 笔记-CSDN博客https://blog.csdn.n…

使用Docker本地部署chatgpt

GitHub上有一个开源的工程ChatGPT-Next-Web&#xff0c;这个工程已经封装好了UI以及和OpenAI的API之间的交互&#xff0c;你要做的事情就是把他部署到本地&#xff0c;并配置好你的OpenAI的sk&#xff0c;然后就可以使用了。那么接下来的文章里&#xff0c;我会手把手教你如何C…

Vue3 究竟好在哪里?

Vue3 相较于 Vue2 在很多方面都有所改进和优化&#xff0c;以下是一些主要的优点&#xff1a; 性能提升&#xff1a;Vue3 使用了新的编译器&#xff08;Vite&#xff09;&#xff0c;使得打包速度更快&#xff0c;运行速度也有所提升。同时&#xff0c;Vue3 对响应式系统进行了…

关于如何写好单元测试的思考

“二八定律”&#xff0c;由19世纪末20世纪初意大利经济学家巴莱多提出。他认为&#xff0c;在任何一组东西中&#xff0c;最重要的只占其中一小部分&#xff0c;约20%&#xff0c;其余80%尽管是多数&#xff0c;却是次要的。 What&#xff1f; 释义 单元测试&#xff08;uni…

C语言第四十弹---两个整数二进制位不同的个数

C语言求两个整数二进制位不同的个数 遍历法&#xff0c;使用循环获取每一位二进制位数&#xff0c;并让二进制位与1比较&#xff0c;如果相同则忽略&#xff0c;不同则个数增加。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>int main() {int a 0;int b 0;in…

4.求解无向图的各连通分支

求解无向图的各连通分支 输入&#xff1a; 第一行为图的节点数n&#xff08;节点编号0至n-1&#xff0c;0<n<10&#xff09; 从第二行开始列出图的边&#xff0c;-1表示输入结束 输出&#xff1a; 输出每个连通分支的广度优先搜索序列&#xff08;从连通分支的最小编号…

下拉列表select动态添加option和获取选中的option的值和value

分别用两种方法动态添加option&#xff1a; 方法一&#xff1a;JS方法添加 1、创建select标签 var select documnet.createElement(‘select’); 2、给select添加id select.setAttribute(‘id’,‘selectid’); 3、给select添加onchange事件 select.setAttribute(‘onc…

【云原生系列】Kubernetes知识点

目录 概念 基础架构 单master节点 多master节点 组件 Master节点核心组件 其他组件 请求发送流程 插件 核心资源 调度资源 Pod 创建pod组件间调用流程 pod生命周期&#xff1a; 初始化容器 镜像拉取策略 重启策略 钩子函数 探针 探针的实现方式 DownwardAP…

如何解决Windows中“Address already in use: bind“错误

当在Windows系统中开发网络应用程序时&#xff0c;经常会遇到 "Address already in use: bind" 的错误。这个错误通常表示正在尝试绑定的端口已经被其他程序占用了。本篇技术博客将介绍如何在Windows系统中解决这个问题&#xff0c;并提供实用的解决方案。 在网络应用…

Axios.post 请求报错: 403 Forbidden missing csrf token 和 invalid csrf token

Axios.post 请求报错&#xff1a;403 Forbidden missing csrf token 和 invalid csrf token 问题及解决 这个问题是在一个 post 请求的跨域接口上出现的 很奇怪的问题&#xff0c;可以直接看一解决方案就行了 一、解决方案 问题&#xff1a;使用 Axios.post 请求报错&#xff…

数据收集与处理(爬虫技术)

文章目录 1 前言2 网络爬虫2.1 构造自己的Scrapy爬虫2.1.1 items.py2.1.2 spiders子目录2.1.3 pipelines.py 2.2 构造可接受参数的Scrapy爬虫2.3 运行Scrapy爬虫2.3.1 在命令行运行2.3.2 在程序中调用 2.4 运行Scrapy的一些要点 3 大规模非结构化数据的存储与分析4 全部代码 1 …

【JavaSE】Java基础(学习笔记)

一、数组 1、动态初始化 int arr new int[3];数组名字是地址默认初始值为0数组的内存分配 2、数组的内存分配 arr存在栈里&#xff0c;只存地址&#xff0c;是局部变量&#xff0c;相当于指针new出来的实体/对象存在堆里&#xff0c;存放数据&#xff0c;用完也不会立即消…

【二叉树】Leetcode 266.翻转二叉树

题目链接 参考文章 解题思路 如果从整棵树的角度来看&#xff0c;用层序遍历翻转一棵二叉树需要遍历同一层节点后再反向遍历该层节点并且改变指针&#xff0c;但是这样做不仅低效率还会访问到野指针。因此必须换一个角度考虑问题&#xff1a;如果将每一个父节点的左右孩子交换…

LCR 140. 训练计划 II 23.12.01

给定一个头节点为 head 的链表用于记录一系列核心肌群训练项目编号&#xff0c;请查找并返回倒数第 cnt 个训练项目编号。 示例 1&#xff1a; 输入&#xff1a;head [2,4,7,8], cnt 1 输出&#xff1a;8 提示&#xff1a; 1 < head.length < 100 0 < head[i] …

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)

文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、…

【Spark基础】-- 宽窄依赖

目录 1、前言 2、宽窄依赖 2.1 窄依赖 2.2 宽依赖 3、宽窄转换的算子 1、前言 要理解宽窄依赖,首先我们需要了解 Transformations,什么是 Transformations?在 Spark 中,核心的数据结构是不可变的

数据结构-03-栈

1-栈的结构和特点 先进后出&#xff0c;后进先出 是栈的特点&#xff1b; 从图中&#xff0c;我们看到A入栈先放入底部&#xff0c;然后依次B和C&#xff1b;出栈的顺序依次是C-B-A&#xff1b;这种结构只能在一端操作。所以当某个数据集合只涉及在一端插入和删除数据&#xf…

什么是灯塔工厂?灯塔工厂的作用?

什么是灯塔工厂&#xff1f; "灯塔工厂"概念源于德国的工业4.0战略&#xff0c;又称“工业4.0示范工厂”或“标杆工厂”&#xff0c;代表工业领域顶级的智能制造能力。2018年&#xff0c;由世界经济论坛和麦肯锡共同推出。 灯塔工厂是通过数字化、网络化和智能化手…