@[TOC](javaCV 视频工具—截取视频缩略图、获取视频属性)
通过javaCV 视频工具—截取视频缩略图、获取视频属性
<!--javaCV 视频工具--> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5</version> </dependency>
@Slf4j public class VideoUtils { private static final String IMAGEMAT = "png"; private static final String ROTATE = "rotate"; /** * 默认截取视频的中间帧为封面 */ public static final int MOD = 2; /** * 视频缩略图后缀 */ private static final String VIDEO_THUMBNAIL_SUF = "th.png"; /** * 视频缩略图前缀 */ private static final String VIDEO_THUMBNAIL_PRE = "video/thumbnail/"; private static final String SYMBOL = "."; /** * 获取视频缩略图 * @param filePath:视频路径 * @param mod:视频长度/mod获取第几帧 * @throws Exception */ public static String randomGrabberFFmpegImage(String filePath, int mod) { String targetFilePath = ""; try{ FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath); ff.start(); //图片位置是否正确 String rotate = ff.getVideoMetadata(ROTATE); //获取帧数 int ffLength = ff.getLengthInFrames(); Frame f; int i = 0; //设置截取帧数 int index = ffLength / mod; while (i < ffLength) { f = ff.grabImage(); if(i == index){ if (null != rotate && rotate.length() > 1) { OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); IplImage src = converter.convert(f); f = converter.convert(rotate(src, Integer.parseInt(rotate))); } targetFilePath = getImagePath(filePath, i); doExecuteFrame(f, targetFilePath); break; } i++; } ff.stop(); }catch (Exception e){ log.error("获取视频缩略图异常:" + e.getMessage()); } return targetFilePath; } /** * 随机生成生成缩略图存放路径 * @param filePath:视频路径 * @param index:第几帧 * @return:缩略图的存放路径 */ private static String getImagePath(String filePath, int index){ String fileName = FileUtils.getName(filePath); //去后缀 fileName = fileName.substring(0, fileName.indexOf(SYMBOL)); return TencentCosConfig.baseUrl + VIDEO_THUMBNAIL_PRE + DateUtils.datePath() + "/" + fileName + "_" + index + VIDEO_THUMBNAIL_SUF; } /** * 旋转图片 * @param src * @param angle * @return */ public static IplImage rotate(IplImage src, int angle) { IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels()); opencv_core.cvTranspose(src, img); opencv_core.cvFlip(img, img, angle); return img; } /** * 截取缩略图 * @param f * @param targerFilePath:封面图片 */ public static void doExecuteFrame(Frame f, String targerFilePath) { COSClient cosClient = TencentCosUtils.initCosClient(); if (null == f || null == f.image) { return; } Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bi = converter.getBufferedImage(f); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(bi, IMAGEMAT, out); // 获取文件流 InputStream bufferedImage = new ByteArrayInputStream(out.toByteArray()); int length = out.size(); ObjectMetadata objectMetadata = new ObjectMetadata(); // 从输入流上传必须制定content length, 否则http客户端可能会缓存所有数据,存在内存OOM的情况 objectMetadata.setContentLength(length); // 默认下载时根据cos路径key的后缀返回响应的contenttype, 上传时设置contenttype会覆盖默认值 PutObjectRequest putObjectRequest = new PutObjectRequest(TencentCosConfig.bucket, targerFilePath, bufferedImage, objectMetadata); PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest); log.info("腾讯COS上传视频缩略图成功:{}", putObjectResult.getETag()); //关闭输入输出流 bufferedImage.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } finally { cosClient.shutdown(); } } /** * 根据视频长度随机生成随机数集合 * @param baseNum:基础数字,此处为视频长度 * @param length:随机数集合长度 * @return:随机数集合 */ public static List<Integer> random(int baseNum, int length) { List<Integer> list = new ArrayList<Integer>(length); while (list.size() < length) { Integer next = (int) (Math.random() * baseNum); if (list.contains(next)) { continue; } list.add(next); } Collections.sort(list); return list; } /** * 获取视频时长 单位/秒 * @param video * @return */ public static long getVideoDuration(File video) { long duration = 0L; FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video); try { ff.start(); duration = ff.getLengthInTime() / (1000 * 1000); ff.stop(); } catch (FrameGrabber.Exception e) { e.printStackTrace(); } return duration; } /** * 获取视频时长 单位/秒 * @param inputStream 输入流 * @return */ public static long getVideoDuration(InputStream inputStream) { long duration = 0L; FFmpegFrameGrabber ff = new FFmpegFrameGrabber(inputStream); try { ff.start(); duration = ff.getLengthInTime() / (1000 * 1000); ff.stop(); } catch (FrameGrabber.Exception e) { e.printStackTrace(); } return duration; } /** * 转换视频文件为mp4 * @param file * @return */ public static String convertToMp4(File file) { FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file); String fileName = null; Frame captured_frame = null; FFmpegFrameRecorder recorder = null; try { frameGrabber.start(); fileName = file.getAbsolutePath() + "__.mp4"; recorder = new FFmpegFrameRecorder(fileName, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels()); recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //avcodec.AV_CODEC_ID_H264 //AV_CODEC_ID_MPEG4 recorder.setFormat("mp4"); recorder.setFrameRate(frameGrabber.getFrameRate()); //recorder.setSampleFormat(frameGrabber.getSampleFormat()); // recorder.setSampleRate(frameGrabber.getSampleRate()); recorder.setAudioChannels(frameGrabber.getAudioChannels()); recorder.setFrameRate(frameGrabber.getFrameRate()); recorder.start(); while ((captured_frame = frameGrabber.grabFrame()) != null) { try { recorder.setTimestamp(frameGrabber.getTimestamp()); recorder.record(captured_frame); } catch (FrameRecorder.Exception e) { e.printStackTrace(); } } recorder.stop(); recorder.release(); frameGrabber.stop(); } catch (Exception | FrameRecorder.Exception e) { e.printStackTrace(); } return fileName; } }