视频抽帧并上传OBS

该代码示例展示了如何使用JavaCV库中的FFmpegFrameGrabber从视频中抽取帧,并利用Java2DFrameConverter转换为BufferedImage,进一步将帧转换为InputStream对象。然后,这些帧被存储为InputStream并上传到OBS(OpenBroadcastingSoftware)服务器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽帧流程:

工具类:

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 视频抽帧工具
 */
@Slf4j
public class VideoFrame {

    public static void main(String[] args) throws IOException {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMdd");
        String videiUrl = "D:/video/抖音测试2.mp4";
        Map<Integer, InputStream> integerInputStreamMap = videoIntercept(videiUrl, 1, 10, false);
        Map<Integer, InputStream> integerInputStreamMapObs = new HashMap<>(integerInputStreamMap);
        System.out.println(integerInputStreamMap.size());
        for (Integer seconds : integerInputStreamMap.keySet()) {
            InputStream inputStream = integerInputStreamMap.get(seconds);
            String fileName = MD5Util.createMd5("抖音测试2" + "_" + seconds) + ".jpg";
            String filePath = FilenameUtils.getFileName("/data/xhh", fileName, LocalDateTime.now().format(format), "douyin", "frame");
            //上传OBS
            String obsUploadUrl = UploadToObs.uploadAndGetKey(filePath, inputStream);
            System.out.println("seconds: "+seconds+", obsUploadUrl: " + obsUploadUrl);
        }
    }

    /**
     * 视频文件指定时间段的帧截取
     * @param videoUrl 视频文件URL
     * @param start 视频开始的帧
     * @param count 需要截取的帧个数
     * @param isAvgTime 在截帧时 是否均匀分布计算时间
     * @return
     */
    public static Map<Integer, InputStream> videoIntercept(String videoUrl, int start, int count, boolean isAvgTime) {
        Frame frame = null;
        //<时间, 图片流>
        Map<Integer, InputStream> files = new HashMap<>();
        FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoUrl);
        try {
            fFmpegFrameGrabber.start();
            long frameTime = 1;
            if(isAvgTime){
                frameTime = fFmpegFrameGrabber.getLengthInTime()/count/1000000L;
                if(frameTime < 0){
                    frameTime = 1;
                }
            }
            for(int i=start; i<=count; i++){
                fFmpegFrameGrabber.setTimestamp(i*frameTime*1000*1000);
                frame = fFmpegFrameGrabber.grabImage();
                InputStream inputStream = doExecuteFrame(frame, i);
                if(inputStream != null){
                    files.put(i, inputStream);
                }
            }
            fFmpegFrameGrabber.stop();
        } catch (Exception E) {
            E.printStackTrace();
        }
        return  files;
    }
    public static InputStream doExecuteFrame(Frame frame, int index) {
        if ( frame == null || frame.image == null) {
            return null;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(frame);
        InputStream inputStream = bufferedImageToInputStream(bi);
        return inputStream;
    }

    public static InputStream bufferedImageToInputStream(BufferedImage image){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            return input;
        } catch (IOException e) {
        }
        return null;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值