Java调用FFmpeg
- 1、FFmepg基础知识
- 1.1 下载 FFmpeg
- 1.2 FFmpeg 工具使用
- 2、Java使用
- 2.1 FFmpeg源码编译
- 2.2 Java集成FFmpeg
- 2.2.1 JNI
- 2.2.2 Java调用执行 FFmpeg 工具 命令
1、FFmepg基础知识
About FFmpeg
ffmpeg(计算机程序) - 百度百科
FFmpeg/FFmpeg - GitHub
CSDN:FFmpeg 基础知识 @在奋斗的大道
关于FFmpeg
FFmpeg是领先的多媒体框架,能够解码,编码, 转码,复用,解复用,流,过滤和播放几乎任何东西 人类和机器创造的。它支持最晦涩的 古老的格式直到最前沿。不管他们是不是 由一些标准委员会,社区或公司设计。是的 而且高度可移植:FFmpeg 编译、运行并通过我们的测试基础设施 FATE 跨 Linux、Mac OS X、 Microsoft Windows,BSD,Solaris等在各种各样的构建下 环境、计算机体系结构和配置。它包含
libavcodec,libavutil,libavformat,libavfilter,libavdevice,libswscale和libswresample可供应用程序使用。 以及ffmpeg,ffplay和ffprobe,可用于 最终用户进行转码和播放。
FFmpeg项目试图提供最好的技术可能 适用于应用程序开发人员和最终用户的解决方案。要实现 我们结合了可用的最佳免费软件选项。我们稍微 支持我们自己的代码,以保持对其他库的依赖较低,并 最大化FFmpeg各部分之间的代码共享。 凡是“最好”的问题无法回答的地方,我们都支持两者 选项,以便最终用户可以选择。
FFmpeg欢迎所有人,也欢迎所有贡献。 我们很高兴收到补丁,拉取请求,错误报告,捐赠 或任何其他类型的贡献。安全性是重中之重,代码审查始终使用 牢记安全性。虽然由于大量的代码接触 不受信任的数据安全问题是不可避免的,因此我们提供 在以下情况下尽快更新到我们上一个稳定版本 发现新的安全问题。
FFmpeg 工具
- FFMPEG 用于转换多媒体文件的 命令行工具 格式之间
- ffplay 基于 SDL 和 FFmpeg 库的简单媒体播放器
- FF探针 一个简单的多媒体流分析仪
面向开发人员的 FFmpeg 库
- libavutil 是一个包含函数的库 简化编程,包括随机数生成器、数据 结构、数学例程、核心多媒体实用程序等等 更多。
- libavcodec是一个包含解码器和编码器的库 用于音频/视频编解码器。
- libavformat 是一个包含解复用器和 用于多媒体容器格式的复用器。
- libavdevice 是一个包含输入和输出的库 用于抓取和渲染许多常见多媒体的设备 输入/输出软件框架,包括Video4Linux,Video4Linux2, VfW和ALSA。
- libavfilter 是一个包含媒体过滤器的库。
- libswscale 是一个执行高度优化图像的库 缩放和色彩空间/像素格式转换操作。
- libswresample 是一个执行高度优化的库 音频重新采样、重新矩阵和样本格式转换操作。
1.1 下载 FFmpeg
Download FFmpeg
-
Windows EXE Files:Windows builds from gyan.dev、Windows builds by BtbN

-
FFmpeg Source Code:ffmpeg-6.0.tar.xz

