Java调用FFmpeg应使用Jave2而非Runtime.exec(),因其自动处理进程通信、路径空格、编码乱码、平台适配(如Windows需ffmpeg.exe)及错误捕获;常见错误多源于FFmpeg路径未显式配置或中文路径未转码。

Java里调用FFmpeg为什么别直接拼命令行
因为Runtime.getRuntime().exec()容易卡死、路径空格报错、编码乱码,还难捕获真实错误。Jave2本质是帮你把FFmpeg命令封装成Java对象,自动处理进程通信、临时文件、平台适配(Windows要.exe后缀,Linux/macOS没后缀),省得你反复调试ProcessBuilder的redirectErrorStream(true)和waitFor()超时逻辑。
常见错误现象:java.io.IOException: Cannot run program "ffmpeg": error=2, No such file or directory——不是Jave2问题,是你没配好FFmpeg可执行文件路径。
- 必须显式指定
FFMPEGLocator,不能依赖PATH;Windows下传"ffmpeg.exe",Linux/macOS传"ffmpeg" - 输入路径含中文或空格?用
new File("路径").getAbsolutePath()转绝对路径再传,别直接塞相对路径字符串 - Jave2默认不校验输入文件是否存在或是否为有效视频,转到一半才报
Invalid data found when processing input,建议转前先用AudioInfo/VideoInfo简单探测
Jave2转换MP4到AVI的基本写法
不是所有格式都能无损互转,MP4→AVI这种跨容器操作,核心是选对编码器。Jave2底层仍走FFmpeg命令,所以AudioAttributes和VideoAttributes实际映射到-c:a和-c:v参数。
使用场景:内部系统导出兼容老设备的AVI,不要求高压缩率,只要能播。
立即学习“Java免费学习笔记(深入)”;
-
VideoAttributes里设setCodec("msmpeg4v2")(AVI常用),别用"libx264"——那会生成MP4风格的AVI,很多播放器不认 -
AudioAttributes推荐setCodec("mp3"),"aac"在AVI里支持差,易出现音画不同步 - 分辨率/帧率不手动设的话,Jave2会照搬源文件,但AVI对高帧率(如60fps)兼容性弱,建议显式调用
setFrameRate(30)
Encoder encoder = new Encoder();
encoder.encode(
new MultimediaObject(new File("input.mp4")),
new File("output.avi"),
new EncodingAttributes()
.setFormat("avi")
.setVideoAttributes(new VideoAttributes()
.setCodec("msmpeg4v2")
.setBitRate(1000000)
.setSize(640, 480)
.setFrameRate(30))
.setAudioAttributes(new AudioAttributes()
.setCodec("mp3")
.setBitRate(128000))
);
转GIF时内存爆掉或颜色失真怎么救
Jave2转GIF本质是先抽帧再合成,VideoAttributes.setCodec("gif")只是告诉FFmpeg输出格式,真正控制质量的是调色板和帧间隔。默认行为会加载全部帧到内存,大视频直接OOM。
性能影响:1080p视频抽3秒(30帧)就可能吃掉500MB堆内存,且默认调色板只有256色,渐变区域出现明显色带。
- 强制限制帧数:
setFramesPerSecond(10)比默认的25更稳妥,再加setStartTimeInMillis(0)和setDurationInMillis(3000)限定范围 - 颜色修复必须加FFmpeg高级参数:
new EncodingAttributes().setCustomOptions("-vf \"fps=10,scale=320:-1:flags=lanczos,palettegen\" -lavfi \"fps=10,scale=320:-1:flags=lanczos [x]; [x][1:v] paletteuse\"")——注意这里palettegen和paletteuse必须成对,Jave2不自动补 - 别信
setQuality(0.8),GIF不走这个参数,它只对JPEG等有损格式生效
Windows上中文路径转码失败的真实原因
不是Java文件API问题,是FFmpeg.exe在Windows控制台默认用GBK读参数,而JavaString是UTF-16,Jave2传参时没做Charset.forName("GBK").encode()转换。现象是Invalid argument或输出文件名变成乱码。
兼容性影响:同一段代码在Linux/macOS跑得好好的,Windows必挂,开发者常误判为“Jave2不支持中文”。
- 最稳解法:转存为英文路径,用
Files.createTempDirectory("jave2_")建临时目录,把输入/输出文件copyTo()进去再处理 - 如果必须用原路径,Windows下手动转码:
String winPath = System.getProperty("os.name").toLowerCase().contains("win") ? new String(path.getBytes(StandardCharsets.UTF_8), Charset.forName("GBK")) : path;——但这只适用于简单路径,含特殊符号仍可能崩 - Jave2 3.2+开始支持
setEnvironmentVariables()传CHCP 65001,但需确保系统装了UTF-8语言包,生产环境慎用
FFmpeg参数细节和平台差异比Jave2 API本身复杂得多,别指望一个encode()调用包打天下。路径、编码、容器与编码器匹配这三块,漏掉任何一环都会在深夜收到告警。










