我是靠谱客的博主 想人陪手套,最近开发中收集的这篇文章主要介绍Java提取视频中的指定桢数生成视频缩略图的解决方案参考资料,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Java提取视频中的指定桢数生成视频缩略图的解决方案

    • 1.1 开发背景
    • 1.2 如何使用JavaCV?
      • 1.2.1 引入依赖
      • 1.2.2 编写工具类库
      • 1.2.3 测试调用
    • 1.3 利用阿里云OOS获取视频缩略图
  • 参考资料

1.1 开发背景

在Java后端开发中,当返回给前端或移动端视频列表的时候,客户端往往并不直接加载所有视频,而是先加载后端返回的视频缩略图列表。

然而这个视频缩略图列表从哪里来呢?总不能让上传视频的用户自己上传吧?

答案当然是不能, 我们Java后端其实是有办法解决这个问题的。

  • 一种方法是使用FFmpeg 视频定时截图工具,这种局限在必须部署在windows 服务器。

  • 另外一种是通过程序Java 代码编程方式使用JavaCV 类库实现。

那么什么是JavaCV 呢?

  • JavaCV是对各种常用计算机视觉库的封装后的一组jar包,其中封装了FFmpegOpenCV等计算机视觉编程人员常用库的接口,可以通过其中的Utility类方便的在包括Android在内的Java平台上调用这些接口。
  • 最开始Javacvgooglecode下面的一个项目,后来迁移到了github,因此JavaCV相关的包名也由com.googlecode.javacv改为org.bytedeco.javacv。目前最新版本是 1.3.

上面这段话也解开了我的一个疑惑。

因为我之前尝试maven 中心仓库搜索javacv 后发现有这三个类库,到底使用哪一种开始心存疑惑。
在这里插入图片描述
google java cv 那个版本太老了,也就是说我们如果使用javacv,直接使用java CV Platform 类库即可。至于为什么不用JavaCV 那个,其实我也找了一篇博文,但是试了下貌似需要缺少so 库,于是放弃了。

JavaCV目前最新版本是 1.5.3。项目地址:https://github.com/bytedeco/javacv

1.2 如何使用JavaCV?

1.2.1 引入依赖

      <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.3</version>
        </dependency>

查看最新版本

1.2.2 编写工具类库

编写工具类库SmartFileUtils.java

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * @author qing-feng.zhao
 */
public class SmartFileUtils {

    /**
     * * 截取视频第六帧的图片
     *
     * @param filePath 视频路径
     * @param dir      文件存放的根目录
     * @return 图片的相对路径 例:pic/1.png
     */
    public static String videoImage(String filePath, String dir) throws FrameGrabber.Exception {
        String pngPath = "";
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.setFormat("mp4");
        ff.start();
        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        while (i < ffLength) {
            f = ff.grabImage();
            //截取第6帧
            if ((i > 5) && (f.image != null)) {
                //生成图片的相对路径 例如:pic/uuid.png
                pngPath = getPngPath();
                //执行截图并放入指定位置
                doExecuteFrame(f, dir + pngPath);
                break;
            }
            i++;
        }
        ff.stop();

        return pngPath;
    }

    /**
     * 生成图片的相对路径
     *
     * @return 图片的相对路径 例:pic/1.png
     */
    private static String getPngPath() {
        return "pic/" + getUUID() + ".png";
    }


    /**
     * 生成唯一的uuid
     *
     * @return uuid
     */
    private static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }


    /**
     * 截取缩略图
     *
     * @param f                       Frame
     * @param targerFilePath:封面图片存放路径
     */
    private static void doExecuteFrame(Frame f, String targerFilePath) {
        String imagemat = "png";
        if (null == f || null == f.image) {
            return;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(f);
        File output = new File(targerFilePath);
        try {
            ImageIO.write(bi, imagemat, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

1.2.3 测试调用

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FrameGrabber;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

@Slf4j
class SmartFileUtilsTest {

    private String testPath;

    @BeforeEach
    void setUp() {
        testPath="/Users/zhaoqingfeng/Documents/temp/test.mp4";
        //testPath="https://v.qq.com/txp/iframe/player.html?vid=q0024wtk0v8";
    }

    @AfterEach
    void tearDown() {
    }

    @Test
    void videoImage() {
        
        try {
            String filePath=SmartFileUtils.videoImage(testPath,"/Users/zhaoqingfeng/Documents/temp/");
            log.info("{}",filePath);
        } catch (FrameGrabber.Exception e) {
            log.error("出错",e);
        }
    }
}

然后就可以看到/Users/zhaoqingfeng/Documents/temp/test.mp4 视频的缩略图已经存放到/Users/zhaoqingfeng/Documents/temp/pic/ 文件夹下了,图片名称命名我们使用了UUID.
在这里插入图片描述

PS:
如果出现错误,javacv-error-has-setformat-been-called 那么可能视频地址文件不对,请使用绝对路径。
另外,代码里不要少了这一行: ff.setFormat("mp4");
测试二在尝试获取腾讯视频地址的时候由于无法获取到视频真实文件地址,导致报错失败。

1.3 利用阿里云OOS获取视频缩略图

今天偶然发现的一个新操作,凡是存放在阿里云OOS上的视频,都可以很方便的获取视频缩略图。

操作示例如下:

比如这是阿里云OOS上一个视频:http://a-image-demo.oss-cn-qingdao.aliyuncs.com/demo.mp4

那么获取视频第一秒的png格式的缩略图缩略图就是:http://a-image-demo.oss-cn-qingdao.aliyuncs.com/demo.mp4?x-oss-process=video/snapshot,t_10000,m_fast,w_400,h_400,f_png

参数描述取值范围
t截图时间单位ms,[0,视频时长]
w截图宽度,如果指定为0则自动计算像素值:[0,视频宽度]
h截图高度,如果指定为0则自动计算,如果w和h都为0则输出为原视频宽高像素值:[0,视频高度]
m截图模式,不指定则为默认模式,根据时间精确截图,如果指定为fast则截取该时间点之前的最近的一个关键帧枚举值:fast
f输出图片格式枚举值:jpg、png

本篇完~

参考资料

  • JavaCV 学习(一):JavaCV 初体验
  • JAVA生成视频缩略图的两种方式
  • 用Java代码提取视频的缩略图的两种办法
  • javacv-error-has-setformat-been-called
  • https://github.com/bytedeco/javacv
  • 阿里云oss视频上传后,如何获取视频封面

最后

以上就是想人陪手套为你收集整理的Java提取视频中的指定桢数生成视频缩略图的解决方案参考资料的全部内容,希望文章能够帮你解决Java提取视频中的指定桢数生成视频缩略图的解决方案参考资料所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部