一、概述
FFmpeg由C语言编写,因此也提供大量C的接口,涉及libavformat、libavcodec、libavfilter等库的接口,功能涵盖转封装、转码、滤镜等功能。因此调用FFmpeg由两种主流方式:
- 编码调用ffmpeg命令行
- 编码调用ffmpeg的API接口
二、Java命令行调用
在Java中提供了两种方法来调用诸如exe,shell这样的程序或脚本
- 使用Runtime的exec()方法
- 使用ProcessBuilder的start()方法
Runtime和ProcessBulider提供了不同的方式来启动程序,设置启动参数、环境变量和工作目录,但是这两种方法都会返回一个用于管理操作系统进程的Process对象。
正常情况下,我们调用命令行会返回process对象,通过waitFor方法等待该process表示的进程已经终止后,再继续执行。
java代码如下:
1 | public void test1(){ |
如果需要打印命令行执行结果,可获取process的inputStream。
1 | public void test2(){ |
当将命令换成ffmpeg命令时,当打印日志时,程序无法结束,似乎卡住了。
1 | public void test3(){ |
问题的关键在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。接着来分析缓冲区,哪来的这个东西,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。我们尝试在ffmpeg加上-v quiet不输出日志时,可正常转码,印证了这一问题。
改用
1 | public void test6(){ |