JavaCV如何实现读取视频信息及自动截取封面图(javacv,开发技术)

时间:2024-05-05 21:53:51 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    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());}}}

    这样我们就能快速的实现截图了。

    JavaCV如何实现读取视频信息及自动截取封面图

     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:JavaCV如何实现读取视频信息及自动截取封面图的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:flask-SQLALchemy连接数据库如何实现下一篇:

    7 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18