javacv获取视频第一帧

第一种是用ffmpeg工具,不过还得安装客户端软件,于是放弃了,还有一种是javacv开源工具,所以选择第二种:

第一种:ffmpeg工具

需要安装ffmpeg软件,支持windows和linux,视频安装教程参考:https://www.cnblogs.com/rxbook/p/9652185.html

然后用以下代码:

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;

public class FirstFrameUtil {
    protected String ffmpegApp;
    public FirstFrameUtil(String ffmpegApp) {
        this.ffmpegApp = ffmpegApp;
    }
    @SuppressWarnings("unused")
    /****
     * 获取指定时间内的图片
     * @param videoFilename:视频路径
     * @param thumbFilename:图片保存路径
     * @param width:图片长
     * @param height:图片宽
     * @param hour:指定时
     * @param min:指定分
     * @param sec:指定秒
     * @throws IOException
     * @throws InterruptedException
     */
    public void getThumb(String videoFilename, String thumbFilename,  int hour, int min, float sec) throws IOException, InterruptedException {
            ProcessBuilder processBuilder = new ProcessBuilder(ffmpegApp, "-y", "-i", videoFilename, "-vframes", "1", "-ss", hour + ":" + min + ":" + sec, "-f", "mjpeg",  "-an",
                    thumbFilename);
        Process process = processBuilder.start();
        InputStream stderr = process.getErrorStream();
        InputStreamReader isr = new InputStreamReader(stderr);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null)
            ;
        process.waitFor();   
        if (br != null)
            br.close();
        if (isr != null)
            isr.close();
        if (stderr != null)
            stderr.close();
    }
    public static void main(String[] args) {
        String path = "D:\\config\\ffmpeg-win64\\bin\\ffmpeg.exe";

        FirstFrameUtil videoThumbTaker = new FirstFrameUtil(path);
        try {
            videoThumbTaker.getThumb("D:\\test2.mp4", "D:\\test\\result.png", 0, 0, 1);
            File ffmpegFile = new File("D:\\test\\result.png");
            FileInputStream input=new FileInputStream(ffmpegFile);
            
            System.out.println("over");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
View Code

即可获取第一帧图片

第二种javacv

直接上代码:(后边有介绍pom文件的引用)

import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.Frame;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class VideoTool {

    public static void main(String[] args) throws Exception {

       // randomGrabberFFmpegImage("http://101.132.110.90/group1/M00/00/05/rBN4LFq8p5SAJT0wA5k4vpHKf7Q325.mp4", "D:\\test", "test2");
        randomGrabberFFmpegImage("D:\\test2.mp4", "D:\\test", "test2");
        //randomGrabberFFmpegImage("C:/Users\\Administrator\\Desktop\\VID_20171229_162251.mp4", "G:\\test", "111");
    }

    public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName)
            throws Exception {
        //创建视频帧抓取工具
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        //获取旋转角度信息(90度)
        String rotate =ff.getVideoMetadata("rotate");
        //
        Frame f;
        //i可以控制获取第几帧
        int i = 0;
        while (i <5) {
            //一帧一帧去抓取视频图片,ff.grabImage();每次抓取下一帧
            f =ff.grabImage();
            IplImage src = null;
            //旋转图像并输出第29帧
            if(i==4){
                //手机录的视频有旋转角度,需要旋转处理
                if(null !=rotate &&rotate.length() > 1) {
                    OpenCVFrameConverter.ToIplImage converter =new OpenCVFrameConverter.ToIplImage();
                    src =converter.convert(f);
                    f =converter.convert(rotate(src, Integer.valueOf(rotate)));
                }
                //输出第几帧图片
                doExecuteFrame(f,targerFilePath,targetFileName+i+i);
            }           
            i++;
        }
        ff.stop();
    }

    /*
     * 旋转角度的
     */
    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName) {

        if (null ==f ||null ==f.image) {
            return;
        }
        Java2DFrameConverter converter =new Java2DFrameConverter();
        String imageMat ="jpg";
        String FileName =targerFilePath + File.separator +targetFileName +"." +imageMat;
        BufferedImage bi =converter.getBufferedImage(f);
        System.out.println("width:" + bi.getWidth());
        System.out.println("height:" + bi.getHeight());
        File output =new File(FileName);
        try {
            ImageIO.write(bi,imageMat,output);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }   
   
}

如果不判断旋转,把手机视频放上去,截出来的是方向不对,如图左边是旋转过的,右边没有旋转的:

解决图片旋转问题参考:http://blog.csdn.net/z562743237/article/details/54667252,通过一段时间的搜索了解到,如果拍摄的视频中带有旋转(rotate)信息,那么截取出来的图片就会被旋转。通过查询API发现FFmpegFrameGrabber的getVideoMetadata("rotate")方法可以获取到视频的旋转信息。根据获取到的rotate信息对ff.grabImage()得到的Frame进行旋转,但是Frame并没有提供旋转接口。但IpImage对象提供了旋转方法 。

大多数人都是直接引入

javacv-platform
<dependency>
   <groupId>org.bytedeco</groupId>
   <artifactId>javacv-platform</artifactId>
   <version>1.3.1</version>
</dependency>

 

javacv-platform这种方式依赖的jar包300M,太大了,经过精简后pom文件如下:(在用,40兆左右)
    <properties>
        <javacpp.version>1.3</javacpp.version>
    </properties>  

    <dependencies>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>flycapture</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libdc1394</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libfreenect</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libfreenect2</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>librealsense</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>videoinput</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>artoolkitplus</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>artoolkitplus</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>flandmark</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

      <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv</artifactId>
            <version>3.1.0-${javacpp.version}</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv</artifactId>
            <version>3.1.0-${javacpp.version}</version>
            <classifier>windows-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>3.2.1-${javacpp.version}</version>
            <classifier>windows-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>3.2.1-${javacpp.version}</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
   </dependencies>

共8个jar

 

 

转载于:https://www.cnblogs.com/zhaoyanhaoBlog/p/11465516.html

### 回答1: JavaCV是一个Java编写的计算机视觉库,它并没有直接提供限制视频播放长度的功能。不过,你可以使用JavaCV提供的视频处理工具来实现这个功能。具体操作步骤如下: 1. 使用FFmpegFrameGrabber类从视频文件中读取。 2. 通过FrameGrabber.getFrameRate()方法获取视频率。 3. 使用OpenCVFrameConverter.ToMat类将转换为OpenCV的Mat格式。 4. 根据需要选择需要播放的时间段,例如前10秒。 5. 使用FrameGrabber.setFrameNumber()方法设置读取的起始,例如fps * 10。 6. 在循环中读取视频,直到达到指定的结束,例如fps * 20。 7. 关闭FrameGrabber。 下面是一个示例代码: ``` FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("input.mp4"); grabber.start(); int fps = (int) grabber.getFrameRate(); OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat(); grabber.setFrameNumber(fps * 10); // 从第10秒开始播放 while (true) { Frame frame = grabber.grab(); if (frame == null || grabber.getFrameNumber() >= fps * 20) { // 播放前20秒 break; } Mat mat = converter.convert(frame); // 处理视频 } grabber.stop(); ``` 需要注意的是,这种方式只是在读取视频时限制了播放的时间长度,如果需要实现更为严格的限制,可以在处理视频时根据时间戳来判断是否超过了限制。 ### 回答2: Javacv是一个用于在Java中操作计算机视觉和图像处理的开源库。它提供了许多功能强大的类和方法,可以用于处理图像、视频和流媒体。 在Javacv中限制视频播放长度可以通过以下步骤实现: 1. 首先,使用Javacv加载视频文件并创建一个视频流对象。 2. 然后,获取视频的总数和率。 3. 计算出期望的播放时长,可以通过设置一个播放时长的阈值或者输入一个特定的播放时长。 4. 使用一个循环来逐读取视频,直到达到预期的播放时长或者视频的末尾。 5. 在每一上执行必要的操作,例如渲染或处理图像。 6. 当达到预期的播放时长或者视频的末尾时,停止循环和视频播放。 以下是一个简单的示例代码,用于限制视频播放长度为10秒: ```java import static org.bytedeco.javacpp.opencv_core.*; import static org.bytedeco.javacpp.opencv_highgui.*; import org.bytedeco.javacv.*; public class VideoPlayer { public static void main(String[] args) { FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("input.mp4"); try { grabber.start(); double frameRate = grabber.getFrameRate(); int totalFrames = grabber.getLengthInFrames(); int targetFrames = (int) (frameRate * 10); // 设置播放时长为10秒 int currentFrame = 0; Frame frame = null; CanvasFrame canvas = new CanvasFrame("Video"); while (currentFrame < targetFrames && (frame = grabber.grab()) != null) { canvas.showImage(frame); currentFrame++; } canvas.dispose(); grabber.stop(); } catch (Exception e) { e.printStackTrace(); } } } ``` 上面的示例代码中,我们使用了FFmpegFrameGrabber来加载视频文件。然后,我们获取率和总数,并将播放时长设置为10秒,即10秒内的数。接着,我们使用一个循环来逐播放视频,直到达到预期的播放时长或者视频的末尾。在循环中,我们使用CanvasFrame来显示每一并更新当前的计数。最后,我们关闭CanvasFrame并停止视频播放。 通过上面的步骤和示例代码,你可以在Javacv中限制视频播放的长度为特定的时长。这样,你可以根据需要控制视频的播放时长,实现自定义的视频播放效果。 ### 回答3: 在使用javacv进行视频播放时,并没有直接限制视频播放长度的方法或属性。但可以通过代码来实现限制视频播放长度的效果。 一种常见的做法是使用定时器和视频计数器,来控制播放的时间。具体步骤如下: 1. 对于要播放的视频文件,首先使用JavaCV库的FFmpegFrameGrabber类创建一个FrameGrabber对象,并打开视频文件。 2. 初始化一个定时器,设定一个指定的播放时间长度。 3. 在定时器的任务中,使用FrameGrabber对象的grabFrame方法获取视频的每一图像,并将其显示在界面上。 4. 同时,在每一显示之后,可以使用一个视频计数器对当前播放的数进行累加,并判断是否超过了设定的播放时间。 5. 当播放时间超过设定的时间后,停止播放视频并关闭FrameGrabber对象。 通过以上步骤,我们可以实现对视频播放长度的限制。当达到设定的播放时间后,即使视频文件还未播放完毕,也会停止播放。 需要注意的是,由于JavaCV是对FFmpeg的封装,因此也可以直接使用FFmpeg的命令行参数来实现对视频播放长度的限制。通过设置“-t”参数,可以指定视频文件要播放的最长时间,超过指定时间后,播放会自动停止。但这种方法需要对FFmpeg命令行的使用比较熟悉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值