Java使用FFmpeg处理视频文件指南

本文详述如何使用Java结合FFmpeg处理视频文件,包括信息提取、码率压缩、分辨率转换等。介绍引入JAVE.jar框架和手动安装FFmpeg的方法,并给出代码结构解析、MediaUtil.java主程序类的使用注意事项以及在CentOS服务器上安装FFmpeg的指南。
摘要由CSDN通过智能技术生成

本文主要讲述如何使用Java + FFmpeg实现对视频文件的信息提取、码率压缩、分辨率转换等功能;

之前在网上浏览了一大圈Java使用FFmpeg处理音视频的文章,大多都讲的比较简单

1. 什么是FFmpeg

点我了解

2. 开发前准备

在使用Java调用FFmpeg处理音视频之前,需要先安装FFmpeg,安装方法分为两种:

  • 引入封装了FFmpeg的开源框架
  • 在系统中手动安装FFmpeg

2.1 引入封装了FFmpeg的开源框架

JAVE.jar(官网点我) 是一个封装了FFmpeg的Java框架,在项目中能直接调用它的API来处理音视频文件;

优点:使用方便,直接在项目中引入JAVE.jar即可处理媒体文件,且开发完成后可以随工程一起打包发布,不需要在目标运行环境内手动安装FFmpeg相关的类库

缺点:JAVE.jar最后一次更新是2009年,其封装的FFmpeg版本是09年或更早前的版本,比较老旧,无法使用一些新特性
(当然也可以看看有没有其他比较新的封装了FFmpeg的框架)

Maven坐标如下:

<dependency>
    <groupId>org.ffmpeg</groupId>
    <artifactId>sdk</artifactId>
    <version>1.0.2</version>
</dependency>

2.2 在系统中手动安装FFmpeg

在运行环境中手动安装FFmpeg稍微有一些麻烦,可以百度 windows/mac安装FFmpeg 这样的关键字,根据网上的安装教程将FFmpeg安装到系统中;

懒人链接:Windows安装教程 Mac安装教程

优点:可以直接调用FFmpeg的相关API处理音视频,FFmpeg版本可控

缺点:手动安装较为麻烦,开发环境与目标运行环境都需要先安装好FFmpeg

3. 使用FFmpeg处理音视频

使用JAVE.jar进行开发与直接使用FFmpeg开发的代码有一些不同,这里以直接使用FFmpeg进行开发的代码进行讲解(开发环境MacOS);(使用JAVE的代码、直接使用FFmpeg的代码都会附在文末供大家下载参考)

通过MediaUtil.java类及其依赖的类,你将可以实现:

  • 解析源视频的基本信息,包括视频格式、时长、码率等;
  • 解析音频、图片的基本信息;
  • 将源视频转换成不同分辨率、不同码率、带或不带音频的新视频;
  • 抽取源视频中指定时间点的帧画面,来生成一张静态图;
  • 抽取源视频中指定时间段的帧画面,来生成一个GIF动态图;
  • 截取源视频中的一段来形成一个新视频;
  • 抽取源视频中的音频信息,生成单独的MP3文件;
  • 对音视频等媒体文件执行自定义的FFmpeg命令;

3.1 代码结构梳理

MediaUtil.java是整个解析程序中的核心类,封装了各种常用的解析方法供外部调用;

MetaInfo.java定义了多媒体数据共有的一些属性,VideoMetaInfo.java MusicMetaInfo.java ImageMetaInfo.java都继承自MetaInfo.java,分别定义了视频、音频、图片数据相关的一些属性;

AnimatedGifEncoder.java LZWEncoder.java NeuQuant.java在抽取视频帧数、制作GIF动态图的时候会使用到;

CrfValueEnum.java 定义了三种常用的FFmpeg压缩视频时使用到的crf值,PresetVauleEnum.java定义了FFmpeg压缩视频时常用的几种压缩速率值;

有关crf、preset的延伸阅读点我

3.2 MediaUtil.java主程序类解析

3.2.1 使用前需要注意的几点

  1. 指定正确的FFmpeg程序执行路径

    MacOS安装好FFmpeg后,可以在控制台中通过which ffmpeg命令获取FFmpeg程序的执行路径,在调用MediaUtil.java前先通过其 setFFmpegPath() 方法设置好FFmpeg程序在系统中的执行路径,然后才能顺利调用到FFmpeg去解析音视频;

    Windows系统下该路径理论上应设置为:FFmpeg可执行程序在系统中的绝对路径(实际情况有待大家补充)
  2. 指定解析音视频信息时需要的正则表达式

    因项目需要解析后缀格式为 .MP4 .WMV .AAC 的视频和音频文件,所以我研究了JAVE.jar底层调用FFmpeg时的解析逻辑后,在MediaUtil.java中设置好了匹配这三种格式的正则表达式供解析时使用(参考程序中的 durationRegex videoStreamRegex musicStreamRegex 这三个表达式值);

    注意:如果你需要解析其他后缀格式如 .MKV .MP3 这样的媒体文件时,你很可能需要根据实际情况修改durationRegex videoStreamRegex musicStreamRegex 这三个正则表达式的值,否则可能无法解析出正确的信息;
  3. 程序中的很多默认值你可以根据实际需要修改,比如视频帧抽取的默认宽度或高度值、时长等等;

