使用ffmpeg实现视频操作相关需求
一、依赖引入
为了解决依赖冲突问题,所以变成了如下很不美观的依赖引入,排除了一些本就不需要的,有依赖冲突的
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.6</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>tesseract</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.4-1.5.6</version>
<classifier>windows-x86_64</classifier>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.4-1.5.6</version>
<classifier>linux-x86_64</classifier>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
</exclusion>
</exclusions>
</dependency>
二、抽取视频中的第一帧作为封面图片
通过读取流的方式进行视频播放,并抽取第一帧存储图片
public FileUploadCompletedVo uploadVideoImage(String bucketName, String objectName, InputStream stream) {
// 创建FfmpegFrameGrabber对象
String imagePath = "";
int videoSecondLength = 0;
try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(stream)){
// 打开视频文件
grabber.start();
videoSecondLength = (int) grabber.getLengthInTime() / 1000000;
// 逐帧抓取视频
Frame frame;
if ((frame = grabber.grabImage()) != null) {
BufferedImage bufferedImage = frameToBufferedImage(frame);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, MediaType.IMAGE_JPEG.getSubtype(), outputStream);
InputStream input = new ByteArrayInputStream(outputStream.toByteArray());
imagePath = this.putObject(bucketName, objectName, input);
}
} catch (IOException e) {
log.error("Error occurred while grabbing frames: {}", e.getMessage());
}
return FileUploadCompletedVo.builder().videoImagePath(imagePath).videoLength(videoSecondLength).build();
}
/**
* 将Frame转换为BufferedImage
*/
private static BufferedImage frameToBufferedImage(Frame frame) {
Java2DFrameConverter converter = new Java2DFrameConverter();
return converter.getBufferedImage(frame);
}
/**
* 通过InputStream上传对象
*
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param stream 文件流
* @return url
*/
@SneakyThrows(value = {ErrorResponseException.class, InsufficientDataException.class, InternalException.class, InvalidKeyException.class, InvalidResponseException.class,
IOException.class, NoSuchAlgorithmException.class, ServerException.class, XmlParserException.class})
public String putObject(String bucketName, String objectName, InputStream stream) {
try {
super.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).build()).get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
super.throwEncapsulatedException(e);
return null;
}
return this.getUrl(bucketName, objectName);
}