记于:2024-05-06 晚
地点:浙江省·温州市·家里
天气:多云
背景
业务需求上需要使用ffmpeg转码并获取其识别的音频时长。
代码
命令示例:
1
| ffmpeg -y -hide_banner -i input.wav output.wav
|
输出示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [aist#0:0/pcm_s16le @ 0x122f06af0] Guessed Channel Layout: mono Input Metadata: encoder : Lavf61.1.100 Duration: 00:00:07.86, bitrate: 256 kb/s Stream Stream mapping: Stream Press [q] to stop, [?] for help Output Metadata: ISFT : Lavf61.1.100 Stream Metadata: encoder : Lavc61.3.100 pcm_s16le [out#0/wav @ 0x6000002c8180] video:0KiB audio:246KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.031011% size= 246KiB time=00:00:07.86 bitrate= 256.1kbits/s speed=7.04e+03x
|
Duration: 00:00:07.86 即为音频时长。
接下来使用Java代码调用 ffmpeg 命令,并解析输出信息获取音频时长。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
public Double transcoding(String ffmpegPath, String input, String output) { String info = output + ".info"; FileUtil.touch(info); String[] ffmpegCommand = { ffmpegPath, "-hide_banner", "-y", "-i", input, output, "2>&1 | cat >", info }; List<String> listCommand = CollUtil.newArrayList(ffmpegCommand);
String finalCommandStr = StrUtil.join(" ", listCommand); log.info("finalCommandStr: {}", finalCommandStr);
int exitCode = -1; try {
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", String.join(" ", listCommand)); Process process = pb.inheritIO().start(); exitCode = process.waitFor(); process.destroy(); } catch (Exception e) { e.printStackTrace(); }
log.info("exitCode: {}", exitCode);
Double length = this.getAudioLength(info); FileUtil.del(info);
return length; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
private Double getAudioLength(String infoFile) { Double durationInSeconds = null;
List<String> lines = FileUtil.readLines(infoFile, "UTF-8"); for (String line : lines) { if (line.contains("Duration:")) { String durationLine = line.trim(); String durationPart = durationLine.split("Duration:")[1].trim().split(",")[0].trim();
String[] timeParts = durationPart.split(":"); double hours = Double.parseDouble(timeParts[0]); double minutes = Double.parseDouble(timeParts[1]); double seconds = Double.parseDouble(timeParts[2]); double milliseconds = (hours * 3600 + minutes * 60 + seconds) * 1000;
durationInSeconds = milliseconds / 1000.0; } } return durationInSeconds; }
|
注意:
- ffmpeg命令的输出信息是输出到标准错误流的,所以将标准错误重定向到标准输出流,然后通过管道配合cat命令将标准输出流输出到文件中;(尝试过使用process.getOutputStream()和process.getErrorStream(),但是无法获取到输出信息,所以使用了重定向的方式)
- 输出文件的中间目录如果不存在,需要提前创建;
补充(2024-05-20):ffprobe命令专门用于检测多媒体文件的信息。