ruoyi实现视频压缩并上传到阿里云
·
废话不多说,直接上代码,复制粘贴即可使用
maven依赖
<!-- 阿里云OSS对象存储 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!--获取视频时长、分辨率、帧率、码率-->
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>2.6.0</version>
</dependency>
application-dev.yaml
aliyun:
oss:
# 阿里云OSS服务接入点
endpoint: oss**************.com
# 阿里云账号Access Key Id
accessKeyId: L****************PU4j
# 阿里云账号Access Key Secret
accessKeySecret: 0*******************qr
# OSS存储空间
bucketName: d*******t
OssService.java
private Logger log = LoggerFactory.getLogger(OssService.class);
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
public Map<String, String> uploadVideo(MultipartFile file) throws Exception {
log.info("上传视频开始" + System.currentTimeMillis());
try {
// 获取文件名和扩展名
String OriginalFilename = file.getOriginalFilename();
String fileExt = OriginalFilename.substring(OriginalFilename.lastIndexOf(".") + 1).toLowerCase();
// 原始文件保存到临时目录
String tempPath = RuoYiConfig.getUploadPath();
String upload = FileUploadUtils.upload(tempPath, file);
String originalFilePath = tempPath + upload.replaceAll("/profile/upload", "");
Map<String,String> videoMap = this.getVideoInfo(originalFilePath);
//是否压缩视频
// TODO 分辨率-宽大于等于1920,分辨率-高大于等于1080,则压缩视频;
int isCompressed = this.isCompressed(videoMap);
if(isCompressed == 0){
Map<String, String> videoToOSSMap = this.uploadVideoToOSS(file, originalFilePath, videoMap);
//删除本地文件
File file1 = new File(originalFilePath);
if (file1.exists()) {
file1.delete();
}
return videoToOSSMap;
}
else {
//视频压缩
log.info("开始压缩视频:"+System.currentTimeMillis());
Map<String, String> compressMap = this.toCompressFile(originalFilePath,fileExt,isCompressed);
log.info("压缩视频结束:"+System.currentTimeMillis());
String compressedCode = compressMap.get("compressedCode");
String compressedFilePath = compressMap.get("compressedFilePath");
File compressedFile = new File(compressedFilePath);
Map<String, String> videoToOSSMap = new HashMap<>();
if ("0".equals(compressedCode) && compressedFile.exists()) {
videoToOSSMap = this.uploadVideoToOSS(file, compressedFilePath, videoMap);
}
//删除上传的视频以及压缩后的视频
File file1 = new File(originalFilePath);
file1.delete();
compressedFile.delete();
log.info("上传视频结束:"+System.currentTimeMillis());
return videoToOSSMap;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/*
* 压缩视频
* @param originalFilePath 待转换的文件
* @param fileExt 文件扩展名
* @param type 压缩类型
*/
private Map<String, String> toCompressFile(String originalFilePath,String fileExt,int type) throws Exception {
File originalFile = new File(originalFilePath);
// 设置压缩后的视频文件路径
String compressedFilePath = originalFilePath.substring(0, originalFilePath.lastIndexOf(".")) + "_压缩后" + "." + fileExt;
File compressedFile = new File(compressedFilePath);
while (true) {
boolean exists = originalFile.exists();
log.info("等待文件生成:" + exists);
if (originalFile.exists()) {
break;
}
}
// 调用ffmpeg命令行进行压缩
ProcessBuilder processBuilder = null;
if(type == 1){
processBuilder = new ProcessBuilder(
"ffmpeg",
"-i", originalFile.getAbsolutePath(),
// "-vcodec", "libx264",
// "-crf", "18", // 提高CRF值,降低画质来减少CPU使用
"-preset", "ultrafast", // 更快的编码速度,减少CPU负载
// "-maxrate", "2000k", // 降低最大比特率
// "-bufsize", "4000k", // 减小缓冲区大小
// "-acodec", "aac", // 音频编码
// "-b:a", "128k", // 降低音频比特率
// "-r", "15", // 降低帧率
// "-b:v", "600k", // 降低视频比特率
"-s", "1280x720", // 降低分辨率
// "-movflags", "+faststart", // 提前索引以支持快速播放
"-threads", "2", // 使用双线程,视系统资源增加
compressedFile.getAbsolutePath() // 输出文件路径
);
}
else if(type == 2){
processBuilder = new ProcessBuilder(
"ffmpeg",
"-i", originalFile.getAbsolutePath(),
// "-vcodec", "libx264",
// "-crf", "18", // 提高CRF值,降低画质来减少CPU使用
"-preset", "ultrafast", // 更快的编码速度,减少CPU负载
// "-maxrate", "2000k", // 降低最大比特率
// "-bufsize", "4000k", // 减小缓冲区大小
// "-acodec", "aac", // 音频编码
// "-b:a", "128k", // 降低音频比特率
"-r", "20", // 降低帧率
// "-b:v", "600k", // 降低视频比特率
// "-s", "1280x720", // 降低分辨率
// "-movflags", "+faststart", // 提前索引以支持快速播放
"-threads", "2", // 使用双线程,视系统资源增加
compressedFile.getAbsolutePath() // 输出文件路径
);
}else {
processBuilder = new ProcessBuilder();
}
processBuilder.inheritIO();
Process process = processBuilder.start();
int i = process.waitFor();
log.info("压缩视频完成,状态码:" + i);
Map<String, String> map = new HashMap<>();
map.put("compressedCode", i + "");
map.put("compressedFilePath", compressedFile.getAbsolutePath());
return map;
}
/**
* 获取视频信息
*/
private Map<String, String> getVideoInfo(String videoUrl) {
Map<String, String> map = new HashMap<>();
// 视频时长
long time = 0;
// 码率
int bitRate = 0;
// 帧率
float frameRate = 0;
// 分辨率-高
int height = 0;
// 分辨率-宽
int width = 0;
// 视频解码器名称
String decoder = "";
try {
MultimediaObject media = new MultimediaObject(new File(videoUrl));
MultimediaInfo info = media.getInfo();
// 时长,毫秒级
long duration = info.getDuration();
// 毫秒级时长转化为秒
BigDecimal bigDecimal1 = new BigDecimal(duration);
BigDecimal bigDecimal2 = new BigDecimal(1000);
// 四舍五入,只保留整数
time = bigDecimal1.divide(bigDecimal2, 0, RoundingMode.HALF_UP).longValue();
// 获取媒体视频对象
VideoInfo video = info.getVideo();
// 码率
bitRate = video.getBitRate();
// 帧率
frameRate = video.getFrameRate();
// 分辨率-高
height = video.getSize().getHeight();
// 分辨率-宽
width = video.getSize().getWidth();
// 视频解码器名称
decoder = video.getDecoder();
} catch (Exception e) {
e.getMessage();
}
map.put("time", time + "");
map.put("bitRate", bitRate + "");
map.put("frameRate", frameRate + "");
map.put("height", height + "");
map.put("width", width + "");
map.put("decoder", decoder);
return map;
}
/**
* 判断是否压缩视频
* 0:不压缩
* 1:分辨率压缩
* 2:帧率压缩
*
*/
private int isCompressed(Map<String, String> videoMap){
//视频码率
int bitRate = Convert.toInt(videoMap.get("bitRate"));
//视频帧率
float frameRate = Convert.toFloat(videoMap.get("frameRate"));
//分辨率-高
int height = Convert.toInt(videoMap.get("height"));
// 分辨率-宽
int width = Convert.toInt(videoMap.get("width"));
//判断视频分辨率是否超过限制
if (height > 720 && width > 1280){
return 1;
}
// 判断视频帧率是否超过限制
if (frameRate > 30){
return 2;
}
return 0;
}
/**
* 上传视频到阿里云
*/
private Map<String, String> uploadVideoToOSS(MultipartFile file, String filePath, Map<String,String> videoMap) throws Exception {
Map<String, String> map = new HashMap<>();
String endPoint = this.endpoint;
String accessKeyId = this.accessKeyId;
String accessKeySecret = this.accessKeySecret;
String bucketName = this.bucketName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
//上传文件流
InputStream inputStream = new FileInputStream(new File(filePath));
String originalFilename = file.getOriginalFilename();
String uuid = java.util.UUID.randomUUID().toString().replaceAll("-", "");
String fileName = uuid + "_" + originalFilename;
//按照当前日期,创建文件夹,上传到创建的文件夹下。规则: 年/月/日
String timeUrl = new DateTime().toString("yyyy/MM/dd");
fileName = timeUrl + "/" + fileName;
// 文件上传。
ossClient.putObject(bucketName, fileName, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
//上传之后文件路径
String url = "https://" + bucketName + "." + endPoint + "/" + fileName;
map.put("url", url);
map.put("originalFilename", originalFilename);
map.put("fileName", fileName);
map.put("time", videoMap.get("time"));
return map;
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)