uploadVideo

This commit is contained in:
2025-11-21 16:24:07 +08:00
parent b18ab98feb
commit 1e9e815314
5 changed files with 139 additions and 29 deletions

View File

@ -48,52 +48,82 @@ public class VideoProcessUtil {
return bytesToHexList(binaryData);
}
/**
* 从视频中提取帧
*
* @param videoFile 视频文件对象
* @param frameRate 每秒提取的帧数(帧率)
* @param duration 需要提取的视频时长(秒)
* @param width 提取帧的宽度
* @param height 提取帧的高度
* @return 提取的帧图像列表
* @throws Exception 如果在提取过程中发生错误
*/
private List<BufferedImage> extractFramesFromVideo(File videoFile, int frameRate, int duration, int width, int height) throws Exception {
// 初始化帧列表
List<BufferedImage> frames = new ArrayList<>();
// 计算需要提取的总帧数 = 帧率 × 时长
int totalFramesToExtract = frameRate * duration;
// 使用FFmpegFrameGrabber从视频文件中抓取帧
try (FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(videoFile)) {
// 启动抓取器
grabber.start();
// 获取视频总帧数
long totalFramesInVideo = grabber.getLengthInFrames();
// 获取视频帧率如果获取不到则默认为30fps
int fps = (int) Math.round(grabber.getFrameRate());
if (fps <= 0) fps = 30;
// 计算视频总时长(秒)
double durationSeconds = (double) totalFramesInVideo / fps;
// 检查视频时长是否满足要求
if (durationSeconds < duration) {
throw new IllegalArgumentException("视频太短,至少需要 " + duration + "");
}
// 计算帧间隔,用于均匀分布提取的帧
double frameInterval = (double) totalFramesInVideo / totalFramesToExtract;
// 循环提取指定数量的帧
for (int i = 0; i < totalFramesToExtract; i++) {
// 计算目标帧号
int targetFrameNumber = (int) Math.round(i * frameInterval);
// 检查目标帧号是否超出视频范围
if (targetFrameNumber >= totalFramesInVideo) {
throw new IllegalArgumentException("目标帧超出范围: " + targetFrameNumber);
}
// 设置抓取器到目标帧
grabber.setFrameNumber(targetFrameNumber);
// 抓取当前帧
Frame frame = grabber.grab();
// 如果成功抓取到帧且帧图像不为空
if (frame != null && frame.image != null) {
// 将帧转换为BufferedImage并裁剪到指定尺寸
BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(frame);
frames.add(cropImage(bufferedImage, width, height));
} else {
// 如果无法获取帧则抛出异常
throw new IllegalArgumentException("无法获取第 " + targetFrameNumber + "");
}
}
// 停止抓取器
grabber.stop();
}
// 记录提取的帧数
log.debug("从视频中提取了 {} 帧", frames.size());
// 返回提取的帧列表
return frames;
}
/**
* 将所有帧转换为 RGB565 格式字节数组
*/