package com.highsoft.video.processing.utils;
import org.apache.commons.lang3.RandomStringUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class VideoProcessingUtil {
/**
* 判断是不是视频
*/
public static boolean isVideo(String path) {
//设置视频后缀
List<String> typeList = new ArrayList<String>();
typeList.add("mp4");
typeList.add("flv");
typeList.add("avi");
typeList.add("rmvb");
typeList.add("rm");
typeList.add("wmv");
//获取文件名和后缀
String suffix = path.substring(path.lastIndexOf(".") + 1);
for (String type : typeList) {
//统一为大写作比较
if (type.toUpperCase().equals(suffix.toUpperCase())) {
return true;
}
}
return false;
}
private static RenderedImage FrameToBufferedImage(Frame frame) {
//创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
return converter.getBufferedImage(frame);
}
public static boolean getTempPath(String filePath) throws Exception {
String path = "E:/images/";
int count = 3;
int sum = 0;
System.out.println("确认文件是否是视频...");
//判断文件是否为视频
if (VideoProcessingUtil.isVideo(filePath)) {
System.out.println("确认成功!");
//判断文件是否存在
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
ff.start();
int width = ff.getImageWidth();
int height = ff.getImageHeight();
System.out.println("宽:" + width + ";高:" + height);
// 视频帧数
int ftp = ff.getLengthInFrames();
System.out.println("一共有:" + ftp + "帧");
// 视频帧率
double videoFrameRate = ff.getVideoFrameRate();
System.out.println("帧率:" + videoFrameRate);
System.out.println("秒数:" + ff.getLengthInTime() / 1000000.00);
// ff.start();
int step = ftp / (count + 1);
System.out.println("每隔:" + step + "帧取一帧");
int flag = 0;
Frame frame;
List<String> images = new ArrayList<>();
boolean isFirst = true;
// 生成文件名称
// 获取当前日期
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime now = LocalDateTime.now();
Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
Random random = new Random();
long delayedTime = ff.getLengthInTime() / 1000000;
long sep = delayedTime / (count+1);
System.out.println(delayedTime + "." + sep);
for(int i = 0; i < count; i++){
long time = (sep * (i + 1)) * 1000000L;
System.out.println(time);
ff.setTimestamp(time);
Frame f = ff.grabImage();
BufferedImage bi = java2dFrameConverter.getBufferedImage(f);
String fileName = now.format(dtf) + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
File out = Paths.get(path, fileName).toFile();
ImageIO.write(bi, "jpg", out);
images.add(fileName);
}
/*for (int i = 1; i <= ftp; i++) {
frame = ff.grabImage();
if ((i > 3 && frame != null && isFirst) || (i % step == 0 && frame != null)) {
sum++;
System.out.println(i);
String fileName = now.format(dtf) + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
File file = new File(path + fileName);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
BufferedImage image = java2dFrameConverter.convert(frame);
// 存储抽取到的图片
boolean isSuccess = ImageIO.write(image, "jpg", file);
if(isSuccess){
images.add(fileName);
}
// 取首帧 过滤前3帧,避免出现全黑图片
isFirst = false;
if(sum == (count + 1)){
break;
}
}
}*/
System.out.println(images);
ff.stop();
ff.release();
return true;
} else {
System.out.println("确认失败!");
return false;
}
}
public static void main(String[] args) throws Exception {
// boolean tempPath = VideoProcessingUtil.getTempPath("E:/images/542.jpg", "http://pinxls.zlzbgj.com/uploads/videos/202208/23/6fdd53665bf6f7aa847daca49b684436.mp4");
// System.out.println("获取首帧是否成功!"+tempPath);
// VideoProcessingUtil.getTempPath("http://pinxls.zlzbgj.com/uploads/videos/202208/23/5763bccd10bfb2be2a827d940cbb5b4d.mp4");
long time = 12000000 / 1000; // 获取ms时长
long step = time / (3 + 2); // 获取按照count拆分后的每段时长 为了去掉前一段和后一段 取中间段来截取图片
System.out.println(step);
Random random = new Random();
for(int i = 0; i<3;i++){
int randomInt = random.nextInt(Math.toIntExact(step));// 随机取一个点
System.out.println(randomInt);
long jumpTime = (step * (i+1) + randomInt) * 1000L;
System.out.println(jumpTime);
}
}
}
public class ProcessingServiceImpl implements IProcessingService {
// 视频格式
private static final String[] VIDEO_TYPES = {"mp4", "flv", "avi", "rmvb", "rm", "wmv"};
// 文件存储路径
@Value("${video.images.path:/www/wwwroot/supply_chain/images/}")
private String path;
// 图片展示路径前缀
@Value("${video.images.url_prefix:http://images.kdfff.com/images/}")
private String url_prefix;
// 截取截图数量
@Value("${video.images.count:3}")
private Integer count;
@Override
public ResultDTO processing(String videoUrl) {
// String videoUrl = params.get("video");
if (StringUtils.isBlank(videoUrl)) {
// 传入的视频路径为空
log.info("传入的视频路径为空");
return ResultDTO.fail("未传入视频路径!");
}
if (!isVideo(videoUrl)) {
// 文件不为视频文件
log.info("文件不为视频文件");
return ResultDTO.fail("文件不为视频文件!");
}
String suffix = videoUrl.substring(videoUrl.lastIndexOf(".") + 1);
log.info("开始获取视频,并抓取视频信息,url:【{}】, 后缀:【{}】", videoUrl, suffix);
FFmpegFrameGrabber grabber = null;
VideoInfoRespDTO respDTO = new VideoInfoRespDTO(); // 返回视频信息
try {
grabber = FFmpegFrameGrabber.createDefault(videoUrl); // 获取视频
grabber.start(); // 启动视频
respDTO.setUrlPrefix(url_prefix); // 设置图片展示前缀
respDTO.setHeight(grabber.getImageHeight()); // 获取高度
respDTO.setWidth(grabber.getImageWidth()); // 获取宽度
respDTO.setBitrate(grabber.getVideoBitrate()); // 获取视频码率
respDTO.setFps(grabber.getVideoFrameRate()); // 获取视频流帧率
respDTO.setDuration(grabber.getLengthInTime() / 1000000); // 获取视频流长度: 单位s
respDTO.setFormat(suffix); // 获取视频流格式
// 生成文件名称 具体为 /日期/时间戳+随机字符串.jpg
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
String now = LocalDateTime.now().format(dtf);
Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
// 获取首帧图片
int ftp = grabber.getLengthInFrames();
int flag = 0;
Frame firstFrame;
while (flag <= 10) {
firstFrame = grabber.grabImage();
//过滤前3帧,避免出现全黑图片
if ((flag > 5) && (firstFrame != null)) {
BufferedImage bi = java2dFrameConverter.getBufferedImage(firstFrame);
String fileName = now + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
File out = new File(path + fileName);
if(!out.getParentFile().exists()){
out.getParentFile().mkdirs();
}
if (ImageIO.write(bi, "jpg", out)) {
// 图片保存成功!
respDTO.setCover_url(url_prefix + fileName);
break;
}
}
flag++;
}
// 随机获取 count 帧图片
long time = grabber.getLengthInTime() / 1000; // 获取ms时长
long step = time / (count + 2); // 获取按照count拆分后的每段时长 为了去掉前一段和后一段 取中间段来截取图片
Random random = new Random();
List<String> images = new ArrayList<>();
for (int i = 0; i < count; i++) {
int randomInt = random.nextInt(Math.toIntExact(step));// 随机取一个点
long jumpTime = (step * (i + 1) + randomInt) * 1000L;
grabber.setTimestamp(jumpTime);
Frame f = grabber.grabImage();
BufferedImage bi = java2dFrameConverter.getBufferedImage(f);
String fileName = now + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
File out = Paths.get(path, fileName).toFile();
if(!out.getParentFile().exists()){
out.getParentFile().mkdirs();
}
ImageIO.write(bi, "jpg", out);
images.add(url_prefix + fileName);
}
respDTO.setSnapshots(images);
log.info("处理结果:【{}】", JSONObject.toJSONString(respDTO));
return ResultDTO.success(respDTO);
} catch (Exception e) {
log.error("处理发生异常!msg:{}", e);
} finally {
if (grabber != null) {
try {
grabber.release();
grabber.stop();
grabber.close();
} catch (FrameGrabber.Exception e) {
log.error("关闭grabber发生异常!msg:{}", e);
}
}
}
return ResultDTO.error();
}
/**
* 判断是不是视频
*/
private static boolean isVideo(String path) {
//获取文件名和后缀
String suffix = path.substring(path.lastIndexOf(".") + 1);
for (String type : VIDEO_TYPES) {
//统一为大写作比较
if (type.equalsIgnoreCase(suffix)) {
return true;
}
}
return false;
}
}
Java视频抽取图片ffmpeg
最新推荐文章于 2024-05-13 01:33:07 发布