Java整合ffmpeg视频处理的正确使用方式

相信不少做app开发的同事,都遇到一种需求,要做视频的轮播图,这时候我们没办法或者不好直接将视频作为轮播,所以通常的解决方案是获取到视频的第一帧图像作为首图,使用该首图作为轮播。实现首图获取无非就是前端获取或者后端获取后传给前端。在使用uniapp作为前端基础开发app应用时,限于组件的约束,要实现视频第一帧的获取是比较麻烦的,所以我们通常可以选择后端进行获取。

一、网上提供的方案

我使用的语言是java,初次接触这个问题,大家都会去搜索网上是如何实现的,在参考大量文章之后,我们发现,大部分文章提供的都是如下的方式:

引入依赖:

实现代码:

启动执行main方法,在指定的文件夹汇总,惊喜的发现我们成功得到了第一帧的图片。

于是信心满满的部署到了服务器上(作者环境是docker),结果发现问题并没有我们想象的如此简单,我们得到了下面的错误:

那怎么解决呢?我们在容器当中安装对应的组件就行吗?带着疑问进行尝试;因为javacv图像处理的核心还是使用的ffmpeg这个工具组件,所以我们不妨在doker当中安装一下,看看能否解决问题。基于我们的环境可以查看当前linux中是否带有这个组件,我以Alpine Linux为例,通过下面的命令进行查找和安装:

shell 复制代码
# 查找系统是否有ffmpeg
apk search ffmpeg

# 安装(如果有的话)
apk add ffmpeg

安装成功后,我们再次尝试在获取第一帧图片的功能,于是惊奇的发现又报了其他我的错误:

不能进行初始化,就是下面这行代码:

java 复制代码
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);

这是怎么回事呢?其实我也不知道,于是又开始不停的在网上搜索相关的内容,得到的结果大概有两种方式:

  • 替换pom引用,我的javacv版本较低,于是乎就开始像无头苍蝇一样的替换各种依赖,调整各种实现代码,结果无一例外的,在windows好使,docker中仍然是一样的效果。即使咱们针对不同的错误去处理,你会发现像无底洞一样,不同的错误会一一出现在你的眼前,最终还是不能再linux使用。
  • 于是乎我们不得不怀疑是不是我们的环境有问题,所以在有些文章里会提到,是不是我们可以尝试更换下jdk等,比如更换成openjdk等。

由于我开始尝试了第一种方式,没达到效果,也不想去尝试更换openjdk了,毕竟结果似乎也没有被人验证。所以我不得不转换一下自己的思路。

二、使用cmd调用ffmpeg

经过前面的踩坑过程,我能确定的是,我们可以使用ffmpeg去获取第一帧,不过要转换下自己的思路,首先需要简单了解下ffmpeg是什么。

ffmpeg官网

ffmpeg是一个完整的跨平台解决方案,用于录制、转换和流式传输音频和视频。

2.1 安装

windows安装

在官网下载对应的安装包:

如上下载完成后解压到本地,同时去配置对应的环境变量:

此时就可以进行验证了,查看版本:

cmd 复制代码
C:\Users\86133>ffmpeg -version
ffmpeg version N-111780-g7098bec73b-20230817 Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 13.1.0 (crosstool-NG 1.25.0.196_227d99d)
configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --enable-shared --disable-static --disable-w32threads --enable-pthreads --enable-iconv --enable-libxml2 --enable-zlib --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-libvorbis --enable-opencl --disable-libpulse --enable-libvmaf --disable-libxcb --disable-xlib --enable-amf --enable-libaom --enable-libaribb24 --enable-avisynth --enable-chromaprint --enable-libdav1d --enable-libdavs2 --disable-libfdk-aac --enable-ffnvcodec --enable-cuda-llvm --enable-frei0r --enable-libgme --enable-libkvazaar --enable-libass --enable-libbluray --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librist --enable-libssh --enable-libtheora --enable-libvpx --enable-libwebp --enable-lv2 --enable-libvpl --enable-openal --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopenmpt --enable-librav1e --enable-librubberband --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libsvtav1 --enable-libtwolame --enable-libuavs3d --disable-libdrm --disable-vaapi --enable-libvidstab --enable-vulkan --enable-libshaderc --enable-libplacebo --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libzimg --enable-libzvbi --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-ldexeflags= --extra-libs=-lgomp --extra-version=20230817
libavutil      58. 16.101 / 58. 16.101
libavcodec     60. 23.100 / 60. 23.100
libavformat    60. 10.100 / 60. 10.100
libavdevice    60.  2.101 / 60.  2.101
libavfilter     9. 11.100 /  9. 11.100
libswscale      7.  3.100 /  7.  3.100
libswresample   4. 11.100 /  4. 11.100
libpostproc    57.  2.100 / 57.  2.100

