FFMPEG是特别强大的专门用于处理音视频的开源库。你既可以使用它的API对音视频进行处理,也可以使用它提供的工具,如ffmpeg, ffplay, ffprobe,来编辑你的音视频文件。
本文主要使用ffmepg进行图像的压缩,以及视频的抽帧。
抽帧:
cmd = "ffmpeg -i %s -y -vframes 1 -vf scale=%d:%d/a %s";
-
ffmpeg
: 这是调用 FFmpeg 程序的命令。 -
-i %s
: 输入文件的路径,%s
是一个占位符,通常表示视频文件路径。 -
-y
: 自动覆盖输出文件(如果已存在),避免手动确认。 -
-vframes 1
: 指定提取1帧图片,1
表示只提取一帧。 -
-vf scale=%d:%d/a
:-
-vf
是 FFmpeg 的视频过滤器选项,这里用于缩放图像。 -
scale=%d:%d/a
是缩放过滤器,%d
表示目标宽度和高度,/a
用来保持输入视频的宽高比。意思是,宽度指定为%d
,而高度按比例缩放,使得图像不变形。
-
-
%s
: 输出文件路径的占位符,用来指定生成的图片文件路径。
服务层:
ScaleFilter.createCover4Video(new File(targetFilePath), Constants.LENGTH_150, new File(coverPath));
调用createCover4Video方法
public static void createCover4Video(File sourceFile, Integer width, File targetFile) {
try {
//抽取视频中的第一帧
String cmd = "ffmpeg -i %s -y -vframes 1 -vf scale=%d:%d/a %s";
ProcessUtils.executeCommand(String.format(cmd, sourceFile.getAbsoluteFile(), width, width, targetFile.getAbsoluteFile()), false);
} catch (Exception e) {
logger.error("生成视频封面失败", e);
}
}
创建线程
public static String executeCommand(String cmd, Boolean outprintLog) throws BusinessException {
if (StringTools.isEmpty(cmd)) {
logger.error("--- 指令执行失败,因为要执行的FFmpeg指令为空! ---");
return null;
}
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = Runtime.getRuntime().exec(cmd);
// 执行ffmpeg指令
// 取出输出流和错误流的信息
// 注意:必须要取出ffmpeg在执行命令过程中产生的输出信息,如果不取的话当输出流信息填满jvm存储输出留信息的缓冲区时,线程就回阻塞住
PrintStream errorStream = new PrintStream(process.getErrorStream());
PrintStream inputStream = new PrintStream(process.getInputStream());
//启动读取输出流和错误流的线程
errorStream.start();
inputStream.start();
// 等待ffmpeg命令执行完
process.waitFor();
// 获取执行结果字符串
String result = errorStream.stringBuffer.append(inputStream.stringBuffer + "\n").toString();
// 输出执行的命令信息
if (outprintLog) {
logger.info("执行命令:{},已执行完毕,执行结果:{}", cmd, result);
} else {
logger.info("执行命令:{},已执行完毕", cmd);
}
return result;
} catch (Exception e) {
// logger.error("执行命令失败:{} ", e.getMessage());
e.printStackTrace();
throw new BusinessException("视频转换失败");
} finally {
if (null != process) {
ProcessKiller ffmpegKiller = new ProcessKiller(process);
runtime.addShutdownHook(ffmpegKiller);
}
}
}
图像压缩:
cmd = "ffmpeg -i %s -vf scale=%d:-1 %s -y";
-
ffmpeg
: 调用 FFmpeg 程序进行视频处理。 -
-i %s
: 输入文件路径,%s
是一个占位符,表示视频文件的路径。 -
-vf scale=%d:-1
:-
-vf
表示应用视频过滤器(video filter)。 -
scale=%d:-1
表示对视频进行缩放:-
%d
是目标宽度的占位符,用实际数值替换。 -
-1
表示高度按比例自动计算,以保持原视频的宽高比不变。
-
-
-
%s
: 输出文件路径的占位符,用实际的文件路径替换。 -
-y
: 自动覆盖已有的输出文件(如果存在),避免提示确认。
public static void compressImage(File sourceFile, Integer width, File targetFile, Boolean delSource) {
try {
String cmd = "ffmpeg -i %s -vf scale=%d:-1 %s -y";
ProcessUtils.executeCommand(String.format(cmd, sourceFile.getAbsoluteFile(), width, targetFile.getAbsoluteFile()), false);
if (delSource) {
FileUtils.forceDelete(sourceFile);
}
} catch (Exception e) {
logger.error("压缩图片失败");
}
}