1.2 FFmpeg 工具使用
ffmpeg\bin\ffmpeg.exe
| 命令 | 说明 |
|---|---|
ffmpeg -i input.avi | 查询视频信息 |
ffmpeg -i input.avi -hide_banner | 查询只显示视频信息 |
ffmpeg -i input.avi output.mp4 | 通过重新编码媒体流,将输入媒体文件转换为其他格式 |
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4 | 将输出文件的视频比特率设置为 64 kbit/s |
ffmpeg -i input.avi -r 24 output.mp4 | 强制输出文件的帧速率为 24 fps |
ffmpeg -r 1 -i input.m2v -r 24 output.mp4 | 强制输入文件的帧速率(仅对原始格式有效)为 1 fps,并且 输出文件的帧速率为 24 fps |
ffmpeg\bin\ffplay.exe
| 命令 | 说明 |
|---|---|
ffplay -i input.avi | 读取视频input.avi。不会自动退出,原比例播放 |
ffplay -autoexit input.avi | 视频播放完毕后退出。 |
ffplay -x 600 -y 800 input.avi | 以600x800播放 |
ffmpeg\bin\ffprobe.exe
| 命令 | 说明 |
|---|---|
ffprobe input.avi -hide_banner | 显示视频信息 |
ffprobe input.avi -hide_banner -show_format | 显示有关输入多媒体的容器格式的信息 |
ffprobe input.avi -hide_banner -show_format -print_format json | 以json数据显示有关输入多媒体的容器格式的信息 |
2、Java使用
2.1 FFmpeg源码编译
Windows下编译FFmpeg - 知乎
Windows编译和使用ffmpeg
2.2 Java集成FFmpeg
2.2.1 JNI
Java版流媒体编解码和图像处理(JavaCPP+FFmpeg)
Javacv使用ffmpeg实现音视频同步播放
Java通过JNI调用FFmpeg的c语言,Window上需要FFmpeg相应的
.dll文件,Linux上需要FFmpeg相应的.so文件
2.2.2 Java调用执行 FFmpeg 工具 命令
Java执行命令方法:
java/lang/Runtime.java
java/lang/ProcessBuilder.java// 执行命令Process process = Runtime.getRuntime().exec("cmd /c dir /b");// 获取命令输出结果BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {XLog.d(line);}// 等待命令执行完成process.waitFor();
Java通过流获取命令输出结果可能会存在缓存的问题。当使用Java通过Runtime.getRuntime().exec等方法执行指令时,命令本身的输出结果是通过标准输出流(stdout)和标准错误流(stderr)来输出的。而Java读取输出结果的方式是通过获取进程的标准输出流/标准错误流来进行读取的。但当命令输出比较多时,标准输出流和标准错误流会同时存在一定大小的缓存区,如果Java读取不及时,就可能无法获取到完整的输出结果。解决该问题可以采用多线程读取和行缓冲。即为程序开启一个线程去读取进程输出,每读取一行即将其写入缓冲中。这样就能解决输出结果获取不到的问题。
- 配置ffmpeg环境变量,命令找到ffmpeg程序
1、IOUtils使用apache的commons-io库
2、XLog使用Logger:Java原生日志工具
String osname = System.getProperty("os.name").toLowerCase();
XLog.d("osname = " + osname);
String cmd = osname.contains("windows") ? "where.exe ffmpeg" : "which ffmpeg";Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();String ffmpeg = IOUtils.toString(p.getInputStream(), Charset.defaultCharset()).trim();XLog.d(ffmpeg);

- 调用
ffmpeg -i input.avi -hide_banner:这里配置了环境变量,如ffmpeg\bin

Process process = Runtime.getRuntime().exec("ffmpeg -i C:\\Users\\Administrator\\Desktop\\input.avi -hide_banner");
process.waitFor();
String ffmpegGetInputStream = IOUtils.toString(process.getInputStream(), Charset.defaultCharset()).trim();
String ffmpegGetErrorStream = IOUtils.toString(process.getErrorStream(), Charset.defaultCharset()).trim();XLog.d("ffmpegGetInputStream: "+ffmpegGetInputStream);
XLog.d("ffmpegGetErrorStream: "+ffmpegGetErrorStream);
String osname = System.getProperty("os.name").toLowerCase();
XLog.d("osname = " + osname);
String cmd = osname.contains("windows") ? "where.exe ffmpeg" : "which ffmpeg";
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
String ffmpeg = IOUtils.toString(p.getInputStream(), Charset.defaultCharset()).trim();
XLog.d(ffmpeg);String[] cmdarray = new String[]{ffmpeg, "-i", "C:\\Users\\Administrator\\Desktop\\input.avi", "-hide_banner"};
Process process = Runtime.getRuntime().exec(cmdarray);
process.waitFor();
String ffmpegGetInputStream = IOUtils.toString(process.getInputStream(), Charset.defaultCharset()).trim();
String ffmpegGetErrorStream = IOUtils.toString(process.getErrorStream(), Charset.defaultCharset()).trim();
XLog.d("ffmpegGetInputStream: "+ffmpegGetInputStream);
XLog.d("ffmpegGetErrorStream: "+ffmpegGetErrorStream);
1> 这里比较奇怪,输出结果在
process.getErrorStream()获取
2> 可以研究一下ProcessBuilder:Java ProcessBuilder类源码分析(开发“Java命令执行器”前期准备)
3> 建议使用线程池ExecutorService、Executors
