• Java调用FFmpeg


    1、FFmepg基础知识

    About FFmpeg
    ffmpeg(计算机程序) - 百度百科
    FFmpeg/FFmpeg - GitHub
    CSDN:FFmpeg 基础知识 @在奋斗的大道

    关于FFmpeg
    FFmpeg是领先的多媒体框架,能够解码,编码, 转码,复用,解复用,流,过滤和播放几乎任何东西 人类和机器创造的。它支持最晦涩的 古老的格式直到最前沿。不管他们是不是 由一些标准委员会,社区或公司设计。是的 而且高度可移植:FFmpeg 编译、运行并通过我们的测试基础设施 FATE 跨 Linux、Mac OS X、 Microsoft Windows,BSD,Solaris等在各种各样的构建下 环境、计算机体系结构和配置。

    它包含libavcodeclibavutillibavformatlibavfilterlibavdevicelibswscalelibswresample 可供应用程序使用。 以及ffmpeg,ffplay和ffprobe,可用于 最终用户进行转码和播放。

    FFmpeg项目试图提供最好的技术可能 适用于应用程序开发人员和最终用户的解决方案。要实现 我们结合了可用的最佳免费软件选项。我们稍微 支持我们自己的代码,以保持对其他库的依赖较低,并 最大化 FFmpeg 各部分之间的代码共享。 凡是“最好”的问题无法回答的地方,我们都支持两者 选项,以便最终用户可以选择。

    FFmpeg 欢迎所有人,也欢迎所有贡献。 我们很高兴收到补丁,拉取请求,错误报告,捐赠 或任何其他类型的贡献。

    安全性是重中之重,代码审查始终使用 牢记安全性。虽然由于大量的代码接触 不受信任的数据安全问题是不可避免的,因此我们提供 在以下情况下尽快更新到我们上一个稳定版本 发现新的安全问题。


    FFmpeg 工具


    面向开发人员的 FFmpeg 库

    • libavutil 是一个包含函数的库 简化编程,包括随机数生成器、数据 结构、数学例程、核心多媒体实用程序等等 更多。
    • libavcodec是一个包含解码器和编码器的库 用于音频/视频编解码器。
    • libavformat 是一个包含解复用器和 用于多媒体容器格式的复用器。
    • libavdevice 是一个包含输入和输出的库 用于抓取和渲染许多常见多媒体的设备 输入/输出软件框架,包括Video4Linux,Video4Linux2, VfW和ALSA。
    • libavfilter 是一个包含媒体过滤器的库。
    • libswscale 是一个执行高度优化图像的库 缩放和色彩空间/像素格式转换操作。
    • libswresample 是一个执行高度优化的库 音频重新采样、重新矩阵和样本格式转换操作。

    1.1 下载 FFmpeg

    Download FFmpeg

    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.avi600x800播放
    • 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执行命令方法: ( 工具类:org.apache.commons:commons-exec )
    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    Java通过流获取命令输出结果可能会存在缓存的问题。当使用Java通过Runtime.getRuntime().exec等方法执行指令时,命令本身的输出结果是通过标准输出流(stdout)和标准错误流(stderr)来输出的。而Java读取输出结果的方式是通过获取进程的标准输出流/标准错误流来进行读取的。但当命令输出比较多时,标准输出流和标准错误流会同时存在一定大小的缓存区,如果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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    • 调用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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1> 这里比较奇怪,输出结果在process.getErrorStream()获取
    2> 可以研究一下ProcessBuilderJava ProcessBuilder类源码分析(开发“Java命令执行器”前期准备)
    3> 建议使用线程池ExecutorService、Executors

  • 相关阅读:
    MyBatis底层源码分析
    深入探究深度学习、神经网络与卷积神经网络以及它们在多个领域中的应用
    vue3 tsx 写法下,一个有趣的、基础的渲染问题
    算法刷题总结 (一) 数组
    常用射频接头之2.92mm
    ORB-SLAM2 ---- ExtractorNode::DivideNode函数
    重学操作系统(一)操作系统概述
    String的实例化及内存解析
    sonic云真机通过linux系统接入苹果手机
    我们为什么需要 DAO 操作系统?
  • 原文地址:https://blog.csdn.net/qq_23452385/article/details/133832315