首页 > 编程语言 >Java使用javacv处理视频文件过程记录

Java使用javacv处理视频文件过程记录

时间:2024-04-15 18:12:15浏览次数:29  
标签:视频 Java import grabber org 视频文件 javacv recorder

最近接到一个需求是将.mp4/.m4v文件体积进行压缩,我使用javacv中的FFmpegFrameGrabber、FFmpegFrameFilter、FFmpegFrameRecorder简单的实现视频帧的抓取、过滤、录制与输出。
性能暂未验证。文章对这次的过程进行记录。


1.jdk的选择
mcr.microsoft.com/java/jdk:8u222-zulu-centos


2.maven依赖

`<dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.4</version>
</dependency>
<dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.4.4</version>
</dependency>`

3.实现过程

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.avutil;
import org.bytedeco.javacv.FFmpegFrameFilter;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.junit.Test;

@Slf4j
public class CoverVideoImageResolution {

    @Test
    public void changeResolution() {
        String inputFilePath = "原文件地址";
        String outputFilePath = "目标文件地址";

        // 创建一个视频帧抓取器
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFilePath);
        // 创建一个视频帧过滤器,用于修改视频分辨率
        FFmpegFrameFilter frameFilter = new FFmpegFrameFilter("scale=720:480", grabber.getImageWidth(), grabber.getImageHeight());
        // 创建一个视频帧录制器,用于将处理后的视频帧写入输出文件
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFilePath, 720, 480);

        try {
            long now = System.currentTimeMillis();
            // 开始从输入文件中抓取视频帧
            grabber.start();
            log.info("Video Frame Rate:{};",grabber.getFrameRate());
            log.info("Video Width:{};",grabber.getImageWidth());
            log.info("Video Height:{};",grabber.getImageHeight());
            log.info("Video Bitrate:{};",grabber.getVideoBitrate());
            log.info("Video Sample Rate:{};",grabber.getSampleRate());
            log.info("Video Codec:{};",grabber.getVideoCodec());
            // 启动视频帧过滤器
            frameFilter.start();
            // 设置输出视频的格式,与输入视频相同
            recorder.setFormat(grabber.getFormat());
            // 设置视频的采样率和帧速率与输入视频相同
            recorder.setSampleRate(grabber.getSampleRate());
            recorder.setFrameRate(grabber.getFrameRate());
            // 设置视频比特率,值越大视频质量越好,文件体积也越大,可根据需要调整
            log.info("原视频比特率:{}", grabber.getVideoBitrate());
            //CRF 的值范围是0到51,其中 0 表示无损压缩,而 51 表示质量非常差的压缩
            recorder.setOption("crf","28");
            // 设置视频比特率
            recorder.setVideoBitrate(grabber.getVideoBitrate()/2);
            // 设置视频编解码器为h.264
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 设置视频编解码器为h.264
            // 设置像素格式为YUV420P
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            // 设置音频参数
            recorder.setAudioChannels(2); // 设置音频通道数
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); // 设置音频编解码器
            recorder.setSampleRate(grabber.getSampleRate()); // 设置音频采样率
            recorder.setAudioBitrate(grabber.getAudioBitrate()); // 音频比特率
            // 启动视频帧录制器
            recorder.start();

            Frame frame;
            // 处理视频帧并将处理后的帧写入输出文件
            while ((frame = grabber.grab()) != null) {
                frameFilter.push(frame);// 将抓取的视频帧传递给过滤器
                Frame filteredFrame = frameFilter.pull();// 获取过滤后的视频帧
                recorder.record(filteredFrame);// 将过滤后的视频帧写入输出文件
            }
            // 停止视频帧抓取器、过滤器和录制器
            grabber.stop();
            frameFilter.stop();
            recorder.stop();
            System.out.println("Video resolution modified successfully.");
            log.info("压缩耗时:{}秒",  (System.currentTimeMillis()-now)/1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

标签:视频,Java,import,grabber,org,视频文件,javacv,recorder
From: https://www.cnblogs.com/mxzeve/p/18113036

相关文章

  • java中接口多个实现类,如何指定实现类,根据子类类型选择实现方法
    问题背景在Java代码中,经常会遇到一个接口有多个实现的情况。而这些实现类的参数又是不同的子类,这时候我们该如何选择正确的实现方法呢?解决方案我们可以通过判断参数的子类类型来选择正确的实现方法。具体实现可以使用Java中的instanceof关键字,它可以判断一个对象是否是某个类的......
  • Java并发编程实战读书笔记
    1.线程池模型    netty实战中讲到的线程池模型可以描述为:1.从线程池中选择一个空间的线程去执行任务,2.任务完成时,把线程归还给线程池。这个模型与连接池类似。    根据jdk源码的研究,具体的实现模型是,线程池ThreadPoolExecutor中有一个静态内部类Worker,使用装饰器模式扩......
  • java基础_03_包机制
    1、包的本质,就是文件夹 2、建包方法: packagecom.baidu.hhb;//这就是包,必须加在整个类的最上边,不能删,删除后下面的类就找不到包importxiaodi_java_base.*;//*通配符,可以导入该目录下所有的类。importxiaodi_java_base.khhhk;//导入类importjava.util.Date;......
  • day06_我的Java学习笔记 (综合应用专题课)
    专题课(综合案例)案例一:买飞机票案例二:找素数上述老师代码有点问题,即:j<i/2;应为j<=i/2;见如下判断:其实出问题的点,只会在i=4时,因为当i=4时,j<i/2:不成立,直接跳过该循环,执行步骤3的操作了。(当范围不是101-200,而是包含了4,则会出现上述的现象,因4不满......
  • day04_我的Java学习笔记 (数组的静态初始化、数组的动态初始化,debug调试等)
    1.数组1.1数组的定义那python怎么定义数组的呢?Java:String[]names={"zhangsan","lisi","wangwu"}Python:names=["zhangsan","lisi","wangwu"]在python中,列表可以存储不同类型的数据,而在Java中,数组只能存储相同类型的数据。1......
  • day02_我的Java学习笔记 (类型转换、+做连接符、变量自增自减运算、三元运算符、键盘
    Java语言基础知识1.类型转换1.1自动类型转换1.2表达式的自动类型转换1.3强制类型转换这里得出的结果为啥是-36呢???后面高级篇再细讲。2.运算符2.1算数运算符2.1.1基本算数运算符2.1.2案例:数值拆分2.2+符号做连接符【思考1】:a+'a'为啥......
  • 十款优质企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目,减少开发工作!)
     Java微服务开源项目前言一、pig二、zheng三、SpringBlade四、SOP五、matecloud六、mall七、jeecg-boot八、Cloud-Platform九、microservices-platform十、RuoYi-Cloud 前言这篇文章为大家推荐几款优质的Java开源项目框架,可以用于学习,毕业设计,公司项目......
  • 【Kubernetes 系列】如何优雅的配置 Java 微服务
    【Kubernetes系列】如何优雅的配置Java微服务 目标创建KubernetesConfigMap和Secret使用MicroProfileConfig注入微服务配置一、实现外部化应用配置在Kubernetes中,为docker容器设置环境变量有几种不同的方式,比如:Dockerfile、kubernetes.yml、Kubernet......
  • Java微服务框架一览
    Java微服务框架一览微服务在开发领域的应用越来越广泛,因为开发人员致力于创建更大、更复杂的应用程序,而这些应用程序作为微小服务的组合能够更好地得以开发和管理。这些微小的服务可以组合在一起工作,并实现更大、应用更广泛的功能。现在出现了很多的工具来满足使用逐段法而不......
  • java实现的微服务架构_详解Java 微服务架构
    java实现的微服务架构_详解Java微服务架构一、传统的整体式架构传统的整体式架构都是模块化的设计逻辑,如展示(Views)、应用程序逻辑(Controller)、业务逻辑(Service)和数据访问对象(Dao),程序在编写完成后被打包部署为一个具体的应用。如图所示:系统的水平扩展如果要对系统......