视频截取第一帧
前言
网上视频截取第一帧的案例还是比较多的,普遍的方法主要是使用ffmpeg 对其截取。在实践过程中,发现window 截取成功。但linux 环境中截取失败,对于失败原因这里将失败内容贴出来,供他人查看失败原因
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x000000000000d1f6, pid=14, tid=0x00007fe8b67e6b10
#
# JRE version: OpenJDK Runtime Environment (8.0_212-b04) (build 1.8.0_212-b04)
# Java VM: OpenJDK 64-Bit Server VM (25.212-b04 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea 3.12.0
# Distribution: Custom build (Sat May 4 17:33:35 UTC 2019)
# Problematic frame:
# C 0x000000000000d1f6
#
# Core dump written. Default location: //core or core.14
#
# If you would like to submit a bug report, please include
# instructions on how to reproduce the bug and visit:
# https://icedtea.classpath.org/bugzilla
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- T H R E A D ---------------
Current thread (0x00005565ead9c800): JavaThread "http-nio-8889-exec-9" daemon [_thread_in_native, id=109, stack(0x00007fe8b66e6000,0x00007fe8b67e6ad0)]
siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x000000000000d1f6
(省略部分)
Stack: [0x00007fe8b66e6000,0x00007fe8b67e6ad0], sp=0x00007fe8b67e1558, free space=1005k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C 0x000000000000d1f6
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.bytedeco.javacpp.avformat.avformat_open_input(Lorg/bytedeco/javacpp/avformat$AVFormatContext;Ljava/lang/String;Lorg/bytedeco/javacpp/avformat$AVInputFormat;Lorg/bytedeco/javacpp/avutil$AVDictionary;)I+0
j org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe()V+624
j org.bytedeco.javacv.FFmpegFrameGrabber.start()V+1
j com.megvii.qingqiu.middle.platform.provider.util.VideoFrameUtil.fetchFrame(Ljava/io/File;Ljava/io/File;)V+26
j com.megvii.qingqiu.middle.platform.provider.util.VideoFrameUtil.fetchFrame(Lorg/springframework/web/multipart/MultipartFile;)Ljava/io/File;+148
j
(省略部分)
实践
这里将 ffmpeg 截取的方式改为 jcodec 和 jcodec-javase 来处理
maven 依赖(注释部分为使用ffmpeg 方式处理)
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId>
<version>0.2.5</version>
</dependency>
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec-javase</artifactId>
<version>0.2.5</version>
</dependency>
<!--<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> <version>3.4.1-1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>3.4.2-1.4.1</version> </dependency>-->
**视频截取工具类(注释部分为使用ffmpeg 方式处理) **
package com.yin.demo
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.jcodec.api.FrameGrab;
import org.jcodec.api.JCodecException;
import org.jcodec.common.model.Picture;
import org.jcodec.scale.AWTUtil;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
//import org.bytedeco.javacv.FFmpegFrameGrabber;
//import org.bytedeco.javacv.Frame;
//import org.bytedeco.javacv.Java2DFrameConverter;
/** * @author yinfeiyue */
@Slf4j
public class VideoFrameUtil {
/** * 获取指定视频的帧并保存为图片至指定目录 * @param videoFilePath 源视频文件路径 * @param frameFilePath 截取帧的图片存放路径 */
public static void fetchFrame(String videoFilePath, String frameFilePath)
throws Exception {
File videoFile = new File(videoFilePath);
File frameFile= new File(frameFilePath);
getThumbnail(videoFile, frameFile);
}
/** * * 获取指定视频的帧并保存为图片至指定目录 * @param videoFile 源视频文件 * @param targetFile 截取帧的图片 */
public static void fetchFrame(MultipartFile videoFile, File targetFile) throws Exception {
File file = new File(videoFile.getName());
FileUtils.copyInputStreamToFile(videoFile.getInputStream(), file);
getThumbnail(file, targetFile);
}
// /**
// *
// * 获取指定视频的帧并保存为图片至指定目录
// * @param videoFile 源视频文件
// * @param targetFile 截取帧的图片
// */
// public static void fetchFrame(File videoFile, File targetFile) throws Exception {
// long start = System.currentTimeMillis();
//
// FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
// log.debug("视频文件 - 帧截取 - FFMPEG初始化完成");
//
// ff.start();
// log.debug("视频文件 - 帧截取 - 调用start开始");
//
// int lenght = ff.getLengthInFrames();
// int i = 0;
// Frame f = null;
// while (i < lenght) {
// // 过滤前5帧,避免出现全黑的图片,依自己情况而定
// f = ff.grabFrame();
// if ((i > 5) && (f.image != null)) {
// break;
// }
// i++;
// }
// log.debug("视频文件 - 帧截取 - 过滤前5帧");
//
// assert f != null;
// 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);
// ImageIO.write(bi, "jpg", targetFile);
// ff.stop();
// log.debug("视频文件 - 帧截取 - 调用stop结束");
//
// System.out.println(System.currentTimeMillis() - start);
//
// }
/** * 获取指定视频的帧并保存为图片至指定目录 * * @param videoFile 源视频文件 */
public static File fetchFrame(MultipartFile videoFile) throws Exception {
String originalFilename = videoFile.getOriginalFilename();
File file = new File(originalFilename);
File targetFile = null;
try {
FileUtils.copyInputStreamToFile(videoFile.getInputStream(), file);
int i = originalFilename.lastIndexOf(".");
String imageName = "";
if (i > 0) {
imageName = originalFilename.substring(0, i);
} else {
imageName = UUID.randomUUID().toString().replace("-", "");
}
imageName = imageName + ".jpg";
targetFile = new File(imageName);
getThumbnail(file, targetFile);
} catch (Exception e) {
log.error("fetch frame fail", e);
}finally {
if (file.exists()) {
file.delete();
}
}
log.debug("视频文件 - 帧截取 - 处理结束");
return targetFile;
}
private static final String FILE_EXT = "jpg";
/** * 帧数 */
private static final int THUMB_FRAME = 5;
public static void getThumbnail(File videoFile,File targetFile) {
try {
// 根据扩展名创建一个新文件路径
Picture picture = FrameGrab.getFrameFromFile(videoFile, THUMB_FRAME);
BufferedImage bufferedImage = AWTUtil.toBufferedImage(picture);
ImageIO.write(bufferedImage, FILE_EXT, targetFile);
} catch (IOException | JCodecException e) {
e.printStackTrace();
log.error("getThumbnail fail", e);
}
}
public static void main(String[] args) {
try {
long startTime = System.currentTimeMillis();
getThumbnail(new File("C:\\Users\\xxx\\Desktop\\video\\33.mp4"), new File("C:\\Users\\xxx\\Desktop\\video\\33.jpg"));
System.out.println("count time is "+(System.currentTimeMillis()-startTime));
} catch (Exception e) {
e.printStackTrace();
}
}
}
还没有评论,来说两句吧...