2021SC@SDUSC-multimedia-utils-一款java后端的图片、视频处理工具jar包

本文档介绍了FFmpegUtils工具,用于处理多媒体文件,包括获取视频信息、截取封面和视频压缩等功能。getInfo方法能获取视频的详细信息如时长、大小、编码等;createCover用于截取视频封面,而putCompressionTask则用于视频压缩,支持自定义参数如最大帧率、比特率等。源码中展示了如何使用这些功能。
摘要由CSDN通过智能技术生成

2021SC@SDUSC 

目录

项目名称:multimedia-utils

文档

视频工具FFmpegUtils


项目名称:multimedia-utils

博客五

文档

上篇博客我们介绍了图片工具,并且给出了详细的介绍。下面我们介绍其他各个文件所实现的功能和用处。接下来看视频工具FFmpegUtils

视频工具FFmpegUtils

方法

1.获取视频信息

getInfo(tempDirectory,inputFileName)

输入参数

参数类型必需注释
tempDirectoryString临时文件目录
inputFileNameString输入文件名

输出参数

参数类型必需注释
formatFFFormat文件信息
videoInfoVideoInfo视频信息
audioInfoAudioInfo音频信息

其中:

FFFormat

参数类型必需注释
filenameString文件名全路径名
durationString文件时长
sizeString文件大小
bitRateString文件比特率

VideoInfo

参数类型必需注释
codecNameString视频 编码名称
codecTypeString类型 video
widthInteger视频 宽度
heightInteger视频 高度
frameRateInteger视频 帧率
durationInteger视频 时长
bitRateInteger视频 比特率
nbFramesInteger视频 总帧数

AudioInfo

参数类型必需注释
codecNameString音频 编码名称
codecTypeString类型 audio
durationInteger音频 时长
bitRateInteger音频 比特率
sampleRateInteger音频 采样率
channelsInteger音频 声道数 1:单声道 2:双声道

2.截取视频封面

createCover(tempDirectory, inputFileName, outputFileSuffix)

createCover(tempDirectory, inputFileName)

输入参数

参数类型必需注释
tempDirectoryString临时文件目录
inputFileNameString输入文件名
outputFileSuffixSuffix输出文件格式,默认jpg

输出参数

参数类型必需注释
outputFileNameString输出文件名

3.视频压缩

putCompressionTask(tempDirectory, inputFileName, compressionAttributes)

putCompressionTask(tempDirectory, inputFileName, compressionAttributes, outputFileName)

输入参数

参数类型必需注释
tempDirectoryString临时文件目录
inputFileNameString输入文件名
compressionAttributesCompressionAttributes压缩参数
outputFileNameString输出文件名,默认UUID生成

其中:

CompressionAttributes

参数类型必需注释
videoAttributesVideoAttributes视频压缩参数
audioAttributesAudioAttributes音频压缩参数
progressUrlString压缩完成后的回调地址

VideoAttributes

参数类型必需注释
codecVideoCodec视频编码(默认libx264,libx265)
maxFpsInteger最大帧率
videoSizeVideoSize视频分辨率(hd480,hd720,hd1080,800x800)
maxDurationInteger最大时长
maxBitRateInteger视频最大比特率

AudioAttributes

参数类型必需注释
maxBitRateInteger音频最大比特率
maxSamplingRateInteger音频最大采样率

输出参数

参数类型必需注释
outputFileNameString输出文件名

 下面我们给出源码(我们已经在源码中给出了相应的注释)

