近期接到一个音频转换的需求,涉及音频信息获取、格式转换、采样率、比特率、声道数量改变,现将具体demo分享给大家。
首先先安装ffmpeg,安装后的bin目录如下所示:
我们主要用ffprobe、ffmpeg这两个执行程序,其中ffprobe用于获取音频流信息、ffmpeg用于音频转换,下面直接上代码
public String getAudioInformation(String filePath) {
Runtime run = null;
Process p = null;
try {
run = Runtime.getRuntime();
p = run.exec("ffprobe -v quiet -show_format -show_streams -print_format json " + filePath);
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String lineStr;
while ((lineStr = inBr.readLine()) != null) {
sb.append(lineStr);
}
if (p.waitFor() != 0) {
if (p.exitValue() == 1)
log.error("命令执行失败!");
return null;
}
return sb.toString();
} catch (Exception e) {
log.error("msg=getAudioInformation异常:{}", e.getMessage(), e);
} finally {
try {
p.getOutputStream().close();
p.getInputStream().close();
p.getErrorStream().close();
run.freeMemory();
} catch (IOException e) {
log.error("msg=getAudioInformation异常:{}", e.getMessage(), e);
}
}
return null;
}
@Test
public void getAudioInformation() {
String filePath = "/Users/hetao/Desktop/Ensoniq-ZR-76-01-Dope-77.wav";
log.info("audioInformation:{}", ffmpegUtil.getAudioInformation(filePath));
}
格式化后的结果:
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s16le",
"codec_long_name": "PCM signed 16-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 2,
"bits_per_sample": 16,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"duration_ts": 137095,
"duration": "3.108730",
"bit_rate": "1411200",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "/Users/hetao/Desktop/Ensoniq-ZR-76-01-Dope-77.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "3.108730",
"size": "548500",
"bit_rate": "1411508",
"probe_score": 99,
"tags": {
"artist": "freewavesamples.com",
"title": "test",
"encoder": "Lavf58.45.100"
}
}
}
public void waveMaker(String sourcePath, String targetPath) {
Runtime run = null;
Process p = null;
try {
run = Runtime.getRuntime();
//-ac 1:声道数量转成1 -ar 22050:采样率转成22050Hz -ab 64k:比特率转成64kb
//格式通过targetPath后缀自动识别转换
String command = "ffmpeg -i " + sourcePath + " -ac 1 -ar 22050 -ab 64k " + targetPath;
if (StringUtils.isBlank(command)) {
return;
}
p = run.exec(command);
p.waitFor();
log.info("sourcePath:{} convert to targetPath:{} success", sourcePath, targetPath);
} catch (Exception e) {
log.error("msg=waveMaker异常:{}", e.getMessage(), e);
} finally {
try {
p.getOutputStream().close();
p.getInputStream().close();
p.getErrorStream().close();
run.freeMemory();
} catch (IOException e) {
log.error("msg=waveMaker异常:{}", e.getMessage(), e);
}
}
}
@Test
public void waveMaker() {
String sourcePath = "/Users/hetao/Desktop/Ensoniq-ZR-76-01-Dope-77.wav";
String targetPath = "/Users/hetao/Desktop/Ensoniq-ZR-76-01-Dope-77.mp3";
ffmpegUtil.waveMaker(sourcePath, targetPath);
}
查看转换后的音频信息:
localhost:Desktop hetao$ pwd
/Users/hetao/Desktop
localhost:Desktop hetao$ ffmpeg -i Ensoniq-ZR-76-01-Dope-77.mp3
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.17)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.3.1_4 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100
Input #0, mp3, from 'Ensoniq-ZR-76-01-Dope-77.mp3':
Metadata:
artist : freewavesamples.com
title : test
encoder : Lavf58.45.100
Duration: 00:00:03.19, start: 0.050113, bitrate: 64 kb/s
Stream #0:0: Audio: mp3, 22050 Hz, mono, fltp, 64 kb/s
注:
声道转换可能影响比特率的值
转换前后如果inputPath、outputPath路径一致,转换不生效(本地测试结果)
欢迎拍砖交流~