3.2.2 MediaUtil.java代码

package media;

import lombok.extern.slf4j.Slf4j;
import media.domain.ImageMetaInfo;
import media.domain.MusicMetaInfo;
import media.domain.VideoMetaInfo;
import media.domain.gif.AnimatedGifEncoder;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 基于FFmpeg内核来编解码音视频信息;
 * 使用前需手动在运行环境中安装FFmpeg运行程序,然后正确设置FFmpeg运行路径后MediaUtil.java才能正常调用到FFmpeg程序去处理音视频;
 *
 * Author: dreamer-1
 * 
 * version: 1.0
 *
 */
@Slf4j
public class MediaUtil {

    /**
     * 可以处理的视频格式
     */
	public final static String[] VIDEO_TYPE = { "MP4", "WMV" };
    /**
     * 可以处理的图片格式
     */
	public final static String[] IMAGE_TYPE = { "JPG", "JPEG", "PNG", "GIF" };
    /**
     * 可以处理的音频格式
     */
    public final static String[] AUDIO_TYPE = { "AAC" };

    /**
     * 视频帧抽取时的默认时间点,第10s(秒)
     * (Time类构造参数的单位:ms)
     */
	private static final Time DEFAULT_TIME = new Time(0, 0, 10);
    /**
     * 视频帧抽取的默认宽度值,单位:px
     */
	private static int DEFAULT_WIDTH = 320;
    /**
     * 视频帧抽取的默认时长,单位:s(秒)
     */
	private static int DEFAULT_TIME_LENGTH = 10;
    /**
     * 抽取多张视频帧以合成gif动图时,gif的播放速度
     */
    private static int DEFAULT_GIF_PLAYTIME = 110;
    /**
     * FFmpeg程序执行路径
     * 当前系统安装好ffmpeg程序并配置好相应的环境变量后,值为ffmpeg可执行程序文件在实际系统中的绝对路径
     */
	private static String FFMPEG_PATH = "/usr/bin/ffmpeg"; // /usr/bin/ffmpeg


    /**
     * 视频时长正则匹配式
     * 用于解析视频及音频的时长等信息时使用;
     *
     * (.*?)表示:匹配任何除\r\n之外的任何0或多个字符,非贪婪模式
     *
     */
	private static String durationRegex = "Duration: (\\d*?):(\\d*?):(\\d*?)\\.(\\d*?), start: (.*?), bitrate: (\\d*) kb\\/s.*";
    private static Pattern durationPattern;
	/**
     * 视频流信息正则匹配式
     * 用于解析视频详细信息时使用;
     */
	private static String videoStreamRegex = "Stream #\\d:\\d[\\(]??\\S*[\\)]??: Video: (\\S*\\S$?)[^\\,]*, (.*?), (\\d*)x(\\d*)[^\\,]*, (\\d*) kb\\/s, (\\d*[\\.]??\\d*) fps";
    private static Pattern videoStreamPattern;
	/**
     * 音频流信息正则匹配式
     * 用于解析音频详细信息时使用;
     */
	private static String musicStreamRegex = "Stream #\\d:\\d[\\(]??\\S*[\\)]??: Audio: (\\S*\\S$?)(.*), (.*?) Hz, (.*?), (.*?), (\\d*) kb\\/s";;
	private static Pattern musicStreamPattern;

    /**
     * 静态初始化时先加载好用于音视频解析的正则匹配式
     */
	static {
        durationPattern = Pattern.compile(durationRegex);
        videoStreamPattern = Pattern.compile(videoStreamRegex);
        musicStreamPattern = Pattern.compile(musicStreamRegex);
    }

	/**
	 * 获取当前多媒体处理工具内的ffmpeg的执行路径
	 * @return
	 */
	public static String getFFmpegPath() {
		return FFMPEG_PATH;
	}

    /**
     * 设置当前多媒体工具内的ffmpeg的执行路径
     * @param ffmpeg_path ffmpeg可执行程序在实际系统中的绝对路径
     * @return
     */
	public static boolean setFFmpegPath(String ffmpeg_path) {
	    if (StringUtils.isBlank(ffmpeg_path)) {
	        log.error("--- 设置ffmpeg执行路径失败,因为传入的ffmpeg可执行程序路径为空! ---");
	        return false;
        }
        File ffmpegFile = new File(ffmpeg_path);
        if (!ffmpegFile.exists()) {
            log.error("--- 设置ffmpeg执行路径失败,因为传入的ffmpeg可执行程序路径下的ffmpeg文件不存在! ---");
            return false;
        }
	    FFMPEG_PATH = ffmpeg_path;
        log.info("--- 设置ffmpeg执行路径成功 --- 当前ffmpeg可执行程序路径为: " + ffmpeg_path);
	    return true;
    }

    /**
     * 测试当前多媒体工具是否可以正常工作
     * @return
     */
    public static b
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值