import com.whty.zdxt.multimedia.enumeration.VideoSize;
import com.whty.zdxt.multimedia.pojo.AudioInfo;
import com.whty.zdxt.multimedia.pojo.FFStream;
import com.whty.zdxt.multimedia.pojo.FFmpegInfo;
import com.whty.zdxt.multimedia.pojo.VideoInfo;
import org.springframework.beans.BeanUtils;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FFmpegUtils {

    /**
     * ffmpeg命令ffprobe,需设置ffmpeg环境变量
     */
    private static final String FFPROBE = "ffprobe";

    /**
     * ffmpeg命令ffmpeg,需设置ffmpeg环境变量
     */
    private static final String FFMPEG = "ffmpeg";

    /**
     * 创建大小为 1 的固定线程池,同时执行任务的只有一个,
     * 其它的任务都放在LinkedBlockingQueue中排队等待执行
     */
    ExecutorService executorService = Executors.newSingleThreadExecutor();


    /**
     * 获取视频信息
     *
     * @param tempDirectory 临时文件目录
     * @param inputFileName 视频文件名
     * @return 文件信息
     */
    public FFmpegInfo getInfo(String tempDirectory, String inputFileName) {
        if (!FileUtils.checkFileName(inputFileName)) {
            throw new RuntimeException("输入文件名格式错误");
        }

        StringBuilder command = new StringBuilder();

        command.append(FFPROBE);
        command.append(" -v quiet -print_format json -show_format -show_streams ");
        command.append(FileUtils.getFilePath(tempDirectory, inputFileName));

        String response = RuntimeUtils.execSuccessful(command.toString());

        FFmpegInfo fFmpegInfo = JsonUtils.toBean(response, FFmpegInfo.class);

        if (fFmpegInfo.getStreams() == null) {
            throw new RuntimeException("文件不存在");
        }

        List<FFStream> streams = fFmpegInfo.getStreams();
        for (FFStream ffStream : streams) {
            if ("audio".equals(ffStream.getCodecType())) {
                AudioInfo audioInfo = new AudioInfo();
                BeanUtils.copyProperties(ffStream, audioInfo);
                fFmpegInfo.setAudioInfo(audioInfo);
            } else if ("video".equals(ffStream.getCodecType())) {
                VideoInfo videoInfo = new VideoInfo();
                BeanUtils.copyProperties(ffStream, videoInfo);
                String rFrameRate = ffStream.getrFrameRate();
                String[] split = rFrameRate.split("/");
                videoInfo.setFrameRate(Integer.valueOf(split[1]) == 0 ? 0 : (Integer.valueOf(split[0]) / Integer.valueOf(split[1])));
                fFmpegInfo.setVideoInfo(videoInfo);
            }
        }
        return fFmpegInfo;
    }

    /**
     * 获取封面图
     *
     * @param tempDirectory    临时文件目录
     * @param inputFileName    视频文件名
     * @param outputFileSuffix 输出文件后缀名
     * @return 封面文件名
     */
    public String createCover(String tempDirectory, String inputFileName, Suffix outputFileSuffix) {
        if (!FileUtils.checkFileName(inputFileName)) {
            throw new RuntimeException("输入文件名格式错误");
        }

        // 设置封面图格式
        String suffix = outputFileSuffix == null ? Suffix.JPG.getCode() : outputFileSuffix.getCode();

        String outputFileName = FileUtils.createFileName(suffix);

        StringBuilder command = new StringBuilder();
        command.append(FFMPEG);

        command.append(" -i ");

        command.append(FileUtils.getFilePath(tempDirectory, inputFileName));

        command.append(" -ss 1 -t 1 -r 1 -f image2 ");

        command.append(FileUtils.getFilePath(tempDirectory, outputFileName));

        RuntimeUtils.execSF(command.toString());

        return outputFileName;
    }

    /**
     * 获取封面图
     *
     * @param tempDirectory 临时文件目录
     * @param inputFileName 视频文件名
     * @return 封面文件名
     */
    public String createCover(String tempDirectory, String inputFileName) {
        return this.createCover(tempDirectory, inputFileName, null);
    }


    /**
     * 将任务放入执行队列中
     *
     * @param tempDirectory         临时文件目录
     * @param inputFileName         输入的文件名
     * @param compressionAttributes 压缩参数
     * @return 输出文件名
     */
    public String putCompressionTask(String tempDirectory, String inputFileName, CompressionAttributes compressionAttributes) {
        // 生成输出文件名
        String suffix = FileUtils.getSuffix(inputFileName);
        String outputFileName = FileUtils.createFileName(suffix);

        this.executeTask(tempDirectory, inputFileName, compressionAttributes, outputFileName);
        return outputFileName;
    }

    /**
     * 将任务放入执行队列中
     *
     * @param tempDirectory         临时文件目录
     * @param inputFileName         输入的文件名
     * @param compressionAttributes 压缩参数
     * @param outputFileName        输出的文件名
     * @return 输出文件名
     */
    public String putCompressionTask(String tempDirectory, String inputFileName, CompressionAttributes compressionAttributes, String outputFileName) {
        this.executeTask(tempDirectory, inputFileName, compressionAttributes, outputFileName);
        return outputFileName;
    }

    /**
     * 添加压缩任务
     */
    private void executeTask(String tempDirectory, String inputFileName, CompressionAttributes compressionAttributes, String outputFileName) {
        executorService.execute(new Runnable() {
            public void run() {
                compressionVideo(tempDirectory, inputFileName, compressionAttributes, outputFileName);
            }
        });
    }

    /**
     * 压缩视频文件
     *
     * @param tempDirectory         临时文件目录
     * @param inputFileName         原视频文件名
     * @param compressionAttributes 压缩参数
     * @param outputFileName        压缩视频文件名
     */
    private void compressionVideo(String tempDirectory, String inputFileName, CompressionAttributes compressionAttributes, String outputFileName) {


        if (!FileUtils.checkFileName(inputFileName)) {
            throw new RuntimeException("输入文件名格式错误");
        }
        if (!FileUtils.checkFileName(outputFileName)) {
            throw new RuntimeException("输出文件名格式错误");
        }

        if (compressionAttributes == null) {
            throw new RuntimeException("缺少压缩参数");
        }


        String progressUrl = compressionAttributes.getProgressUrl();
        if (progressUrl == null) {
            throw new RuntimeException("缺少压缩完成回调URL");
        }

        VideoAttributes videoAttributes = compressionAttributes.getVideoAttributes();
        AudioAttributes audioAttributes = compressionAttributes.getAudioAttributes();

        // 获取原视频信息
        FFmpegInfo info = this.getInfo(tempDirectory, inputFileName);
        VideoInfo videoInfo = info.getVideoInfo();
        AudioInfo audioInfo = info.getAudioInfo();

        StringBuilder command = new StringBuilder();

        command.append(FFMPEG);

        // 设置视频源
        command.append(" -i ");
        command.append(FileUtils.getFilePath(tempDirectory, inputFileName));
        command.append(" ");

        // 设置视频属性
        if (videoAttributes != null && videoInfo != null) {

            // 设置视频编码
            if (videoAttributes.getCodec() != null) {
                command.append("-c:v ");
                command.append(videoAttributes.getCodec().getCode());
                command.append(" ");
            }

            // 设置视频帧率
            if (this.isSetUp(videoInfo.getFrameRate(), videoAttributes.getMaxFps())) {
                command.append("-r ");
                command.append(videoAttributes.getMaxFps());
                command.append(" ");
            }

            // 设置视频比特率
            if (this.isSetUp(videoInfo.getBitRate(), videoAttributes.getMaxBitRate())) {
                command.append("-b:v ");
                command.append(videoAttributes.getMaxBitRate());
                command.append(" ");
            }

            // 设置视频宽度
            VideoSize videoSize = videoAttributes.getVideoSize();
            if (videoSize != null) {
                command.append("-s ");
                command.append(videoSize.getCode());
                command.append(" ");
            }

            // 设置视频时长
            if (this.isSetUp(Double.valueOf(videoInfo.getDuration()).intValue(), videoAttributes.getMaxDuration())) {
                command.append("-t ");
                command.append(videoAttributes.getMaxDuration());
                command.append(" ");
            }


        }

        // 设置音频属性
        if (audioAttributes != null && audioInfo != null) {
            // 设置音频比特率
            if (this.isSetUp(audioInfo.getBitRate(), audioAttributes.getMaxBitRate())) {
                command.append("-b:a ");
                command.append(audioAttributes.getMaxBitRate());
                command.append(" ");
            }

            // 设置音频采样率
            if (this.isSetUp(audioInfo.getSampleRate(), audioAttributes.getMaxSamplingRate())) {
                command.append("-ar ");
                command.append(audioAttributes.getMaxSamplingRate());
                command.append(" ");
            }
        }

        command.append(FileUtils.getFilePath(tempDirectory, outputFileName));

        command.append(" -progress ");

        command.append(progressUrl);

        RuntimeUtils.execFailure(command.toString());

    }


    /**
     * 截取文件(截取相应时长 start秒 - end秒)
     *
     * @param tempDirectory 临时文件目录
     * @param inputFileName 输入文件名
     * @param start         截取开始时间 单位s
     * @param end           截取结束时间 单位s
     * @return 输出文件名
     */
    public String copy(String tempDirectory, String inputFileName, Integer start, Integer end) {
        if (!FileUtils.checkFileName(inputFileName)) {
            throw new RuntimeException("输入文件名格式错误");
        }
        if (start == null || end == null) {
            throw new RuntimeException("缺少必要参数");
        }

        String suffix = FileUtils.getSuffix(inputFileName);
        String outputFileName = FileUtils.createFileName(suffix);

        StringBuilder command = new StringBuilder();

        command.append(FFMPEG);
        command.append(" -i ");
        command.append(FileUtils.getFilePath(tempDirectory, inputFileName));
        command.append(" -ss ");
        command.append(start);
        command.append(" -c copy -to ");
        command.append(end);
        command.append(" ");
        command.append(FileUtils.getFilePath(tempDirectory, outputFileName));

        RuntimeUtils.execFailure(command.toString());

        return outputFileName;
    }

    /**
     * 判断是否设置属性
     *
     * @param originalParameter 原视频属性
     * @param targetParameter   目标属性
     */
    private Boolean isSetUp(Integer originalParameter, Integer targetParameter) {
        if (originalParameter == null || targetParameter == null) {
            return false;
        }
        if (originalParameter <= targetParameter) {
            return false;
        }
        return true;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值