JavaCV如何实现读取视频信息及自动截取封面图
导读:本文共3361.5字符,通常情况下阅读需要11分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: javacv 介绍javacv可以帮助我们在java中很方便的使用 OpenCV 以及 FFmpeg 相关的功能接口项目地址引入 javacv<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId... ...
目录
(为您整理了一些要点),点击可以直达。javacv 介绍
javacv可以帮助我们在java中很方便的使用 OpenCV 以及 FFmpeg 相关的功能接口
项目地址
引入 javacv
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>${javacv.version}</version></dependency>
读取视频信息
创建 VideoInfo 类
packagecom.buguagaoshu.porntube.vo;importcom.fasterxml.jackson.databind.ObjectMapper;importlombok.Getter;importlombok.Setter;/***@authorPuZhiwei{@literalpuzhiweipuzhiwei@foxmail.com}*create2022-06-0619:15*/@Getter@SetterpublicclassVideoInfo{/***总帧数**/privateintlengthInFrames;/***帧率**/privatedoubleframeRate;/***时长**/privatedoubleduration;/***视频编码*/privateStringvideoCode;/***音频编码*/privateStringaudioCode;privateintwidth;privateintheight;privateintaudioChannel;privateStringmd5;/***音频采样率*/privateIntegersampleRate;publicStringtoJson(){try{ObjectMapperobjectMapper=newObjectMapper();returnobjectMapper.writeValueAsString(this);}catch(Exceptione){return"";}}}
使用 FFmpegFrameGrabber 读取视频信息
publicstaticVideoInfogetVideoInfo(Filefile){VideoInfovideoInfo=newVideoInfo();FFmpegFrameGrabbergrabber=null;try{grabber=newFFmpegFrameGrabber(file);//启动FFmpeggrabber.start();//读取视频帧数videoInfo.setLengthInFrames(grabber.getLengthInVideoFrames()); //读取视频帧率videoInfo.setFrameRate(grabber.getVideoFrameRate());//读取视频秒数videoInfo.setDuration(grabber.getLengthInTime()/1000000.00);//读取视频宽度videoInfo.setWidth(grabber.getImageWidth());//读取视频高度videoInfo.setHeight(grabber.getImageHeight());videoInfo.setAudioChannel(grabber.getAudioChannels());videoInfo.setVideoCode(grabber.getVideoCodecName());videoInfo.setAudioCode(grabber.getAudioCodecName());//Stringmd5=MD5Util.getMD5ByInputStream(newFileInputStream(file));videoInfo.setSampleRate(grabber.getSampleRate());returnvideoInfo;}catch(Exceptione){e.printStackTrace();returnnull;}finally{try{if(grabber!=null){//此处代码非常重要,如果没有,可能造成FFmpeg无法关闭grabber.stop();grabber.release();}}catch(FFmpegFrameGrabber.Exceptione){log.error("getVideoInfograbber.releasefailed获取文件信息失败:{}",e.getMessage());}}}
截图
读取信息没有什么难度,但是在对视频截图的过程中,出现了一些问题,在我查找截图实现的代码时,大多数的代码都是这么写的
/***获取视频缩略图*@paramfilePath:视频路径*@parammod:视频长度/mod获取第几帧*@throwsException*/publicstaticStringrandomGrabberFFmpegImage(StringfilePath,intmod){StringtargetFilePath="";try{FFmpegFrameGrabberff=FFmpegFrameGrabber.createDefault(filePath);ff.start();//图片位置是否正确Stringrotate=ff.getVideoMetadata(ROTATE);//获取帧数intffLength=ff.getLengthInFrames();Framef;inti=0;//设置截取帧数intindex=ffLength/mod;while(i<ffLength){f=ff.grabImage();if(i==index){if(null!=rotate&&rotate.length()>1){OpenCVFrameConverter.ToIplImageconverter=newOpenCVFrameConverter.ToIplImage();IplImagesrc=converter.convert(f);f=converter.convert(rotate(src,Integer.parseInt(rotate)));}targetFilePath=getImagePath(filePath,i);doExecuteFrame(f,targetFilePath);break;}i++;}ff.stop();}catch(Exceptione){log.error("获取视频缩略图异常:"+e.getMessage());}returntargetFilePath;}
这样写本身没有什么问题,但是在获取需要截取帧数的部分,使用的是通过循环来一帧一帧的判断,这样在视频较短的时候没有什么问题,但是如果视频较长,就会出现严重的性能问题。
while(i<ffLength){f=ff.grabImage();if(i==index){ ......break;}i++;}
FFmpeg 的命令行参数有一个-ss
的参数,使用-ss
可以快速的帮助我们跳到视频的指定位置,完成操作,不用一帧一帧的判断。
所以现在的问题就是如何在 javacv 中实现-ss
参数
我在 javacv 的 GitHub Issues 中发现了这个操作,即使用setTimestamp()
方法,使用setTimestamp()
方法可以使 FFmpeg 跳转到指定时间,完成截图,于是,最后的截图代码就变成了这样
/***随机获取视频截图*@paramvideFile视频文件*@paramcount输出截图数量*@return截图列表**/publicstaticList<FileTableEntity>randomGrabberFFmpegImage(FilevideFile,intcount,longuserId){FFmpegFrameGrabbergrabber=null;Stringpath=FileTypeEnum.filePath();try{List<FileTableEntity>images=newArrayList<>(count);grabber=newFFmpegFrameGrabber(videFile);grabber.start();//获取视频总帧数//intlengthInVideoFrames=grabber.getLengthInVideoFrames();//获取视频时长,/1000000将单位转换为秒longdelayedTime=grabber.getLengthInTime()/1000000;Randomrandom=newRandom();for(inti=0;i<count;i++){//跳转到响应时间grabber.setTimestamp((random.nextInt((int)delayedTime-1)+1)*1000000L);Framef=grabber.grabImage();Java2DFrameConverterconverter=newJava2DFrameConverter();BufferedImagebi=converter.getBufferedImage(f);StringimageName=FileTypeEnum.newFilename(SUFFIX);Fileout=Paths.get(path,imageName).toFile();ImageIO.write(bi,"jpg",out);FileTableEntityfileTable=FileUtils.createFileTableEntity(imageName,SUFFIX,path,f.image.length,"系统生成截图",userId,FileTypeEnum.VIDEO_PHOTO.getCode());images.add(fileTable);}returnimages;}catch(Exceptione){returnnull;}finally{try{if(grabber!=null){grabber.stop();grabber.release();}}catch(FFmpegFrameGrabber.Exceptione){log.error("getVideoInfograbber.releasefailed获取文件信息失败:{}",e.getMessage());}}}
这样我们就能快速的实现截图了。
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
JavaCV如何实现读取视频信息及自动截取封面图的详细内容,希望对您有所帮助,信息来源于网络。