本人使用java封装的后端媒体处理工具包
基于ImageMagick和FFmpeg客户端,使用java调用命令行实现
https://gitee.com/gnliscream/multimedia-utils
介绍
java后端的图片、视频处理工具jar包
1.获取视频信息
2.生成视频封面图
3.异步压缩视频(生成输出文件名后,调用异步压缩视频方法,且同一时间只会处理一个视频,多个请求的视频会进行排队处理)
4.异步压缩视频完成时回调通知
5.图片裁切
6.图片压缩
客户端安装
运行环境需安装FFmpeg和ImageMagick,官网地址如下:
FFmpeg:https://ffmpeg.org/
ImageMagick:http://www.imagemagick.com.cn/
FFmpeg解压后需设置/bin目录的环境变量,ImageMagick安装版安装后会自动设置环境变量。
引入依赖
<dependency>
<groupId>com.whty.zdxt</groupId>
<artifactId>multimedia-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
配置
yml 配置上传文件的临时路径
spring:
servlet:
multipart:
# 是否支持 multipart 上传文件
enabled: true
# 最大支持文件大小
max-file-size: 10MB
# 最大支持请求大小
max-request-size: 10MB
# 上传文件的临时目录
location: E:/tomcat-temp
注入 视频处理类FFmpegUtils 以及 图片处理类 ImageMagickUtils
import com.whty.zdxt.multimedia.util.FFmpegUtils;
import com.whty.zdxt.multimedia.util.ImageMagickUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class MultimediaUtilsConfig {
/**
* 视频处理工具,因为所有压缩任务需要排队进行,所以FFmpegUtils需要是单例的,FFmpegUtils实例交由spring管理就为单例的
*/
@Bean
public FFmpegUtils fFmpegUtilsImpl() {
return new FFmpegUtils();
}
/**
* 图片处理工具
*/
@Bean
public ImageMagickUtils imageMagickUtils() {
return new ImageMagickUtils();
}
}
使用
FileController
import com.example.demo.util.FileUtil;
import com.whty.zdxt.multimedia.attribute.CompressionAttributes;
import com.whty.zdxt.multimedia.attribute.CropAttributes;
import com.whty.zdxt.multimedia.attribute.ResizeAttributes;
import com.whty.zdxt.multimedia.attribute.VideoAttributes;
import com.whty.zdxt.multimedia.enumeration.Suffix;
import com.whty.zdxt.multimedia.enumeration.VideoSize;
import com.whty.zdxt.multimedia.pojo.FFmpegInfo;
import com.whty.zdxt.multimedia.util.FFmpegUtils;
import com.whty.zdxt.multimedia.util.ImageMagickUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@RestController
@RequestMapping("/file")
public class FileController {
@Autowired
private FFmpegUtils fFmpegUtils;
@Autowired
private MultipartProperties multipartProperties;
@Autowired
private ImageMagickUtils imageMagickUtils;
/**
* 获取视频信息
*/
@PostMapping("/getVideoInfo")
public Object getFileInfo(@RequestParam MultipartFile file) {
String location = multipartProperties.getLocation();
// 生成上传视频的临时文件
File inputFile = FileUtil.multipartFile2File(file, location);
// 调用视频处理工具类
String inputFileName = inputFile.getName();
FFmpegInfo info = fFmpegUtils.getInfo(location, inputFileName);
// 删除上传视频的临时文件
inputFile.delete();
return info;
}
/**
* 生成视频封面图
*/
@PostMapping("/createVideoCover")
public Object createVideoCover(@RequestParam MultipartFile file) {
String location = multipartProperties.getLocation();
// 生成上传视频的临时文件
File inputFile = FileUtil.multipartFile2File(file, location);
// 调用视频处理工具类
String outputFileName = fFmpegUtils.createCover(location, inputFile.getName());
// 删除上传视频的临时文件
inputFile.delete();
return outputFileName;
}
/**
* 压缩视频
*/
@PostMapping("/compressionVideo")
public Object compressionVideo(@RequestParam MultipartFile file) {
String location = multipartProperties.getLocation();
// 生成上传视频的临时文件
File inputFile = FileUtil.multipartFile2File(file, location);
// 调用视频处理工具类
CompressionAttributes compressionAttributes = new CompressionAttributes();
// 设置视频压缩完成时的回调URL
compressionAttributes.setProgressUrl("http://localhost:8999/file/callback?fileId=111111&a=456");
// 设置视频压缩参数
VideoAttributes videoAttributes = new VideoAttributes();
videoAttributes.setMaxDuration(15);
videoAttributes.setMaxFps(20);
videoAttributes.setVideoSize(VideoSize.HD480);
compressionAttributes.setVideoAttributes(videoAttributes);
String outputFileName = fFmpegUtils.putCompressionTask(location, inputFile.getName(), compressionAttributes);
return outputFileName;
}
/**
* 压缩视频完成时的回调
*/
@PostMapping("/callback")
public Object callback(@RequestBody String info, @RequestParam("fileId") String fileId, @RequestParam("a") String a) {
// 回调信息
String[] split = info.split("/");
// 回调参数 fileId,根据fileId查询数据库的上传临时文件名和下载临时文件名,进行文件上传和文件删除
System.out.println(String.format("fileId为%s的文件已压缩完成", fileId));
return null;
}
/**
* 图片裁切
*/
@PostMapping("/crop")
public Object crop(@RequestParam MultipartFile file) {
String location = multipartProperties.getLocation();
// 生成上传图片的临时文件
File inputFile = FileUtil.multipartFile2File(file, location);
// 调用图片处理工具类
// 裁切成3000x1200的图后,修改分辨率为宽800的图(高度按比例缩小)
CropAttributes cropAttributes = new CropAttributes(3000, 1200, 1000, 500);
ResizeAttributes resizeAttributes = new ResizeAttributes(800, null);
String outputFileName = imageMagickUtils.cropAndResize(location, inputFile.getName(), cropAttributes, resizeAttributes);
// 删除上传图片的临时文件
inputFile.delete();
return outputFileName;
}
/**
* 图片分辨率修改
*/
@PostMapping("/resize")
public Object resize(@RequestParam MultipartFile file) {
String location = multipartProperties.getLocation();
// 生成上传图片的临时文件
File inputFile = FileUtil.multipartFile2File(file, location);
// 调用图片处理工具类
ResizeAttributes resizeAttributes = new ResizeAttributes(800, null);
String outputFileName = imageMagickUtils.resize(location, inputFile.getName(), resizeAttributes, Suffix.JPG);
// 删除上传图片的临时文件
inputFile.delete();
return outputFileName;
}
}
FileUtil
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
public class FileUtil {
/**
* 将上传的MultipartFile转化为File
*/
public static File multipartFile2File(MultipartFile multipartFile, String directory) {
String suffix = getSuffix(multipartFile.getOriginalFilename());
File tempFile = null;
try {
tempFile = new File(directory + "/" + UUID.randomUUID().toString() + suffix);
multipartFile.transferTo(tempFile);
} catch (IOException e) {
throw new RuntimeException("multipartFile转File失败", e);
}
return tempFile;
}
/**
* 获取文件拓展名
*/
public static String getSuffix(String fileName) {
if (fileName == null) {
throw new RuntimeException("获取文件拓展名失败");
}
int index = fileName.lastIndexOf(".");
if (-1 == index) {
throw new RuntimeException("获取文件拓展名失败");
}
return fileName.substring(index);
}
}
文档
图片工具ImageMagickUtils
方法
1.图片裁切后修改分辨率并指定输出文件格式
cropAndResize(tempDirectory,inputFileName,cropAttributes,resizeAttributes,outputFileSuffix)
2.图片裁切后修改分辨率
cropAndResize(tempDirectory,inputFileName,cropAttributes,resizeAttributes)
3.图片裁切并指定输出文件格式
crop(tempDirectory,inputFileName,cropAttributes,outputFileSuffix)
4.图片裁切
crop(tempDirectory,inputFileName,cropAttributes)
5.图片修改分辨率并指定输出文件格式
resize(tempDirectory,inputFileName,resizeAttributes,outputFileSuffix)
6.图片修改分辨率
resize(tempDirectory,inputFileName,resizeAttributes)
参数介绍
输入参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
tempDirectory | String | 是 | 临时文件目录 |
inputFileName | String | 是 | 输入文件名 |
cropAttributes | CropAttributes | 否 | 裁切参数 |
resizeAttributes | ResizeAttributes | 否 | 修改分辨率参数 |
outputFileSuffix | Suffix | 否 | 输出文件格式,未设置则同输入文件格式 |
其中:
CropAttributes
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
width | Integer | 是 | 裁切图片的宽 |
height | Integer | 是 | 裁切图片的高 |
leftOffset | Integer | 是 | 距左边偏移量 |
topOffset | Integer | 是 | 距顶部偏移量 |
ResizeAttributes
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
width | Integer | 否 | 输出图片的宽,只填写宽则高自适应 |
height | Integer | 否 | 输出图片的高,只填写高则宽自适应 |
quality | Integer | 否 | 输出图片的质量,范围0~100,默认100 |
输出参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
outputFileName | String | 是 | 输出文件名 |
视频工具FFmpegUtils
方法
1.获取视频信息
getInfo(tempDirectory,inputFileName)
输入参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
tempDirectory | String | 是 | 临时文件目录 |
inputFileName | String | 是 | 输入文件名 |
输出参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
format | FFFormat | 是 | 文件信息 |
videoInfo | VideoInfo | 是 | 视频信息 |
audioInfo | AudioInfo | 是 | 音频信息 |
其中:
FFFormat
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
filename | String | 是 | 文件名全路径名 |
duration | String | 是 | 文件时长 |
size | String | 是 | 文件大小 |
bitRate | String | 是 | 文件比特率 |
VideoInfo
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
codecName | String | 是 | 视频 编码名称 |
codecType | String | 是 | 类型 video |
width | Integer | 是 | 视频 宽度 |
height | Integer | 是 | 视频 高度 |
frameRate | Integer | 是 | 视频 帧率 |
duration | Integer | 是 | 视频 时长 |
bitRate | Integer | 是 | 视频 比特率 |
nbFrames | Integer | 是 | 视频 总帧数 |
AudioInfo
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
codecName | String | 是 | 音频 编码名称 |
codecType | String | 是 | 类型 audio |
duration | Integer | 是 | 音频 时长 |
bitRate | Integer | 是 | 音频 比特率 |
sampleRate | Integer | 是 | 音频 采样率 |
channels | Integer | 是 | 音频 声道数 1:单声道 2:双声道 |
2.截取视频封面
createCover(tempDirectory, inputFileName, outputFileSuffix)
createCover(tempDirectory, inputFileName)
输入参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
tempDirectory | String | 是 | 临时文件目录 |
inputFileName | String | 是 | 输入文件名 |
outputFileSuffix | Suffix | 否 | 输出文件格式,默认jpg |
输出参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
outputFileName | String | 是 | 输出文件名 |
3.视频压缩
putCompressionTask(tempDirectory, inputFileName, compressionAttributes)
putCompressionTask(tempDirectory, inputFileName, compressionAttributes, outputFileName)
输入参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
tempDirectory | String | 是 | 临时文件目录 |
inputFileName | String | 是 | 输入文件名 |
compressionAttributes | CompressionAttributes | 是 | 压缩参数 |
outputFileName | String | 否 | 输出文件名,默认UUID生成 |
其中:
CompressionAttributes
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
videoAttributes | VideoAttributes | 否 | 视频压缩参数 |
audioAttributes | AudioAttributes | 否 | 音频压缩参数 |
progressUrl | String | 是 | 压缩完成后的回调地址 |
VideoAttributes
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
codec | VideoCodec | 否 | 视频编码(默认libx264,libx265) |
maxFps | Integer | 否 | 最大帧率 |
videoSize | VideoSize | 否 | 视频分辨率(hd480,hd720,hd1080,800x800) |
maxDuration | Integer | 否 | 最大时长 |
maxBitRate | Integer | 否 | 视频最大比特率 |
AudioAttributes
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
maxBitRate | Integer | 否 | 音频最大比特率 |
maxSamplingRate | Integer | 否 | 音频最大采样率 |
输出参数
参数 | 类型 | 必需 | 注释 |
---|---|---|---|
outputFileName | String | 是 | 输出文件名 |
ImageMagick官网
http://www.imagemagick.com.cn/
命令行
图片裁切
magick 1.jpg -crop 3000x1200+1000+500 2.jpg
1.jpg 为6000x4500的图片
3000x1200 裁切后图片的宽x高
+1000 裁切横坐标偏移量
+500 裁切纵坐标偏移量
2.jpg 为裁切后的3000x1200的图片
图片压缩
指定分辨率压缩
magick 1.jpg -resize 3000x2250 2.jpg
给定宽度,高度自动选择以保留宽高比。
magick 1.jpg -resize 3000 2.jpg
给定高度,自动选择宽度以保留宽高比。
magick 1.jpg -resize x2250 2.jpg
FFmpeg官网
https://ffmpeg.org/ffmpeg.html#Advanced-options
命令行
查询视频信息
ffprobe -v quiet -print_format json -show_format -show_streams 1.mp4
设置帧率 -r
ffmpeg –i input.mp4 –r fps output.mp4
设置码率 音频:-b:a 视频: - b:v
ffmpeg -i input.avi -b:v 1500k output.mp4
设置分辨率
ffmpeg -i input.mp4 -s 320x240 output.mp4
设置声道和采样率
-ac 1 设置声道数为1
-ar 48000 设置采样率为48000Hz
截取视频生成图片
从第-ss秒开始,每秒截取-r张图片,持续-t秒,使用-s进行缩放,保存为foo-001.jpeg, foo-002.jpeg...
ffmpeg -i 1.mp4 -ss 5 -r 1 -t 1 -s hd480 -f image2 foo-%03d.jpeg
网上的开源框架
https://github.com/a-schild/jave2
网上的相关资料
https://www.jianshu.com/p/e14bc2551cfd
https://www.jianshu.com/p/3c8c4a892f3c
https://blog.csdn.net/u010629285/article/details/102998555