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);
    }

}
相关推荐
唐青枫1 小时前
Java Jersey 实战指南:用 JAX-RS 注解写清晰的 REST API
java
农村小镇哥1 小时前
python操作配置文件ini
开发语言·python
一只小小Java2 小时前
Naocs本地部署&安装3.2.3+Spring boot 3.2.0
java·spring boot·后端·nacos
JL152 小时前
Spring Boot vs Gin:Java 人搭第一个 Go REST API
java·spring boot·gin
神明不懂浪漫3 小时前
【第七章】Java中的常用类
java·开发语言·前端·经验分享·笔记
程序喵大人11 小时前
【C++进阶】STL容器与迭代器 - 01 STL 容器先解决元素放在哪里
开发语言·c++·stl
cui_ruicheng12 小时前
Python从入门到实战(十六):多进程编程
开发语言·python
Jelena1577958579212 小时前
电商运营分析数据比价接口实战:多平台价格监控与智能决策系统
java·大数据·数据库
wdfk_prog13 小时前
嵌入式面试真题第 15 题:不可恢复异常后的通用崩溃快照、调用栈保存与离线分析架构
linux·开发语言·面试·架构