将mp4文件转换成avi文件:

cmd 复制代码
C:\Users\86133>ffmpeg -i C:\Users\86133\Desktop\视频\1.mp4 C:\Users\86133\Desktop\视频\2.avi

下面办我们的正事儿,获取视频的第一帧图片:

cmd 复制代码
ffmpeg -i C:\Users\86133\Desktop\视频\1.mp4 -ss 00:00:01 -vframes 1 -y C:\Users\86133\Desktop\视频\2.jpg

linux安装

linux安装比较简单了,像我前面提到过:

  • 在Alpine Linux当中,基础组件里面就会有对应的安装包,只要使用如下方式安装即可:

    shell 复制代码
    # 查找系统是否有ffmpeg
    apk search ffmpeg
    
    # 安装(如果有的话)
    apk add ffmpeg
  • 如果是centos可以在线使用yum安装,例如,安装过程可能遇到问题,可以参考下面的文章: linux.xiaosiseo.com/post/8523.h...

  • 也可以像windos一样,下载安装包,上传到服务器,同时需要配置环境变量等,相对要比windows复杂,可以参考下面的文章: blog.csdn.net/weixin_4469...

安装完成后一样可以通过查看版本验证是否安装成功:

shell 复制代码
/ # ffmpeg -version
ffmpeg version 3.4.6 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 6.4.0 (Alpine 6.4.0)
configuration: --prefix=/usr --enable-avresample --enable-avfilter --enable-gnutls --enable-gpl --enable-libass --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libxvid --enable-libx264 --enable-libx265 --enable-libtheora --enable-libv4l2 --enable-postproc --enable-pic --enable-pthreads --enable-shared --enable-libxcb --disable-stripping --disable-static --disable-librtmp --enable-vaapi --enable-vdpau --enable-libopus --disable-debug
libavutil      55. 78.100 / 55. 78.100
libavcodec     57.107.100 / 57.107.100
libavformat    57. 83.100 / 57. 83.100
libavdevice    57. 10.100 / 57. 10.100
libavfilter     6.107.100 /  6.107.100
libavresample   3.  7.  0 /  3.  7.  0
libswscale      4.  8.100 /  4.  8.100
libswresample   2.  9.100 /  2.  9.100
libpostproc    54.  7.100 / 54.  7.100

2.2 Java调用

我们就使用前面提到的命令,实现我们第一帧图片的获取,不过对应的地址要更换成服务器的路径:

java 复制代码
/**
 * 获取指定视频的帧并保存为图片至指定目录
 *
 * @param sourcePath 源视频文件路径
 * @param targetPath 截取帧的图片存放路径
 * @throws Exception
 */
public static void fetchFrame(String sourcePath, String targetPath)
        throws Exception {
    // 使用 ffmpeg 获取视频封面
    String cmd = "ffmpeg -i " + sourcePath + " -ss 00:00:01 -vframes 1 -y -loglevel quiet " + targetPath;
    Process process = Runtime.getRuntime().exec(cmd);
    try {
        process.waitFor();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

如果在执行代码时发现程序卡在这一行:

java 复制代码
process.waitFor();

请注意的你的ffmpeg命令中是否有参数:quiet,该参数能够让程序静默工作,不输出版本、工作信息。

三、小结

到此为止,已经将java整合ffmpeg实现视频处理的内容给大家做了简单的扫盲。包括在windows和linux当中的安装和使用方式。文章开篇也包含我在使用中遇到的问题,希望大家不要再走重复的路,直接使用命令的方式调用即可。ffmpeg的功能非常强大,大家可以在自己需要的场景进行使用,但是切记不要做违法乱纪的事哦~~

相关推荐
cwj&xyp4 分钟前
Python(二)str、list、tuple、dict、set
前端·python·算法
dlnu20152506226 分钟前
ssr实现方案
前端·javascript·ssr
古木201911 分钟前
前端面试宝典
前端·面试·职场和发展
啦啦右一1 小时前
Spring Boot | (一)Spring开发环境构建
spring boot·后端·spring
森屿Serien1 小时前
Spring Boot常用注解
java·spring boot·后端
轻口味2 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王2 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发2 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀3 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js