FFmpeg截屏、剪切一段视频、或者压缩视频

使用JavaCV进行精确视频剪切的问题与解决方案,
文章提供了一段使用JavaCV库进行视频剪切的代码,但指出在尝试精确剪切时可能会出现不准确的情况。代码通过FFmpegFrameGrabber和FFmpegFrameRecorder处理视频流,然而在某些情况下无法确保剪切的精确性,如需从20秒剪切到23秒。问题可能出在帧率计算上,代码尝试通过帧率来估算剪切的帧数。

网上大多是通过命令的显示操作ffmpeg,不太灵活
这里我给出剪切视频的一段代码,缺点是无法精确,比如我想剪切20秒,但是可能剪切好的是23秒。
其中FFmpegFrameRecorder(outputstream)操作流会报错。原因未知。

import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.util.MapUtil;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.opencv.video.Video;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.;
import java.security.SecureRandom;
import java.util.
;

@Slf4j
public class VideoUtils {

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

// t1();
cutVideo(new FileInputStream(“C:\Users\Xpdn\Videos\3.mp4”),
new File(“C:\Users\Xpdn\Videos\output.mp4”), 30L, 900L);

// t2();
}

public static File cutVideo(InputStream inputStream, File outFile, long beginSecond, long endSecond) throws Exception {
    FFmpegFrameGrabber grabber = null;
    FFmpegFrameRecorder recorder = null;
    try {
        grabber = new FFmpegFrameGrabber(inputStream);
        grabber.start();
        if (beginSecond < 0 || (grabber.getLengthInTime() / 1000000L) <= endSecond) {
            return null;
        }
        long numFrame = (long) ((endSecond - beginSecond) * grabber.getFrameRate()) * 2; // 120 * 25

// grabber.setVideoTimestamp(beginSecond * 1000000L);
grabber.setVideoFrameNumber((int) (grabber.getFrameRate() * beginSecond)); // 第分钟开始

        recorder = new FFmpegFrameRecorder(outFile, grabber.getImageWidth(), grabber.getImageHeight());
        recorder.setFormat("mp4");
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setVideoBitrate(grabber.getVideoBitrate());
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        recorder.setAudioChannels(2);
        recorder.start();

        Frame frame;
        long num = 0;
        while ((frame = grabber.grabFrame()) != null && (numFrame >= num)) {
            num++;
            // 处理每一帧的图像或音频数据
            recorder.record(frame);
        }
        return outFile;
    }catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (grabber != null) {
                grabber.stop();
                grabber.release();
            }
            if (recorder != null) {
                recorder.stop();
                recorder.release();
            }
        } catch (FFmpegFrameGrabber.Exception e1) {
            e1.printStackTrace();
        }
    }
    return null;
}

我的完整的工具类

package com.ruoyi.file.utils;

import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.util.MapUtil;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.opencv.video.Video;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.;
import java.security.SecureRandom;
import java.util.
;

@Slf4j
public class VideoUtils {

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

// t1();
cutVideo(new FileInputStream(“C:

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值