本人使用java封裝的后端媒體處理工具包
基于ImageMagick和FFmpeg客戶端汁咏,使用java調(diào)用命令行實現(xiàn)
https://gitee.com/gnliscream/multimedia-utils
介紹
java后端的圖片莲趣、視頻處理工具jar包
1.獲取視頻信息
2.生成視頻封面圖
3.異步壓縮視頻(生成輸出文件名后虑啤,調(diào)用異步壓縮視頻方法隙弛,且同一時間只會處理一個視頻,多個請求的視頻會進行排隊處理)
4.異步壓縮視頻完成時回調(diào)通知
5.圖片裁切
6.圖片壓縮
客戶端安裝
運行環(huán)境需安裝FFmpeg和ImageMagick狞山,官網(wǎng)地址如下:
FFmpeg:https://ffmpeg.org/
ImageMagick:http://www.imagemagick.com.cn/
FFmpeg解壓后需設置/bin目錄的環(huán)境變量全闷,ImageMagick安裝版安裝后會自動設置環(huán)境變量。
引入依賴
<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需要是單例的,F(xiàn)FmpegUtils實例交由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);
// 調(diào)用視頻處理工具類
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);
// 調(diào)用視頻處理工具類
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);
// 調(diào)用視頻處理工具類
CompressionAttributes compressionAttributes = new CompressionAttributes();
// 設置視頻壓縮完成時的回調(diào)URL
compressionAttributes.setProgressUrl("http://localhost:8999/file/callback?fileId=111111&a=456");
// 設置視頻壓縮參數(shù)
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;
}
/**
* 壓縮視頻完成時的回調(diào)
*/
@PostMapping("/callback")
public Object callback(@RequestBody String info, @RequestParam("fileId") String fileId, @RequestParam("a") String a) {
// 回調(diào)信息
String[] split = info.split("/");
// 回調(diào)參數(shù) fileId勘纯,根據(jù)fileId查詢數(shù)據(jù)庫的上傳臨時文件名和下載臨時文件名局服,進行文件上傳和文件刪除
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);
// 調(diào)用圖片處理工具類
// 裁切成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);
// 調(diào)用圖片處理工具類
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轉(zhuǎn)化為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轉(zhuǎn)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)
參數(shù)介紹
輸入?yún)?shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
tempDirectory | String | 是 | 臨時文件目錄 |
inputFileName | String | 是 | 輸入文件名 |
cropAttributes | CropAttributes | 否 | 裁切參數(shù) |
resizeAttributes | ResizeAttributes | 否 | 修改分辨率參數(shù) |
outputFileSuffix | Suffix | 否 | 輸出文件格式淫奔,未設置則同輸入文件格式 |
其中:
CropAttributes
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
width | Integer | 是 | 裁切圖片的寬 |
height | Integer | 是 | 裁切圖片的高 |
leftOffset | Integer | 是 | 距左邊偏移量 |
topOffset | Integer | 是 | 距頂部偏移量 |
ResizeAttributes
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
width | Integer | 否 | 輸出圖片的寬,只填寫寬則高自適應 |
height | Integer | 否 | 輸出圖片的高堤结,只填寫高則寬自適應 |
quality | Integer | 否 | 輸出圖片的質(zhì)量唆迁,范圍0~100,默認100 |
輸出參數(shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
outputFileName | String | 是 | 輸出文件名 |
視頻工具FFmpegUtils
方法
1.獲取視頻信息
getInfo(tempDirectory,inputFileName)
輸入?yún)?shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
tempDirectory | String | 是 | 臨時文件目錄 |
inputFileName | String | 是 | 輸入文件名 |
輸出參數(shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
format | FFFormat | 是 | 文件信息 |
videoInfo | VideoInfo | 是 | 視頻信息 |
audioInfo | AudioInfo | 是 | 音頻信息 |
其中:
FFFormat
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
filename | String | 是 | 文件名全路徑名 |
duration | String | 是 | 文件時長 |
size | String | 是 | 文件大小 |
bitRate | String | 是 | 文件比特率 |
VideoInfo
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
codecName | String | 是 | 視頻 編碼名稱 |
codecType | String | 是 | 類型 video |
width | Integer | 是 | 視頻 寬度 |
height | Integer | 是 | 視頻 高度 |
frameRate | Integer | 是 | 視頻 幀率 |
duration | Integer | 是 | 視頻 時長 |
bitRate | Integer | 是 | 視頻 比特率 |
nbFrames | Integer | 是 | 視頻 總幀數(shù) |
AudioInfo
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
codecName | String | 是 | 音頻 編碼名稱 |
codecType | String | 是 | 類型 audio |
duration | Integer | 是 | 音頻 時長 |
bitRate | Integer | 是 | 音頻 比特率 |
sampleRate | Integer | 是 | 音頻 采樣率 |
channels | Integer | 是 | 音頻 聲道數(shù) 1:單聲道 2:雙聲道 |
2.截取視頻封面
createCover(tempDirectory, inputFileName, outputFileSuffix)
createCover(tempDirectory, inputFileName)
輸入?yún)?shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
tempDirectory | String | 是 | 臨時文件目錄 |
inputFileName | String | 是 | 輸入文件名 |
outputFileSuffix | Suffix | 否 | 輸出文件格式竞穷,默認jpg |
輸出參數(shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
outputFileName | String | 是 | 輸出文件名 |
3.視頻壓縮
putCompressionTask(tempDirectory, inputFileName, compressionAttributes)
putCompressionTask(tempDirectory, inputFileName, compressionAttributes, outputFileName)
輸入?yún)?shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
tempDirectory | String | 是 | 臨時文件目錄 |
inputFileName | String | 是 | 輸入文件名 |
compressionAttributes | CompressionAttributes | 是 | 壓縮參數(shù) |
outputFileName | String | 否 | 輸出文件名唐责,默認UUID生成 |
其中:
CompressionAttributes
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
videoAttributes | VideoAttributes | 否 | 視頻壓縮參數(shù) |
audioAttributes | AudioAttributes | 否 | 音頻壓縮參數(shù) |
progressUrl | String | 是 | 壓縮完成后的回調(diào)地址 |
VideoAttributes
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
codec | VideoCodec | 否 | 視頻編碼(默認libx264,libx265) |
maxFps | Integer | 否 | 最大幀率 |
videoSize | VideoSize | 否 | 視頻分辨率(hd480瘾带,hd720鼠哥,hd1080,800x800) |
maxDuration | Integer | 否 | 最大時長 |
maxBitRate | Integer | 否 | 視頻最大比特率 |
AudioAttributes
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
maxBitRate | Integer | 否 | 音頻最大比特率 |
maxSamplingRate | Integer | 否 | 音頻最大采樣率 |
輸出參數(shù)
參數(shù) | 類型 | 必需 | 注釋 |
---|---|---|---|
outputFileName | String | 是 | 輸出文件名 |
ImageMagick官網(wǎng)
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官網(wǎng)
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 設置聲道數(shù)為1
-ar 48000 設置采樣率為48000Hz
截取視頻生成圖片
從第-ss秒開始菜皂,每秒截取-r張圖片贞绵,持續(xù)-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
網(wǎng)上的開源框架
https://github.com/a-schild/jave2
網(wǎng)上的相關資料
http://www.reibang.com/p/e14bc2551cfd
http://www.reibang.com/p/3c8c4a892f3c
https://blog.csdn.net/u010629285/article/details/102998555