【HarmonyOS】实现从视频提取音频并保存到pcm文件功能(API6 Java)
【关键字】
视频提取类Extractor、视频编解码、保存pcm文件
【写在前面】
在使用API6开发HarmonyOS应用时,通常会开发一些音视频媒体功能,这里介绍如何从视频中提取音频保存到pcm文件功能,生成pcm音频文件后,就可使用音频播放类AudioRenderer进行播放了。这里主要介绍从视频提取音频并保存到pcm文件的开发步骤。
【开发步骤】
步骤1:对视频格式的文件进行提取音频文件,并通过解码器解码并监听获取到的buffer数据;直接使用Extractor从视频中提取出来的音频数据不能直接作为类似pcm数据源进行播放,需要使用解码器解码之后得到的原始数据才可AudioRenderer进行播放。新建VideoDecoder类,在里面封装相关功能代码。使用Extractor从视频提取音频数据并使用解码器解码,代码如下:
// 可创建VideoDecoder类,实现相关功能 private Format format;private Codec decoder;private Extractor extractor;public void createDecoder() {decoder = Codec.createDecoder(); // 创建解码器extractor = new Extractor(); // 创建Extractor解封装类boolean ret = extractor.setSource(new Source("/data/data/com.harmonyospro.myapplication/vedio_audio_test.mp4")); // 设置数据源,com.harmonyospro.myapplication为应用包名;也可设置为网络视频数据源System.out.println("setSource ret = " + ret);int trackCount = extractor.getTotalStreams();//获取轨道for (int i = 0; i < trackCount; i++) {format = extractor.getStreamFormat(i);if (format.getStringValue("mime").contains("audio")) { // 视频video,audio音频/*** @tc.steps: step2.set codec format for decoder* @tc.expected: step2.the return value is true*/ret = decoder.setCodecFormat(format);System.out.println("setCodecFormat ret = " + ret);ret = extractor.specifyStream(i);System.out.println("specifyStream ret = " + ret);System.out.println("format.toString() = " + format.toString());System.out.println("format.getStringValue(mine) = "+format.getStringValue("mime"));System.out.println("format.getStringValue(width) = "+format.getIntValue("width"));System.out.println("format.getStringValue(height) = "+format.getIntValue("height"));break;}}decoder.registerCodecListener(listener);}Codec.ICodecListener listener = new Codec.ICodecListener() {@Overridepublic void onReadBuffer(ByteBuffer byteBuffer, BufferInfo bufferInfo, int i) {Format fmt = decoder.getBufferFormat(byteBuffer);System.out.println("fmt.toString() = " + fmt.toString());// 写入文件writeFile(byteBuffer,bufferInfo,i);System.out.println("onReadBuffer == " + bufferInfo.toString());}@Overridepublic void onError(int errorCode, int act, int trackId) {throw new RuntimeException();}};/*** 调用 start()方法开始解码*/public void start(){boolean start = decoder.start();System.out.println("start = " + start);}/*** 调用getAvailableBuffer取到一个可用的ByteBuffer,把数据填入ByteBuffer里,然后再调用writeBuffer把ByteBuffer写入解码器实例*/public void framebuffer(){int i = 1;boolean reachEnd = false;while (!reachEnd){extractor.next();//下一帧ByteBuffer dstBuf = null;dstBuf = decoder.getAvailableBuffer(100000);if (dstBuf == null) {try {Thread.sleep(200);} catch (InterruptedException e) {System.out.println("InterruptedException");}continue;}System.out.println("02b dstBuf.toString() = " + dstBuf.toString());BufferInfo bufferInfo = new BufferInfo();bufferInfo.offset = 0;bufferInfo.size = extractor.readBuffer(dstBuf, 0);bufferInfo.timeStamp = extractor.getFrameTimestamp();bufferInfo.bufferType = extractor.getFrameType();System.out.println("bufferInfo bufferInfo = " + bufferInfo.timeStamp);reachEnd = extractor.getStreamId() == -1;System.out.println("reachEnd = " + reachEnd);if(reachEnd){bufferInfo.bufferType = bufferInfo.BUFFER_TYPE_END_OF_STREAM;}boolean ret = decoder.writeBuffer(dstBuf, bufferInfo);System.out.println("writeBuffer ret = " + ret);try {Thread.sleep(200);} catch (InterruptedException e) {System.out.println("InterruptedException");}}} /*** 停止解码,释放资源*/public void stopAndRelease(){System.out.println("VedioDecoder stopAndRelease");decoder.stop();decoder.release();}
步骤2:封装writeFile方法,将获取到的buffer数据写入pcm文件中,此处com.harmonyospro.myapplication为工程bundleName,可替换为应用包名,代码如下:
private void writeFile(ByteBuffer outputBuffer, BufferInfo info, int trackId) {FileOutputStream fileOutputStream = null;File fd = new File("/data/data/com.harmonyospro.myapplication/1.pcm");try {fileOutputStream = new FileOutputStream(fd, true);final byte[] chunk = new byte[info.size];outputBuffer.get(chunk);fileOutputStream.write(chunk, 0, outputBuffer.limit());outputBuffer.clear();} catch (FileNotFoundException e) {System.out.println("02b FileNotFoundException");} catch (IOException e) {System.out.println("02b IOException");}finally {try {fileOutputStream.close();} catch (IOException e) {System.out.println("IOException");}}
}
步骤3:在需要调用视频提取音频的地方进行方法调用,代码如下:
VideoDecoder videoDecoder = new VideoDecoder();
videoDecoder.createDecoder();
videoDecoder.start();
videoDecoder.framebuffer();
//vedioDecoder.stopAndRelease(); // 需要停止的时候停止
这里就完成从视频获取音频并保存到pcm文件的功能了,获取到pcm文件,就可以使用AudioRenderer进行播放了。
【参考文档】
视频编解码文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-video-codec-0000000000031749
媒体提取开发指导:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-video-extractor-0000000000044202
音频播放开发指导:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-audio-playback-0000000000031734
相关文章:
【HarmonyOS】实现从视频提取音频并保存到pcm文件功能(API6 Java)
【关键字】 视频提取类Extractor、视频编解码、保存pcm文件 【写在前面】 在使用API6开发HarmonyOS应用时,通常会开发一些音视频媒体功能,这里介绍如何从视频中提取音频保存到pcm文件功能,生成pcm音频文件后,就可使用音频播放类…...
Linux:shell命令运行原理和权限的概念
文章目录 shell和kernelshell的概念和原理Linux的权限文件的权限文件的类型文件的权限管理权限的实战应用 shell和kernel 从狭义上来讲,Linux是一个操作系统,我们叫它叫kernel,意思是核心,核心的意思顾名思义,就是最关…...
Javascript -- 数组prototype方法探究
一、数组prototype方法探究 1、不改变原数组 1. concat() 这个是数组拼接方法,可以将两个数组或多个数组拼接并返回一个包含两个数组或多个数组内容的新数组,不会改变原数组 方法里面理论上可以写入n个参数, const arr [1,2]; var str …...
android stduio 打开工程后直接报Connection refused解决
报错如下:Connection refused 解决方案: 打开gradle-wrapper.properties修改distributionUrl 将: distributionUrlhttp\://localhost/gradle/distributions/gradle-6.5-bin.zip 替换为: distributionUrlhttps\://services.gradle.org/distributions/gradle-6.5-bin.zip 错…...
搜索与图论(一)
一、DFS与BFS 1.1深度优先搜索(DFS) DFS不具有最短性 //排列数字问题 #include<iostream> using namespace std;const int N 10; int n; int path[N]; bool st[N];void dfs(int u) {if(u n){for(int i 0;i < n;i) printf("%d",path[i]);puts("&qu…...
百题千解计划【CSDN每日一练】“小明投篮,罚球线投球可得一分”(附解析+多种实现方法:Python、Java、C、C++、C#、Go、JavaScript)
这个心上人,还不知道在哪里,感觉明天就会出现。 🎯作者主页: 追光者♂🔥 🌸个人简介: 💖[1] 计算机专业硕士研究生💖 🌟[2] 2022年度博客之星人工智能领域TOP4🌟 🏅[3] 阿里云社区特邀专家博主🏅 🏆[4] CSDN-人工智能领域优质创作者�…...
lemon框架开发笔记
lemon框架开发笔记 JudgeUtils.isBlank() 字符串为 null 或者 "" ----返回true JudgeUtils.isNotBlankAll() 字符串全部不为 null 或者 "" ----返回true JudgeUtils.isBlankAll() 字符串全部为 null 或者 "" ----返回true// isBlank 是在isEmpt…...
Spark SQL快速入门
1. 了解Spark SQL 1.1 什么是Spark SQL Spark SQL是spark的一个模块,用于处理海量的结构化数据。 1.2 Spark SQL有什么特点?优点是什么? 特点: Spark SQL支持读取和写入多种格式的数据源,包括Parquet、JSON、CSV、…...
linux+Jenkins+飞书机器人发送通知(带签名)
文章目录 如何使用在linux 上安装python 环境发送消息python脚本把脚本上传倒linux上 jenkins 上执行脚本 如何使用 自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 在linux 上安装python 环境 yum install python3 python…...
react hooks
1 useEffect(setup,dependencies) 使用object.is来比较每个依赖项和它先前的值 依赖项为空数组的effect不会在组件任何props和state发生改变时重新运行 当useEffect依赖于外部传入props对象时,容易造成死循环 需要对依赖对象进行深比较 import { isEqual } from…...
一起学数据结构(1)——复杂度
目录 1. 时间复杂度: 1.1 时间复杂度的概念: 1.2 时间复杂度的表示及计算: 1.3 较为复杂的时间复杂度的计算: 2. 空间复杂度: 2.1 空间复杂度的概念: 2.2 空间复杂度的计算: 1. 时间复杂度…...
<el-date-picker>组件选择开始时间,结束时间自动延长30min
背景:选择开始时间,结束时间自动增加30分钟,结束时间也可重新选择,如图: <el-form-item label"预约开始时间" prop"value1"><el-date-pickersize"large"v-model"ruleForm…...
eslint-webpack-plugin
说明:现在eslint已经弃用了eslint-loader,如果要安装来使用的话,会报错,烦死人 大概的报错信息如下: ERROR in ./src/index.js Module build failed (from ./node_modules/eslint-loader/dist/cjs.js): TypeError: Cannot read …...
logback中文一直是乱码,logback中文问号
logback一直是乱码 方案一加上UTF-8 方案二我这边方案一不行 在启动参数加上 -Dfile.encodingutf-8 这个竟然就可以了...
C++之文件操作
1.C文件操作 C中文件操作头文件:fstream。 文件类型:文件文件和二进制文件。 文件操作三大类: ofstream 写操作 ifstream 读操作 fstream:读写操作 文件打开方式: 标志说明ios::in只读ios::out只写,文件不存在则…...
CentOS 7.6安装 MongoDB 5.0.2
https://developer.aliyun.com/article/983777 我遇到的问题:如何以集群的方式启动,使用replSet的方式进行启动: 需要在配置文件上加上replSet的信息 port27017 #端口 bind_ip0.0.0.0 #默认是127.0.0.1 dbpath/usr/local/mongodb/data #数据…...
Windows下安装python3教程
参考:https://blog.csdn.net/kailingr/article/details/128193083 一、安装步骤图解 准备工作: 进官网https://www.python.org/下载Python 安装包,注意:Python 3.9不能在Windows 7或更早版本上使用 安装: 1.下载完之后双击该文…...
opencv-27 阈值处理 cv2.threshold()
怎么理解阈值处理? 阈值处理(Thresholding)是一种常用的图像处理技术,在机器学习和计算机视觉中经常被用于二值化图像或二分类任务。它基于设定一个阈值来将像素值进行分类,将像素值大于或小于阈值的部分分为两个不同的类别&…...
AAOS 音频焦点请求
文章目录 前言基本概念提供给应用来获取音频焦点的apiAAOS中的音频焦点管理交互矩阵duck的实现流程AAOS 测试应用kitchensink焦点相关 前言 本文章的目标是首先了解Android中音频焦点的基本概念,理解代码中相关音频焦点的使用方法。其次理解AAOS 中相关交互矩阵概念…...
订单系统中的幂等实现
一.订单提交的例子 一个订单生成并支付的过程,大致为:用户点击前端页面提交订单->后端根据此次提交信息生成订单->用户确认订单并进行支付操作->支付成功。 主要分为前端层面,后端系统层面,数据库层面。前端层面不详述…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
Linux操作系统共享Windows操作系统的文件
目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项,设置文件夹共享为总是启用,点击添加,可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download(这是我共享的文件夹)&…...
