Java视频按秒截取帧
1. Java视频按秒截取帧工具类
具体方法都在工具类中,可以文件地址,可以按照参数传递,具体场景需要根据工具类具体改造一下,但是基本功能是不变的。
com.github.vip-zpf
jave
1.1.1
com.github.vip-zpf
jave
1.0.8
org.bytedeco
javacv
1.5.6
org.bytedeco
ffmpeg-platform
4.4-1.5.6
package com.xxx.util;
import com.xxx.util.img.ConvertToMultipartFile;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.MultimediaInfo;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class VideoUtil {
public static Map getVideoPic(String frameFilePath, File video, String picPath){
//1.根据一个视频文件,创建一个按照视频中每一帧进行抓取图片的抓取对象
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
Map strMap=new HashMap<>();
List strList=new ArrayList<>();
try {
ff.start();
//抓每一帧图片
//2.先知道这个视频一共有多少帧
int length = ff.getLengthInFrames();
//3.读取视频中每一帧图片
Frame frame = null;
for(int i=1;i图片的转换器
BufferedImage image = converter.getBufferedImage(frame);//转换
String img = picPath+i+".png";
File picFile = new File(img);
//将图片保存到目标文件中
ImageIO.write(image, "png", picFile);
strList.add(frameFilePath+"/"+i+".png");
}
strMap.put("height",ff.getImageHeight());//视频高度
strMap.put("width",ff.getImageWidth());//视频宽度
strMap.put("frame",ff.getFrameRate());//帧率
strMap.put("imgPath",strList);//每一帧图像数据
ff.stop();
} catch (Exception e) {
e.printStackTrace();
}
return strMap;
}
public static int queryVideoDuration(MultipartFile multipartFile) throws EncoderException {
//机算视频时长
File dfile = null;
try {
dfile = File.createTempFile("prefix", "_" + multipartFile.getOriginalFilename());
multipartFile.transferTo(dfile);
} catch (IOException e) {
e.printStackTrace();
}
// 获取视频时长
Encoder encoder = new Encoder();
MultimediaInfo m = encoder.getInfo(dfile);
long ls = m.getDuration()/1000;
int hour = (int) (ls/3600);
int minute = (int) (ls%3600)/60;
int second = (int) (ls-hour*3600-minute*60);
//删除临时文件
dfile.delete();
return second;
}
public static void approvalFile( MultipartFile filecontent , String path){
OutputStream os = null;
InputStream inputStream = null;
String fileName = null;
try {
inputStream = filecontent.getInputStream();
fileName = filecontent.getOriginalFilename();
} catch (IOException e) {
e.printStackTrace();
}
try {
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流保存到本地文件
File tempFile = new File(path);
if (!tempFile.exists()) {
tempFile.mkdirs();
}
os = new FileOutputStream(tempFile.getPath() + File.separator + fileName);
// 开始读取
while ((len = inputStream.read(bs)) != -1) {
os.write(bs, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 完毕,关闭所有链接
try {
os.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void getImage(String filePath, String fileName, int second) {
File folder = new File(filePath);
if (!folder.exists())
{
folder.mkdirs();//如果文件夹不存在则创建
}
try{
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filePath + File.separator + fileName);
grabber.start();
long ftp = grabber.getLengthInFrames();
int flag=0;
int sum=0;
Frame frame = null;
int count = (int)Math.round(grabber.getFrameRate());
while (flag <= ftp) {
if(countflag){
flag++;
continue;
} else if(count > ftp){
break;
} else{
count += (int)Math.round(grabber.getFrameRate());
}
sum++;
//获取帧跳帧
grabber.setFrameNumber(count);
frame = grabber.grabImage();
//过滤前 second 帧,避免出现全黑图片
String rotate = grabber.getVideoMetadata("rotate");
//创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
if (rotate != null) {
//旋转图片
bufferedImage = rotate(bufferedImage, Integer.parseInt(rotate));
}
String newFileName = filePath + File.separator + fileName.substring(0, fileName.lastIndexOf(".")) + sum +".jpeg";
ImageIO.write(bufferedImage, "jpeg", new File(newFileName));
flag += (int)Math.round(grabber.getFrameRate());
}
grabber.close();
grabber.stop();
}catch(Exception e){
System.out.printf("获取视频图片失败!", e);
}
}
private static BufferedImage rotate(BufferedImage src, int angel) {
int src_width = src.getWidth(null);
int src_height = src.getHeight(null);
int type = src.getColorModel().getTransparency();
Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
Graphics2D g2 = bi.createGraphics();
g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
g2.drawImage(src, 0, 0, null);
g2.dispose();
return bi;
}
private static Rectangle calcRotatedSize(Rectangle src, int angel) {
if (angel >= 90) {
if(angel / 90 % 2 == 1) {
int temp = src.height;
src.height = src.width;
src.width = temp;
}
angel = angel % 90;
}
double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
double angel_dalta_width = Math.atan((double) src.height / src.width);
double angel_dalta_height = Math.atan((double) src.width / src.height);
int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
int des_width = src.width + len_dalta_width * 2;
int des_height = src.height + len_dalta_height * 2;
return new Rectangle(new Dimension(des_width, des_height));
}
public static List getVideoImageByUrl(String onlineFileUrl) {
//导出本地地址
// String filePath="C:\Users\wonder\Desktop\ai测试图片\视频解析\截取后\";
// File folder = new File(filePath);
// if (!folder.exists())
// {
// folder.mkdirs();//如果文件夹不存在则创建
// }
Listlist=new ArrayList<>();
try{
//url编码处理,中文名称会变成百分号编码
String fileUrl = URLDecoder.decode(onlineFileUrl, "utf-8");
MultipartFile multipartFile = HuaweiOBSUtil.downloadFileByUrl(fileUrl);
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(multipartFile.getInputStream());
grabber.start();
long ftp = grabber.getLengthInFrames();
Frame frame = null;
int sum=0;
int flag=0;
int count = (int)Math.round(grabber.getFrameRate());
while (flag <= ftp) {
if(countflag){
flag++;
continue;
} else if(count > ftp){
break;
} else{
count += (int)Math.round(grabber.getFrameRate());
}
sum++;
//获取帧
grabber.setFrameNumber(count);
frame = grabber.grabImage();
//过滤前 second 帧,避免出现全黑图片
String rotate = grabber.getVideoMetadata("rotate");
//创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
if (rotate != null) {
//旋转图片
bufferedImage = rotate(bufferedImage, Integer.parseInt(rotate));
}
String newFileName = sum +".jpeg";
//写入本地
//ImageIO.write(bufferedImage, "jpeg", new File(filePath+newFileName));
//BufferedImage 转化为 ByteArrayOutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpeg", out);
//ByteArrayOutputStream 转化为 byte[]
byte[] imageByte = out.toByteArray();
//将 byte[] 转为 MultipartFile
MultipartFile convertMultipartFile = new ConvertToMultipartFile(imageByte, null, newFileName, "jpeg", imageByte.length);
//MultipartFile multipartFile = new ConvertToMultipartFile(imageByte, "C:\Users\wonder\Desktop\ai测试图片\视频解析\截取后\", newFileName, "jpeg", imageByte.length);
list.add(convertMultipartFile);
flag += (int)Math.round(grabber.getFrameRate());
}
grabber.close();
grabber.stop();
}catch(Exception e){
System.out.printf("获取视频图片失败!", e);
}
return list;
}
public static void main(String[] args) {
List videoImageByUrl = getVideoImageByUrl("url");
for (MultipartFile multipartFile : videoImageByUrl) {
String s = FileUtil.generateBase64(multipartFile, true);
System.out.println("multipartFile.getOriginalFilename() = " + multipartFile.getOriginalFilename());
String fileNameNotPrefix = FileUtil.getFileNameNotPrefix(multipartFile.getOriginalFilename());
System.out.println("fileNameNotPrefix = " + fileNameNotPrefix);
}
}
}
2.获取视频时长
public static int queryVideoDuration(MultipartFile multipartFile) throws EncoderException {
//机算视频时长
File dfile = null;
try {
dfile = File.createTempFile("prefix", "_" + multipartFile.getOriginalFilename());
multipartFile.transferTo(dfile);
} catch (IOException e) {
e.printStackTrace();
}
// 获取视频时长
Encoder encoder = new Encoder();
MultimediaInfo m = encoder.getInfo(dfile);
long ls = m.getDuration()/1000;
int hour = (int) (ls/3600);
int minute = (int) (ls%3600)/60;
int second = (int) (ls-hour*3600-minute*60);
//删除临时文件
dfile.delete();
return second;
}