网上很多教程都是需要先在服务器上安装ffmpeg,这样做首先是后期维护非常麻烦,每到一个新环境都得先安装文件,windows还好,linux是非常麻烦的,还可能有权限不足的各种坑。
这里介绍一个包,核心就是将各个环境的ffmpeg打成jar包,只要引入就可以无视环境使用
但需要注意一点,最好将没用的环境的包排除出去,避免最终的jar包过大
Maven依赖
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>3.3.1</version>
<exclusions>
<!-- 排除windows 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-win32</artifactId>
</exclusion>
<!-- 排除linux 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-linux32</artifactId>
</exclusion>
<!-- 排除Mac系统-->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-osx64</artifactId>
</exclusion>
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-osxm1</artifactId>
</exclusion>
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-linux-arm32</artifactId>
</exclusion>
</exclusions>
</dependency>
测试代码(mp4格式转m3u8)
实现方式就是构造出需要执行的指令,和正常操作ffmpeg一样
public static void main(String[] args) {
String filePathName = System.getProperty("user.dir")+"/file/xxx.mp4";
String m3u8FileName = System.getProperty("user.dir") + "/file/xxx.m3u8";
String cmdString = "-y -v error -i {filePathName} -strict strict -f hls -preset ultrafast -acodec aac -ac 1 -vsync 2 -c:v copy -c:a copy -tune fastdecode -hls_time 10 -hls_list_size 0 -threads 12 {outputPath}";
cmdString = cmdString.replace("{filePathName}", filePathName);
cmdString = cmdString.replace("{outputPath}",m3u8FileName);
Integer code = cmdExecut(cmdString);
System.out.println(String.format("获取最终执行结果:%s", code == 0 ? "成功!" : "失败!"));
}
/**
*
* @Description: (执行ffmpeg自定义命令)
* @param: @param cmdStr
* @param: @return
* @return: Integer
* @throws
*/
public static Integer cmdExecut(String cmdStr) {
//code=0表示正常
Integer code = null;
FfmpegCmd ffmpegCmd = new FfmpegCmd();
/**
* 错误流
*/
InputStream errorStream = null;
try {
//destroyOnRuntimeShutdown表示是否立即关闭Runtime
//如果ffmpeg命令需要长时间执行,destroyOnRuntimeShutdown = false
ffmpegCmd.execute(false, true, cmdStr);
errorStream = ffmpegCmd.getErrorStream();
//打印过程
int len = 0;
while ((len=errorStream.read())!=-1){
log.info(String.valueOf(len));
}
//code=0表示正常
code = ffmpegCmd.getProcessExitCode();
} catch (Exception e) {
log.error("转码失败",e);
} finally {
//关闭资源
ffmpegCmd.close();
}
//返回
return code;
}
相关的类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ws.schild.jave.process.ProcessKiller;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FfmpegCmd {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/** The process representing the ffmpeg execution. */
private Process ffmpeg = null;
/**
* A process killer to kill the ffmpeg process with a shutdown hook, useful if the jvm execution
* is shutted down during an ongoing encoding process.
*/
private ProcessKiller ffmpegKiller = null;
/** A stream reading from the ffmpeg process standard output channel. */
private InputStream inputStream = null;
/** A stream writing in the ffmpeg process standard input channel. */
private OutputStream outputStream = null;
/** A stream reading from the ffmpeg process standard error channel. */
private InputStream errorStream = null;
/**
* Executes the ffmpeg process with the previous given arguments.
*
* @param destroyOnRuntimeShutdown destroy process if the runtime VM is shutdown
* @param openIOStreams Open IO streams for input/output and errorout, should be false when
* destroyOnRuntimeShutdown is false too
* @param ffmpegCmd windows such as (mp4 transform to mov):
* " -i C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer.mp4 -c copy C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer_test.mov "
* @throws IOException If the process call fails.
*/
public void execute(boolean destroyOnRuntimeShutdown, boolean openIOStreams, String ffmpegCmd) throws IOException {
DefaultFFMPEGLocator defaultFFMPEGLocator = new DefaultFFMPEGLocator();
StringBuffer cmd = new StringBuffer(defaultFFMPEGLocator.getExecutablePath());
//insert blank for delimiter
cmd.append(" ");
cmd.append(ffmpegCmd);
String cmdStr = String.format("ffmpegCmd final is :%s", cmd.toString());
System.out.println(cmdStr);
logger.info(cmdStr);
Runtime runtime = Runtime.getRuntime();
try {
ffmpeg = runtime.exec(cmd.toString());
if (destroyOnRuntimeShutdown) {
ffmpegKiller = new ProcessKiller(ffmpeg);
runtime.addShutdownHook(ffmpegKiller);
}
if (openIOStreams) {
inputStream = ffmpeg.getInputStream();
outputStream = ffmpeg.getOutputStream();
errorStream = ffmpeg.getErrorStream();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns a stream reading from the ffmpeg process standard output channel.
*
* @return A stream reading from the ffmpeg process standard output channel.
*/
public InputStream getInputStream() {
return inputStream;
}
/**
* Returns a stream writing in the ffmpeg process standard input channel.
*
* @return A stream writing in the ffmpeg process standard input channel.
*/
public OutputStream getOutputStream() {
return outputStream;
}
/**
* Returns a stream reading from the ffmpeg process standard error channel.
*
* @return A stream reading from the ffmpeg process standard error channel.
*/
public InputStream getErrorStream() {
return errorStream;
}
/** If there's a ffmpeg execution in progress, it kills it. */
public void destroy() {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable t) {
logger.warn("Error closing input stream", t);
}
inputStream = null;
}
if (outputStream != null) {
try {
outputStream.close();
} catch (Throwable t) {
logger.warn("Error closing output stream", t);
}
outputStream = null;
}
if (errorStream != null) {
try {
errorStream.close();
} catch (Throwable t) {
logger.warn("Error closing error stream", t);
}
errorStream = null;
}
if (ffmpeg != null) {
ffmpeg.destroy();
ffmpeg = null;
}
if (ffmpegKiller != null) {
Runtime runtime = Runtime.getRuntime();
runtime.removeShutdownHook(ffmpegKiller);
ffmpegKiller = null;
}
}
/**
* Return the exit code of the ffmpeg process If the process is not yet terminated, it waits for
* the termination of the process
*
* @return process exit code
*/
public int getProcessExitCode() {
// Make sure it's terminated
try {
ffmpeg.waitFor();
} catch (InterruptedException ex) {
logger.warn("Interrupted during waiting on process, forced shutdown?", ex);
}
return ffmpeg.exitValue();
}
/**close**/
public void close() {
destroy();
}
}