Java 视频处理,截帧操作

简介: Java 视频处理,截帧操作

Java 视频处理,截帧操作

1.maven
           org.bytedeco
           javacv
           1.4.1
           org.bytedeco
           javacpp
           1.4.1
           org.bytedeco.javacpp-presets
           opencv-platform
           3.4.1-1.4.1
           org.bytedeco.javacpp-presets
           ffmpeg-platform
           3.4.2-1.4.1
2.工具类
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_videoio;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;
import java.util.List;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_videoio.*;
/**
 * 视频工具
 *
 * @author
 */
public class VideoUtil {
    private static final int SECOND = 50;
    private static final Logger logger = LoggerFactory.getLogger(VideoUtil.class);
    /**
     * 获取指定视频的帧并保存为图片至指定目录
     *
     * @param videoFile 源视频文件
     * @param saveFile  截取帧的图片存放路径
     * @throws Exception
     */
    public static List fetchPic(File videoFile, String saveFile, int second) throws Exception {
        java.util.List files = new ArrayList<>();
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
        ff.start();
        int lenght = ff.getLengthInAudioFrames();
        System.out.println(ff.getFrameRate());
        int i = 0;
        Frame frame = null;
        while (i < lenght) {
            // 过滤前5帧,避免出现全黑的图片,依自己情况而定
            frame = ff.grabImage();
            if (i >= (int) (ff.getFrameRate() * second) && frame.image != null) {
                System.out.print(i + ",");
                if (frame != null && frame.image != null) {
                    System.out.println(i);
                    files.add(writeToFile(frame, saveFile, i));
                }
                second++;
            }
            i += second;
        }
        ff.stop();
        return files;
    }
    public static List getList(int count, int length) {
        if (count > length) {
            count = length;
        }
        System.out.println(length);
        System.out.println(count);
        int total = (int) (length / count);
        List list = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            list.add(i * total);
            System.out.println(i * total);
        }
        return list;
    }
    public static List fetchPicByCount(File videoFile, String saveFile, int count) throws Exception {
        java.util.List files = new ArrayList<>();
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
        ff.start();
        int frameLength = ff.getLengthInFrames();
        System.out.println("length:" + frameLength);
        List list = getList(count, frameLength);
        System.out.println(ff.getFrameRate());
        int i = 0;
        Frame frame = null;
        while (i < frameLength) {
            frame = ff.grabImage();
            if (list.contains(i)) {
                if (frame != null && frame.image != null) {
                    System.out.println(i);
                    files.add(writeToFile(frame, saveFile, i));
                }
            }
            i++;
        }
        ff.stop();
        return files;
    }
    public static File writeToFile(Frame frame, String saveFile, int second) throws InvokeException {
        String fileName = String.valueOf(System.currentTimeMillis()) + second;
        File targetFile = new File(saveFile + File.separator + fileName + ".jpg");
        String imgSuffix = "jpg";
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcBi = converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        } catch (Exception e) {
            throw new InvokeException(ResultEnum.FAILED.getCode(), "截帧失败");
        }
        return targetFile;
    }
    /**
     * 获取视频时长,单位为秒
     *
     * @param file
     * @return 时长(s)
     */
    public static Long getVideoTime(File file) {
        Long times = 0L;
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
            ff.start();
            times = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return times;
    }
    public static void getBySecond(String filePath, String directory) {
        opencv_videoio.CvCapture capture = cvCaptureFromFile(filePath);
        //帧率
        double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
        System.out.println("帧率:" + fps);
        opencv_core.IplImage frame = null;
        double pos1 = 0;
        double rootCount = 0;
        while (true) {
            //读取关键帧
            frame = cvQueryFrame(capture);
            rootCount = fps;
            while (rootCount > 0) {
                //这一段的目的是跳过每一秒钟的帧数,也就是说fps是帧率(一秒钟有多少帧),在读取一帧后,跳过fps数量的帧就相当于跳过了1秒钟。
                frame = cvQueryFrame(capture);
                rootCount--;
            }
            //获取当前帧的位置
            pos1 = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
            System.out.println(pos1);
            if (null == frame)
                break;
            cvSaveImage("E:/223/" + pos1 + ".jpg", frame);
        }
        cvReleaseCapture(capture);
    }
    /*public void getBySecond() {
        opencv_videoio.CvCapture capture = opencv_highgui.cvC("D:/085402.crf");
        //帧率
        int fps = (int) opencv_highgui.cvGetCaptureProperty(capture, opencv_highgui.CV_CAP_PROP_FPS);
        System.out.println("帧率:"+fps);
        opencv_core.IplImage frame = null;
        double pos1 = 0;
        int rootCount = 0;
        while (true) {
            //读取关键帧
            frame = opencv_highgui.cvQueryFrame(capture);
            rootCount = fps;
            while(rootCount > 0 ){
                //这一段的目的是跳过每一秒钟的帧数,也就是说fps是帧率(一秒钟有多少帧),在读取一帧后,跳过fps数量的帧就相当于跳过了1秒钟。
                frame = opencv_highgui.cvQueryFrame(capture);
                rootCount--;
            }
            //获取当前帧的位置
            pos1 = opencv_highgui.cvGetCaptureProperty(capture,opencv_highgui.CV_CAP_PROP_POS_FRAMES);
            System.out.println(pos1);
            if (null == frame)
                break;
            opencv_highgui.cvSaveImage("d:/img/" + pos1 + ".jpg",frame);
        }
        opencv_highgui.cvReleaseCapture(capture);
    }*/
    public static void main(String[] args) {
        try {
            //getList(10,113);
            File file = new File("E:/2.mp4");
            List files = VideoUtil.fetchPicByCount(file, "E:/223", 100);
            System.out.println(files.get(0).getName());
            System.out.println(VideoUtil.getVideoTime(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


 

参考:https://blog.csdn.net/qq_22175485/article/details/81025525


相关文章
|
5天前
|
分布式计算 DataWorks Java
DataWorks操作报错合集之在使用MaxCompute的Java SDK创建函数时,出现找不到文件资源的情况,是BUG吗
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
27 0
|
5天前
|
Java Android开发
java利用xml-rpc协议操作wordpress博客
java利用xml-rpc协议操作wordpress博客
12 1
|
5天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
【4月更文挑战第28天】本文简要介绍了自动化测试的实战应用,通过一个在线问卷调查(&lt;https://www.sojump.com/m/2792226.aspx/&gt;)为例,展示了如何遍历并点击问卷中的选项。测试思路包括找到单选和多选按钮的共性以定位元素,然后使用for循环进行点击操作。代码设计方面,提供了Java+Selenium的示例代码,通过WebDriver实现自动答题。运行代码后,可以看到控制台输出和浏览器的相应动作。文章最后做了简单的小结,强调了本次实践是对之前单选多选操作的巩固。
25 0
|
1天前
|
JavaScript 前端开发 测试技术
《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)
【5月更文挑战第12天】本文介绍了WebDriver中用于判断元素状态的三个方法:`isEnabled()`、`isSelected()`和`isDisplayed()`。`isSelected()`检查元素是否被选中,通常用于勾选框。`isDisplayed()`则用来判断元素是否在页面上可见。`isEnabled()`方法确定元素是否可操作,例如是否能点击或输入内容。
11 1
|
5天前
|
监控 Java
Java一分钟之-NIO:非阻塞IO操作
【5月更文挑战第14天】Java的NIO(New IO)解决了传统BIO在高并发下的低效问题,通过非阻塞方式提高性能。NIO涉及复杂的选择器和缓冲区管理,易出现线程、内存和中断处理的误区。要避免这些问题,可以使用如Netty的NIO库,谨慎设计并发策略,并建立标准异常处理。示例展示了简单NIO服务器,接收连接并发送欢迎消息。理解NIO工作原理和最佳实践,有助于构建高效网络应用。
8 2
|
5天前
|
安全 Java 数据安全/隐私保护
Java一分钟之-Java反射机制:动态操作类与对象
【5月更文挑战第12天】本文介绍了Java反射机制的基本用法,包括获取Class对象、创建对象、访问字段和调用方法。同时,讨论了常见的问题和易错点,如忽略访问权限检查、未捕获异常以及性能损耗,并提供了相应的避免策略。理解反射的工作原理和合理使用有助于提升代码灵活性,但需注意其带来的安全风险和性能影响。
23 4
|
5天前
|
Java API
Java操作elasticsearch
Java操作elasticsearch
11 0
|
5天前
|
NoSQL Java Redis
在Java中操作Redis
在Java中操作Redis
13 0
|
5天前
|
SQL Java 关系型数据库
【JAVA基础篇教学】第十六篇:Java连接和操作MySQL数据库
【JAVA基础篇教学】第十六篇:Java连接和操作MySQL数据库
|
5天前
|
Oracle 关系型数据库 Java
java操作多数据源将oracle数据同步达梦数据库
java操作多数据源将oracle数据同步达梦数据库