获取视频帧图片
在实现了minio文件上传的基础上进行操作
一、编写pom
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId>
<version>0.2.5</version>
</dependency>
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec-javase</artifactId>
<version>0.2.5</version>
</dependency>
二、新增创建FileItem的方法
@Slf4j
public class FileUtil {
// 默认文件名
private static final String defaultFilename = "file";
public static FileItem createFileItem(InputStream inputStream) {
final String filename = defaultFilename + "." + MediaType.IMAGE_JPEG.getSubtype();
FileItemFactory factory = new DiskFileItemFactory(16, null);
FileItem item = factory.createItem(filename, MediaType.MULTIPART_FORM_DATA_VALUE, true, filename);
try(OutputStream os = item.getOutputStream()) {
IOUtils.copy(inputStream, os);
} catch (IOException e) {
log.error("create fileItem stream copy occurred exception", e);
throw new VideoFrameException(VideoFrameExceptionTypes.FILE_CREATE_FAILED);
}
return item;
}
}
三、视频工具类获取帧
@Slf4j
public class VideoUtil {
private static final List<String> videoSuffix = Arrays.asList(
"avi", "wmv", "mov", "mpg", "mpeg", "rm", "ram", "flv", "swf", "mp4"
);
public static MultipartFile getFirstFrame(MultipartFile videoFile) {
return getFrame(videoFile, 1);
}
public static MultipartFile getFrame(MultipartFile multipartFile, int frameNumber) {
String originalFilename = multipartFile.getOriginalFilename();
if (StringUtils.isBlank(originalFilename) || !originalFilename.contains(".")) {
throw new VideoFrameException(VideoFrameExceptionTypes.NOT_SUPPORTED_FILE_TYPE);
}
String[] filenameSplit = originalFilename.split("\\.");
if (!videoSuffix.contains(filenameSplit[filenameSplit.length - 1])) {
throw new VideoFrameException(VideoFrameExceptionTypes.NOT_SUPPORTED_FILE_TYPE);
}
CommonsMultipartFile cf = (CommonsMultipartFile) multipartFile;
DiskFileItem fi = (DiskFileItem) cf.getFileItem();
File file = fi.getStoreLocation();
MultipartFile videoCover = null;
try {
Picture pic = FrameGrab.getFrameFromFile(file, frameNumber);
BufferedImage bi = AWTUtil.toBufferedImage(pic);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, MediaType.IMAGE_JPEG.getSubtype(), baos);
InputStream input = new ByteArrayInputStream(baos.toByteArray());
FileItem fileItem = FileUtil.createFileItem(input);
videoCover = new CommonsMultipartFile(fileItem);
} catch (IOException | JCodecException e) {
log.error("获取视频帧出现异常", e);
throw new VideoFrameException(VideoFrameExceptionTypes.GET_VIDEO_FRAME_FAILED);
}
return videoCover;
}
}
四、编写Controller进行测试
@Slf4j
@RequestMapping("video")
@RestController
public class VideoController {
@Resource
private MinioService minioService;
// 上传视频
@PostMapping("/uploadVideo")
public String uploadVideo(MultipartFile file) {
String filename = minioService.upload(file);
log.info("视频 {} 上传成功!", filename);
MultipartFile firstFrame = VideoUtil.getFirstFrame(file);
String firstFrameFilename = minioService.upload(firstFrame);
log.info("封面 {} 上传成功!", firstFrameFilename);
return filename;
}
}
### 上传
POST http://127.0.0.1:8888/video/uploadVideo
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="file"; filename="Grant_Gustin_share.mp4"
< /Users/wangfeihu/IdeaProjects/video-frame/src/main/resources/video/Grant_Gustin_share.mp4
--WebAppBoundary--
获取并上传视频首帧成功!
代码仓库: video-frame-demo