java 精简使用ffmpeg

xml 复制代码
    <properties>
        <java.version>25</java.version>
        <mybatis-flex.version>1.11.7</mybatis-flex.version>
        <awssdk.version>2.42.21</awssdk.version>
        <javacv.version>1.5.13</javacv.version>
        <ffmpeg.version>8.0.1-${javacv.version}</ffmpeg.version>
        <spring-ai.version>2.0.0</spring-ai.version>
        <spring-ai-session.version>0.6.0</spring-ai-session.version>
    </properties>
     <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
        </dependency>
            <profiles>
        <profile>
            <id>window</id>
            <dependencies>
                <dependency>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>ffmpeg</artifactId>
                    <version>${ffmpeg.version}</version>
                    <classifier>windows-x86_64</classifier>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>linux</id>
            <dependencies>
                <dependency>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>ffmpeg</artifactId>
                    <version>${ffmpeg.version}</version>
                    <classifier>linux-x86_64</classifier>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
java 复制代码
package com.kongjs.smo.common.util;

import org.bytedeco.javacv.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class FFmpegUtil {
    private static final Logger log = LoggerFactory.getLogger(FFmpegUtil.class);

    public static void captureFirstFrame(String videoPath, String outImgPath, String format) {
        FFmpegFrameGrabber grabber = null;
        Java2DFrameConverter converter = new Java2DFrameConverter();
        try {
            grabber = new FFmpegFrameGrabber(videoPath);
            grabber.start();
            if (grabber.getImageWidth() <= 0 || grabber.getImageHeight() <= 0) {
                return;
            }
            Frame frame = null;
            int tryCount = 0;
            while (tryCount < 100) {
                frame = grabber.grabFrame();
                tryCount++;
                if (frame != null && frame.image != null) {
                    break;
                }
            }
            if (frame == null || frame.image == null) {
                return;
            }
            BufferedImage image = converter.convert(frame);
            ImageIO.write(image, format, new File(outImgPath));
        } catch (FFmpegFrameGrabber.Exception e) {
            // 帧读取器异常
            log.error("FFmpeg解码视频失败:" + e.getMessage());
        } catch (FrameGrabber.Exception e) {
            // FFmpeg 底层解码
            log.error("帧采集器读取异常:" + e.getMessage());
        } catch (IOException e) {
            // 文件流异常
            log.error("文件IO读写失败:" + e.getMessage());
        } finally {
            // 强制释放资源,防止句柄泄漏
            if (grabber != null) {
                try {
                    grabber.stop();
                    grabber.close();
                } catch (Exception ignored) {
                }
            }
        }
    }

    public static void captureFirstFrame(String videoPath, String outImgPath, String format, int thumbWidth, int thumbHeight, int quality) {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        try {
            grabber = new FFmpegFrameGrabber(videoPath);
            grabber.start();
            if (grabber.getImageWidth() <= 0 || grabber.getImageHeight() <= 0) {
                return;
            }
            Frame frame = null;
            int tryCount = 0;
            while (tryCount < 100) {
                // 抓取关键帧,避免黑屏
                frame = grabber.grabKeyFrame();
                tryCount++;
                if (frame != null && frame.image != null) {
                    break;
                }
            }
            if (frame == null || frame.image == null) {
                return;
            }
            int width = grabber.getImageWidth();
            int height = grabber.getImageHeight();
            recorder = new FFmpegFrameRecorder(outImgPath, width, height);
            recorder.setFormat(format);
            recorder.setVideoQuality(quality);
            recorder.start();
            recorder.record(frame);
        } catch (FFmpegFrameGrabber.Exception e) {
            // 帧读取器异常
            log.error("FFmpeg解码视频失败:" + e.getMessage());
        } catch (FrameGrabber.Exception e) {
            // FFmpeg 底层解码
            log.error("帧采集器读取异常:" + e.getMessage());
        } catch (IOException e) {
            // 文件流异常
            log.error("文件IO读写失败:" + e.getMessage());
        } finally {
            if (recorder != null) {
                try {
                    recorder.close();
                } catch (Exception ignored) {
                }
            }
            // 强制释放资源,防止句柄泄漏
            if (grabber != null) {
                try {
                    grabber.close();
                } catch (Exception ignored) {
                }
            }
        }
    }

    static void main() {
        captureFirstFrame("C:\\Users\\101202104016\\Videos\\Captures\\111111111111111111111111111111.mp4","C:\\Users\\101202104016\\Videos\\Captures\\111111111111111111111111111111.webp",
                "webp",400,400,75);
    }

}
相关推荐
cfm_29148 分钟前
线程池阻塞队列
java·开发语言
xxwxx__26 分钟前
C++ list 深度解析:从使用原理到模拟实现
开发语言·c++·list
坐吃山猪29 分钟前
【多线程】ThreadPool线程池参数说明
java·网络
Chester_199937 分钟前
CSP202303C.LDAP
开发语言·c++·蓝桥杯·stl
奋斗吧程序媛1 小时前
CSV文件导入功能
开发语言·javascript·ecmascript
evans在进步1 小时前
Java 常用设计模式(二):装饰器、适配器、责任链、模板方法、策略与观察者
java·开发语言·设计模式
jvmind_dev1 小时前
频繁 new JedisCluster 之后,对象池为什么回不去了?
java·后端
小雨笙笙1 小时前
C语言:指针
c语言·开发语言
AKA__Zas2 小时前
文件 I/O(速通版
java·intellij-idea·学习方法
学长毕业设计2 小时前
基于SpringBoot的咖啡馆管理系统的设计与实现(源码+文档+讲解视频)
java·spring boot·后端