Java分析音频文件声音大小
客户虐我千百遍,我待客户如初恋。
年前接到了一个奇怪的需求,需求是要采集用户上传的音频文件,并分析出此音频的声音分贝大小,这边记录一下
1.首先在pom.xml中导入jar
<dependency>
<groupId>com.github.dadiyang</groupId>
<artifactId>jave</artifactId>
<version>1.0.4</version>
</dependency>
注意这里使用了ffmpeg,具体的安装步骤自行百度
2.调用AudioUtils.amrToWav转换音频格式
使用MediaId从微信获取上传的音频文件并使用ffmpeg转换格式为wav格式:
try {
InputStream wxAudio = WxApi.getWxAudio(mediaId, wxToken);
if (wxAudio != null) {
String fileName = System.currentTimeMillis() + "_" + new Random().nextInt(1000) + ".arm";
File file = new File(path + fileName);
FileUtils.copyInputStreamToFile(wxAudio, file);
File file1 = new File(path + fileName.split("\\.")[0] + ".wav");
AudioUtils.amrToWav(file, file1);
//删除文件
file.delete();
String db = FfmpegUtil.convert(file1);
return Result.ok(db);
}
} catch (IOException e) {
log.error("voice exception:", e);
}
ps:其中有个问题,具体问题我忘记了,好像是ffmpeg执行文件的问题,翻阅了一下第一步中导入jar包的源码发现其中有ffmpeg的执行文件
这里不做描述,间隔时间太久远了,只提供一下类似问题的解决思路
3.研究ffmpeg命令
先贴命令
/usr/tomcat/tomcat8.5/temp/jave-1/ffmpeg -i /opt/voice/1576573683569_278.wav -filter_complex volumedetect -c:v copy -f null /dev/null
大概解释一下
/usr/tomcat/tomcat8.5/temp/jave-1/ffmpeg 表示你的ffmpeg执行文件路径
/opt/voice/1576573683569_278.wav 表示你的要分析音频文件的路径
后面的都是固定的,我们来执行一下得到如下结果
ffmpeg version 4.0.1-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg
libavutil 56. 14.100 / 56. 14.100
libavcodec 58. 18.100 / 58. 18.100
libavformat 58. 12.100 / 58. 12.100
libavdevice 58. 3.100 / 58. 3.100
libavfilter 7. 16.100 / 7. 16.100
libswscale 5. 1.100 / 5. 1.100
libswresample 3. 1.100 / 3. 1.100
libpostproc 55. 1.100 / 55. 1.100
Input #0, wav, from '/opt/voice/1576573683569_278.wav':
Metadata:
encoder : Lavf58.12.100
Duration: 00:00:02.80, bitrate: 8 kb/s
Stream #0:0: Audio: mp3 (U[0][0][0] / 0x0055), 8000 Hz, mono, fltp, 8 kb/s
[Parsed_volumedetect_0 @ 0x6adcc40] n_samples: 0
Stream mapping:
Stream #0:0 (mp3float) -> volumedetect
volumedetect -> Stream #0:0 (pcm_s16le)
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
Metadata:
encoder : Lavf58.12.100
Stream #0:0: Audio: pcm_s16le, 8000 Hz, mono, s16, 128 kb/s
Metadata:
encoder : Lavc58.18.100 pcm_s16le
size=N/A time=00:00:02.80 bitrate=N/A speed=2.09e+03x
video:0kB audio:44kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[Parsed_volumedetect_0 @ 0x6af7a40] n_samples: 22464
[Parsed_volumedetect_0 @ 0x6af7a40] mean_volume: -39.6 dB
[Parsed_volumedetect_0 @ 0x6af7a40] max_volume: -22.6 dB
[Parsed_volumedetect_0 @ 0x6af7a40] histogram_22db: 2
[Parsed_volumedetect_0 @ 0x6af7a40] histogram_23db: 2
[Parsed_volumedetect_0 @ 0x6af7a40] histogram_24db: 9
[Parsed_volumedetect_0 @ 0x6af7a40] histogram_25db: 27
这么多东西,其实其中只有2个值是我们需要关注的
max_volume为最大分贝
mean_volume为平均分贝
不要问我为什么是负数,我也不知道-_-||,如果有知道的小伙伴可以留言指导指导一下
4.Java代码执行ffmpeg命令
private static final String FFMPEG_PATH = System.getProperty("catalina.home") + "/temp/jave-1/ffmpeg";
/** * 获取wav音量分贝 * * @param file * @return * @throws IOException */
public static String convert(File file) throws IOException {
List<String> command = new ArrayList<String>();
command.add(FFMPEG_PATH);
command.add("-i");
command.add(file.getAbsolutePath());
command.add("-filter_complex");
command.add("volumedetect");
command.add("-c:v");
command.add("copy");
command.add("-f");
command.add("null");
command.add("/dev/null");
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
InputStream errorStream = process.getErrorStream();
InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
BufferedReader br = new BufferedReader(inputStreamReader);
String db = "";
while ((db = br.readLine()) != null) {
if (db.contains("max_volume")) {
db = db.split(": ")[1];
db = db.split(" ")[0];
break;
}
}
br.close();
inputStreamReader.close();
errorStream.close();
return db;
}
其实很简单相当于通过java调用linux命令来获取ffmpeg返回的结果。
PS:ffmpeg很强大,如果遇到类似的问题都是可以采用这种方式来取到我们需要的信息
原文作者:TsukasaHwan
原文地址: https://blog.csdn.net/weixin_49172831/article/details/108751304
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/weixin_49172831/article/details/108751304
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章