视频截取第一帧

前言

网上视频截取第一帧的案例还是比较多的,普遍的方法主要是使用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();
		}
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值