利用jave2进行音频处理
很多朋友都知道,ffmpeg是一个功能强大的多媒体处理工具,可惜它并不是java语言开发,如果需要在java项目中使用时,得自己写很多代码,幸好github上有一个开源项目jave2 把ffmpeg做了封装,很大程度上简化了开发,使用方法如下:
先添加依赖项
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>3.1.1</version>
</dependency>
以下是一些常用示例:
1、获取音频文件的编码信息
MultimediaInfo getMediaInfo() {
String sourceFilePath = "/Users/jimmy/Downloads/bgm.wav";
File file = new File(sourceFilePath);
if (file != null && file.exists()) {
try {
MultimediaObject multimediaObject = new MultimediaObject(file);
MultimediaInfo m = multimediaObject.getInfo();
return m;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
System.out.println(getMediaInfo()); 输出如下:
ws.schild.jave.info.MultimediaInfo (format=wav (metadata={encoder=Lavf58.27.103}, duration=101850, video=null, audio=ws.schild.jave.info.AudioInfo (decoder=pcm_s16le ([1][0][0][0] / 0x0001), samplingRate=44100, channels=2, bitRate=1411000))
从上面可以看出,该文件是wav格式,时长为101.850秒,编码格式为pcm_s16le,采集率为44100,双声道,bit率为1411000
2、wav转mp3
boolean convert2Mp3() {
String sourceFilePath = "/Users/jimmy/Downloads/bgm.wav";
String targetFilePath = "/Users/jimmy/Downloads/bgm.mp3";
try {
File source = new File(sourceFilePath);
File target = new File(targetFilePath);
//Audio Attributes
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
audio.setBitRate(64000);
audio.setChannels(2);
audio.setSamplingRate(44100);
//Encoding attributes
EncodingAttributes attrs = new EncodingAttributes();
attrs.setInputFormat("wav");
attrs.setOutputFormat("mp3");
attrs.setAudioAttributes(audio);
//Encode
Encoder encoder = new Encoder();
encoder.encode(new MultimediaObject(source), target, attrs);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
return true;
}
3、转换编码格式
static boolean changeCode() {
String sourceFilePath = "/Users/jimmy/Downloads/bgm.wav";
String targetFilePath = "/Users/jimmy/Downloads/bgm_2.wav";
//Audio Attributes
AudioAttributes audio = new AudioAttributes();
audio.setCodec("pcm_u8");
audio.setBitRate(64000);
audio.setChannels(2);
audio.setSamplingRate(8000);
//Encoding attributes
EncodingAttributes attrs = new EncodingAttributes();
attrs.setInputFormat("wav");
attrs.setOutputFormat("wav");
attrs.setAudioAttributes(audio);
//Encode
Encoder encoder = new Encoder();
try {
encoder.encode(new MultimediaObject(new File(sourceFilePath)), new File(targetFilePath), attrs);
//辅助输出,观察编码格式的变化
MultimediaObject srcObj = new MultimediaObject(new File(sourceFilePath));
MultimediaObject targetObj = new MultimediaObject(new File(targetFilePath));
System.out.println(srcObj.getInfo());
System.out.println(targetObj.getInfo());
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
return true;
}
第7行,设置了新的编码pcm_u8
4、分离左右声道
boolean splitChannel() {
String source = "/Users/jimmy/Downloads/bgm.wav";
String left = "/Users/jimmy/Downloads/bgm_left.wav";
String right = "/Users/jimmy/Downloads/bgm_right.wav";
File leftFile = new File(left);
File rightFile = new File(right);
if (leftFile.exists()) {
leftFile.delete();
}
if (rightFile.exists()) {
rightFile.delete();
}
DefaultFFMPEGLocator locator = new DefaultFFMPEGLocator();
ProcessWrapper ffmpeg = locator.createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(source);
ffmpeg.addArgument("-map_channel");
ffmpeg.addArgument("0.0.0");
ffmpeg.addArgument(left);
ffmpeg.addArgument("-map_channel");
ffmpeg.addArgument("0.0.1");
ffmpeg.addArgument(right);
BufferedReader br = null;
try {
ffmpeg.execute();
br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
String line;
while ((line = br.readLine()) != null) {
//输出处理过程中的日志(辅助观察处理过程)
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
//辅助输出,观察编码格式的变化
MultimediaObject srcObj = new MultimediaObject(leftFile);
MultimediaObject targetObj = new MultimediaObject(rightFile);
System.out.println(srcObj.getInfo());
System.out.println(targetObj.getInfo());
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
声道分离后,会生成2个文件,分别对应于左右声道。
5、拼接音频(比如:把某段音频重复N次,合成1个新音频)
boolean mergeAudio() {
// ffmpeg -i bullet.wav -i bullet.wav -i bullet.wav -filter_complex '[0:0] [1:0] concat=n=3:v=0:a=1 [a]' -map [a] bullet_3.wav
//先生成要拼接的音频清单
int times = 5;
String src = "/Users/jimmy/Downloads/bullet.wav";
String target = "/Users/jimmy/Downloads/bullet_" + times + ".wav";
File targetFile = new File(target);
if (targetFile.exists()) {
targetFile.delete();
}
DefaultFFMPEGLocator locator = new DefaultFFMPEGLocator();
ProcessWrapper ffmpeg = locator.createExecutor();
for (int i = 1; i <= times; i++) {
ffmpeg.addArgument("-i");
ffmpeg.addArgument(src);
}
ffmpeg.addArgument("-filter_complex");
ffmpeg.addArgument("[0:0] [1:0] concat=n=" + times + ":v=0:a=1 [a]");
ffmpeg.addArgument("-map");
ffmpeg.addArgument("[a]");
ffmpeg.addArgument(target);
BufferedReader br = null;
try {
ffmpeg.execute();
br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
String line;
while ((line = br.readLine()) != null) {
//输出处理过程中的日志(辅助观察处理过程)
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
6、截取音频中的某一段
void cut() throws EncoderException {
String src = "/Users/jimmy/Downloads/bgm.wav";
String target = "/Users/jimmy/Downloads/bgm_1_3.wav";
File targetFile = new File(target);
if (targetFile.exists()) {
targetFile.delete();
}
File srcFile = new File(src);
MultimediaObject srcMultiObj = new MultimediaObject(srcFile);
MultimediaInfo srcMediaInfo = srcMultiObj.getInfo();
Encoder encoder = new Encoder();
EncodingAttributes encodingAttributes = new EncodingAttributes();
//设置起始偏移量(秒)
encodingAttributes.setOffset(1.0F);
//设置切片的音频长度(秒)
encodingAttributes.setDuration(2.0F);
//设置音频属性
AudioAttributes audio = new AudioAttributes();
audio.setBitRate(srcMediaInfo.getAudio().getBitRate());
audio.setSamplingRate(srcMediaInfo.getAudio().getSamplingRate());
audio.setChannels(srcMediaInfo.getAudio().getChannels());
//如果截取的时候,希望同步调整编码,可以设置不同的编码
// audio.setCodec("pcm_u8");
audio.setCodec(srcMediaInfo.getAudio().getDecoder().split(" ")[0]);
encodingAttributes.setInputFormat("wav");
encodingAttributes.setAudioAttributes(audio);
//写文件
encoder.encode(srcMultiObj, new File(target), encodingAttributes);
}
最后说一个可能会存在的问题:默认情况下,jave2在执行时,会把ffmpeg可执行文件释放到"java.io.tmpdir"临时目录下,但在tomcat等容器下执行时,如果启用tomcat的用户,与java应用的执行用户不同,可能会存在无写入权限的问题。遇到这种情况,可以先用代码把java.io.tmpdir这个系统变量,指到其它有权限的目录,执行完后,再还原回来
String oldTmpDir = System.getProperty("java.io.tmpdir");
try {
System.setProperty("java.io.tmpdir", "有权限写入的新临时目录");
// todo (jave2的其它处理)
} finally {
System.setProperty("java.io.tmpdir", oldTmpDir);
}
利用jave2进行音频处理的更多相关文章
- 简单谈谈如何利用h5实现音频的播放
作者:白狼 出处:http://www.manks.top/article/h5_audio本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律 ...
- 使用jave2将音频wav转换成mp3格式
最近需要用到语音合成功能,网上查阅了一番,发现可以使用腾讯云的语音合成API来完成这个功能,但是腾讯云的api返回的是wav格式的音频文件,这个格式的文件有些不通用,因此需要转换成mp3格式的文件. ...
- 利用mciSendString播放音频
最近在写音频播放器,不过有点懒散,开发进度很慢,一天只做了一点点东西.其实就是让程序能播放音频.这个在我大二学winform程序开发时书上有说,那是书上教的是用media player的COM组件,而 ...
- 利用FluorineFX录制音频与视频
要做一个完整的录制程序,处理RPC请求的类不仅要继承ApplicationAdapter,还要继承IStreamService接口,该接口定义了play(),pause(),publish(),cre ...
- iOS开发之音频口通信-通过方波来收发数据
之前做过的项目有需要通过音频口通信用方波来收发数据,由于这方面的资料比较少,下面就介绍下其原理,希望能给大家帮助. 一. 音频通信简介大家应该都知道支付宝声波支付和拉卡拉吧,它们都是利用手机的音频口( ...
- [Audio processing] FFMPEG转音频格式和采样率
利用FFMPEG转音频格式和采样率 import os import string import subprocess as sp #Full path of ffmpeg FFMPEG_BIN = ...
- Audio-支持多个音频文件格式
通过使用 audio 元素或对象支持多个音频格式,你可以将更多的听众从多个浏览器吸引到你的网页上. 使用源元素指定多个音频格式 在将 HTML5 audio 元素添加到代码时,可以指定一条在浏览器不支 ...
- 使用Core Audio实现VoIP通用音频模块
最近一直在做iOS音频技术相关的项目,由于单项直播SDK,互动直播SDK(iOS/Mac),短视频SDK,都会用到音频技术,因此在这里收集三个SDK的音频技术需求,开发一个通用的音频模块用于三个SDK ...
- Android硬编码——音频编码、视频编码及音视频混合
视频编解码对许多Android程序员来说都是Android中比较难的一个知识点.在Android 4.1以前,Android并没有提供硬编硬解的API,所以之前基本上都是采用FFMpeg来做视频软件编 ...
- mux复用 demux解复用
保存音频包: 直接输出解复用之后的的音频数据码流.只需要在每次调用av_read_frame()之后将得到的音频的AVPacket存为本地文件即可. 但在分离AAC码流的时候,直接存储AVPacket ...
随机推荐
- 23.5K star!零代码构建AI知识库,这个开源神器让问答系统开发像搭积木一样简单!
嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 FastGPT 是一个基于大语言模型的智能知识库平台,提供开箱即用的数据处理.RAG检索和可 ...
- 图解Spring源码2-Spring Bean元数据体系与Spring容器
>>>点击去看B站配套视频<<< 系列文章目录和关于我 1. 从一个例子开始 小陈申请加盟咖啡店后,小陈收到总部寄来的<开店规格单>.这份文件允许每家分 ...
- 国际化利器 Intl Messageformat
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:霜序 Formats ICU Message string ...
- vue3 基础-CompositionAPI - setup
之前介绍的是一些关于代码复用的问题, 如 mixin, plugin 等. 从本篇开始呢, 就将来学习一波 vue3 的新特性, 即 Composition API 咱之前的写法, 即把各种逻辑, 方 ...
- C/C++双叹号!!运算符
1.问题引入 在阅读https://github.com/amhndu/SimpleNES源代码中ppu.cpp中发现如下代码 m_bgPage = static_cast<CharacterP ...
- KMP跨平台开发中的现状调研
Kotlin Multiplatform Development(KMP)作为一种先进的跨平台开发技术,已从2023年11月的稳定版演进至2025年更加成熟的状态.目前KMP在业务逻辑共享方面已相当成 ...
- 异步之舞:FastAPI与MongoDB的极致性能优化之旅
title: 异步之舞:FastAPI与MongoDB的极致性能优化之旅 date: 2025/05/23 21:55:11 updated: 2025/05/23 21:55:11 author: ...
- 题解:P4586 [FJOI2015] 最小覆盖双圆问题
写了这么久终于过了,发篇题解记录一下. 第一次写黑题题解,写的不好请见谅. 目录 本题思路 三点定圆 最小圆覆盖 关于最小圆覆盖时间复杂度 回到本题 二分法划分点集 总时间复杂度 最小覆盖双圆问题代码 ...
- ArkUI-X与Android消息通信
平台桥接用于客户端(ArkUI)和平台(Android或iOS)之间传递消息,即用于ArkUI与平台双向数据传递.ArkUI侧调用平台的方法.平台调用ArkUI侧的方法.本文主要介绍Android平台 ...
- 自动 GitHub Readme 20 种语言翻译平台 - OpenAiTx 开源免费
[野人献曝]晚辈开发自动 GitHub Readme 20 种语言翻译平台 - OpenAiTx 开源免费 只需要一键将 GitHub 的网址替换为 OpenAiTx 即可自动进行 AI 翻译 例如: ...