大家好,我叫大鸡腿,大家可以关注下我,会持续更新技术文章还有人生感悟,感谢~
目录
前言
这是一个很慢的生成代码,西西
代码
pom.xml
<!-- 视频截图 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.4.2</version>
</dependency>
<!-- gif -->
<dependency>
<groupId>com.madgag</groupId>
<artifactId>animated-gif-lib</artifactId>
<version>1.4</version>
</dependency>
源码
package com.example.demo;
import com.madgag.gif.fmsware.AnimatedGifEncoder;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
public class TestMain {
/**
* 根据秒数获取帧数
* @param videofile video文件
* @param timeList 时间List
* @return
*/
private static LinkedList<Integer> getTime(String videofile, LinkedList<Integer> timeList) {
int length = 0;
LinkedList<Integer> list = new LinkedList<>();
try (FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile)) {
ff.start();
for (int i : timeList) {
ff.setAudioTimestamp(1000000 * i);
length = ff.getFrameNumber();
list.add(length);
}
} catch (FrameGrabber.Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 截取视频指定帧生成gif
*
* @param startTime 截取视频开始时间(默认第3帧)
* @param endTime 截取视频结束时间
* @param videofile 视频文件
* @param frameRate 帧频率(默认:3)
* @param margin 每截取一次跳过多少帧(默认:3)
* @throws IOException 截取的长度超过视频长度
*/
public static void buildGif(String videofile, Integer startTime, Integer endTime, Integer frameRate, Integer margin) throws IOException {
if (margin == null) {
margin = 3;
}
if (frameRate == null) {
frameRate = 3;
}
LinkedList<Integer> list = new LinkedList<>();
list.add(startTime);
list.add(endTime);
list = getTime(videofile, list);
int startFrame = list.get(0);
startFrame = startFrame > 3 ? startFrame : 3;
int frameCount = list.get(1) / frameRate;
/*int startFrame = 3;
int frameCount = 20;*/
System.out.println(startFrame + " " + frameCount);
FileOutputStream targetFile = new FileOutputStream(videofile.substring(0, videofile.lastIndexOf(".")) + ".gif");
Java2DFrameConverter converter = new Java2DFrameConverter();
try (FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile)) {
ff.start();
if (startFrame > ff.getLengthInFrames() & (startFrame + frameCount) > ff.getLengthInFrames()) {
throw new RuntimeException("视频太短了");
}
ff.setFrameNumber(startFrame);
AnimatedGifEncoder en = new AnimatedGifEncoder();
en.setFrameRate(frameRate);
en.start(targetFile);
for (int i = 0; i < frameCount; i++) {
en.addFrame(converter.convert(ff.grab()));
ff.setFrameNumber(ff.getFrameNumber() + margin);
}
en.finish();
}
}
/**
* 将图片旋转指定度
*
* @param bufferedimage 图片
* @param degree 旋转角度
* @return
*/
public static BufferedImage rotateImage(BufferedImage bufferedimage, int degree) {
int w = bufferedimage.getWidth();// 得到图片宽度。
int h = bufferedimage.getHeight();// 得到图片高度。
int type = bufferedimage.getColorModel().getTransparency();// 得到图片透明度。
BufferedImage img;// 空的图片。
Graphics2D graphics2d;// 空的画笔。
(graphics2d = (img = new BufferedImage(w, h, type))
.createGraphics()).setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);// 旋转,degree是整型,度数,比如垂直90度。
graphics2d.drawImage(bufferedimage, 0, 0, null);// 从bufferedimagecopy图片至img,0,0是img的坐标。
graphics2d.dispose();
return img;// 返回复制好的图片,原图片依然没有变,没有旋转,下次还可以使用。
}
/**
* 截取视频指定帧保存为指定格式的图片(图片保存在视频同文件夹下)
*
* @param videofile 视频地址
* @param imgSuffix 图片格式
* @param indexFrame 第几帧(默认:5)
* @throws Exception
*/
public static void fetchFrame(String videofile, String imgSuffix, Integer indexFrame) throws Exception {
if (indexFrame == null) {
indexFrame = 5;
}
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
ff.start();
try {
int lenght = ff.getLengthInFrames();
int i = 0;
Frame f = null;
while (i < lenght) {
f = ff.grabFrame();
if ((i > indexFrame) && (f.image != null)) {
break;
}
i++;
}
int owidth = f.imageWidth;
int oheight = f.imageHeight;
int width = 800;
int height = (int) (((double) width / owidth) * oheight);
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage fecthedImage = converter.getBufferedImage(f);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, null);
bi = rotateImage(bi, 90);
File targetFile = new File(videofile.substring(0, videofile.lastIndexOf(".")) + imgSuffix);
ImageIO.write(bi, "jpg", targetFile);
} finally {
ff.stop();
ff.close();
}
}
public static void main(String[] args) {
try {
//fetchFrame("D:\\test\\QQ.mp4",".jpg",10);
long time1 = System.nanoTime();
buildGif("C:\\Users\\Max.Yang\\Desktop\\zip\\707955272614649856.mp4", 0, 2, 3, 3);
long time2 = System.nanoTime();
System.out.println("消耗时间" + (time2 - time1));
} catch (Exception e) {
e.printStackTrace();
}
}
}
这一部分是截取别人文章的代码,西西。只是他是使用第几帧来截取视频,我这里改造成第几秒来获取视频,不过特别慢,截取0秒到2秒的话需要耗费10秒,西西
其中还有一些未判空等等问题,你们自行改造咯~