用户提交视频后,后端需要自动截张封面图,便于页面展示,以下方案是采用javacv,
效果还是可以的,只是依赖JAR包比较多,大约有35M,导致整个程序包比较大。
1、首先在build.gradle中增加以下内容:
dependencies {
//JavaCV
compile group: 'org.bytedeco', name: 'javacv', version: '1.5.1'
compile group: 'org.bytedeco', name: 'javacpp', version: '1.5.1'
// compile group: 'org.bytedeco', name: 'opencv', version: '4.1.0-1.5.1', classifier: 'windows-x86_64'
compile group: 'org.bytedeco', name: 'opencv', version: '4.1.0-1.5.1', classifier: 'linux-x86_64'
// compile group: 'org.bytedeco', name: 'openblas', version: '0.3.6-1.5.1', classifier: 'windows-x86_64'
compile group: 'org.bytedeco', name: 'openblas', version: '0.3.6-1.5.1', classifier: 'linux-x86_64'
// compile group: 'org.bytedeco', name: 'ffmpeg', version: '0.3.6-1.5.1', classifier: 'windows-x86_64'
compile group: 'org.bytedeco', name: 'ffmpeg', version: '0.3.6-1.5.1', classifier: 'linux-x86_64'
}
2、工具类
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 视频截封面图 工具类
* 这个方案的依赖JAR包比较多,大约有35M,导致整个程序包比较大。
* @version V1.0
* @date: 2021/7/2
*/
public class VideoImgUtil {
// 获取要取得的帧数
private static final int fifthFrame= 5;
/**
* 将视频的字节流截图
* @param
* @return
*/
public static InputStream getVideoImg(InputStream videofile ) {
System.setProperty("org.bytedeco.javacpp.maxphysicalbytes", "0");
System.setProperty("org.bytedeco.javacpp.maxbytes", "0");
FFmpegFrameGrabber grabber;
InputStream img = null ;
try {
grabber = new FFmpegFrameGrabber(videofile );
grabber.start();
// 视频总帧数
int videoLength = grabber.getLengthInFrames();
Frame frame = null;
int i = 0;
while (i < videoLength) {
// 过滤前5帧,因为前5帧可能是全黑的
frame = grabber.grabFrame();
if ((i > fifthFrame) && (frame.image != null)) {
break;
}
i++;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
// 绘制图片
BufferedImage bufferedImage = converter.getBufferedImage(frame);
img = bufferedImageToInputStream( bufferedImage );
grabber.stop();
grabber.close();
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
/**
* 将BufferedImage转换为InputStream
* @param image
* @return
*/
public static InputStream bufferedImageToInputStream(BufferedImage image){
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
}
return null;
}
}
3、调用方法
MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
MultipartFile file = mRequest.getFile(names.next());
//视频文件 需截封面图
if(fileExtName.toLowerCase().equals("mp4") ){
InputStream inStream = VideoImgUtil.getVideoImg( file.getInputStream() );
// 将InputStream写入本地文件
}