Java 截取視頻資料中的某一幀作為縮略圖
最近項(xiàng)目中有一個(gè)需求,就是要實(shí)現(xiàn)視頻資料的收藏功能,當(dāng)時(shí)想了想,收藏記錄實(shí)現(xiàn)并不是很難,但是想展現(xiàn)出視頻的縮略圖,就要想想其他辦法了,所以就想到了截取視頻資料中的某一幀作為縮略圖,我沒有選擇截取第一幀,選擇的是第五幀,因?yàn)榈谝粠赡軟]有內(nèi)容。
基礎(chǔ)知識(shí)
JavaCV:功能很強(qiáng)大,封裝了很多很視頻、圖片相關(guān)的內(nèi)容。
JavaCV 是一款基于JavaCPP
調(diào)用方式(JNI的一層封裝),由多種開源計(jì)算機(jī)視覺庫組成的包裝庫,封裝了包含F(xiàn)Fmpeg、OpenCV、tensorflow、caffe、tesseract、libdc1394、OpenKinect、videoInput和ARToolKitPlus等在內(nèi)的計(jì)算機(jī)視覺領(lǐng)域的常用庫和實(shí)用程序類。
JavaCV基于Apache License Version 2.0協(xié)議和GPLv2兩種協(xié)議 ,
JavaCV支持Windows、Linux、MacOS,Android、IOS在內(nèi)的Java平臺(tái)上調(diào)用這些接口。
FFmpegFrameGrabber
FFmpegFrameGrabber可以理解為解碼器,也可以理解為幀收集器,可以獲取視頻資料的各種詳細(xì)信息,時(shí)長,寬高,幀等,很強(qiáng)大。
BufferedImage,ImageIO
BufferedImage類是Image的一個(gè)子類,是一個(gè)帶緩沖區(qū)圖像類,主要作用是將一幅圖片加載到內(nèi)存中。
ImageIO提供read()和write()靜態(tài)方法,讀寫照片
將圖片加載到內(nèi)存中
//需要是一個(gè)本地文件 String imgPath = "C:\Users\Administrator\Videos\999.jpg"; BufferedImage image = ImageIO.read(new FileInputStream(imgPath));
將內(nèi)存中的圖片寫到本地
BufferedImage bi=~某個(gè)值 File outputfile = new File("save.png"); //參數(shù) // bi:要寫入的RenderedImage // png:格式類型 // outputfile:要寫入的OutputStream ImageIO.write(bi,"png",outputfile);
MultipartFile
MultipartFile在上一篇文章中介紹過了。
具體實(shí)現(xiàn)
引入依賴
本功能使用的Jar包是javacv,javacv-platform。因?yàn)檫@個(gè)包有150多M,很多依賴項(xiàng)都用不到,所以,將不需要的移除取出。
<!--start:視頻獲取某一幀的圖片--> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.4</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.4</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus-platform</artifactId> </exclusion> </exclusions> </dependency> <!--end:視頻獲取某一幀的圖片-->
Java代碼
/** * 將視頻文件幀處理并以“jpg”格式進(jìn)行存儲(chǔ)。 * 依賴FrameToBufferedImage方法:將frame轉(zhuǎn)換為bufferedImage對(duì)象 * 參數(shù)可串本地文件,或者網(wǎng)絡(luò)文件 * @param videoFileName http://d-godone.dmsd.tech/goDone/M00/00/0A/wKg8O2D2mnqEMg7wAAAAALbl5Ys275.mp4 */ public String videoFramer(String videoFileName){ //最后獲取到的視頻的圖片的路徑 String videPicture=""; //Frame對(duì)象 Frame frame = null; //標(biāo)識(shí) int flag = 0; try { /* 獲取視頻文件 */ FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber( videoFileName); log.info("開始截取視頻:"); // av_register_all();//解決報(bào)錯(cuò) avformat_open_input() error -138: Could not open input // avcodec_register_all(); // 當(dāng)視頻打不開時(shí),會(huì)報(bào)錯(cuò) fFmpegFrameGrabber.start(); //獲取視頻總幀數(shù) int ftp = fFmpegFrameGrabber.getLengthInFrames(); log.info("時(shí)長 " + ftp / fFmpegFrameGrabber.getFrameRate() / 60); while (flag <= ftp) { //獲得每一幀 frame = fFmpegFrameGrabber.grabImage(); /* 對(duì)視頻的第五幀進(jìn)行處理 */ if (frame != null && flag==5) { //將文件轉(zhuǎn)換 BufferedImage bufferedImage = FrameToBufferedImage(frame); //將bufferedImage轉(zhuǎn)換成MultipartFile--方便文件上傳 MultipartFile multipartFile = fileCase(bufferedImage); log.info("開始文件上傳:"); //文件上傳--上傳到FastDFS中,并返回URL String fileLoad = fileLoad(multipartFile); videPicture=fileLoad; log.info("文件上傳成功{}",fileLoad); break; } flag++; } fFmpegFrameGrabber.stop(); fFmpegFrameGrabber.close(); } catch (Exception E) { E.printStackTrace(); } return videPicture; }
兩個(gè)文件類型轉(zhuǎn)換的方法Frame->BufferedImage->MultipartFile
/** * 文件轉(zhuǎn)換,將Frame轉(zhuǎn)換成BufferedImage * @param frame Frame * @return */ public static BufferedImage FrameToBufferedImage(Frame frame) { //創(chuàng)建BufferedImage對(duì)象 Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bufferedImage = converter.getBufferedImage(frame); return bufferedImage; } /** * 文件轉(zhuǎn)換將BufferedImage轉(zhuǎn)換成MultipartFile:為了文件上傳 * @param image * @return */ public static MultipartFile fileCase(BufferedImage image){ //得到BufferedImage對(duì)象 // BufferedImage bufferedImage = JoinTwoImage.testEncode(200, 200, url); MultipartFile multipartFile= null; try { //創(chuàng)建一個(gè)ByteArrayOutputStream ByteArrayOutputStream os = new ByteArrayOutputStream(); //把BufferedImage寫入ByteArrayOutputStream ImageIO.write(image, "jpg", os); //ByteArrayOutputStream轉(zhuǎn)成InputStream InputStream input = new ByteArrayInputStream(os.toByteArray()); //InputStream轉(zhuǎn)成MultipartFile multipartFile =new MockMultipartFile("file", "file.jpg", "text/plain", input); } catch (IOException e) { e.printStackTrace(); } return multipartFile; }
到此這篇關(guān)于Java 截取視頻資料中的某一幀作為縮略圖的文章就介紹到這了,更多相關(guān)Java 視頻縮略圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring對(duì)靜態(tài)變量無法注入的解決方案
這篇文章主要介紹了使用Spring對(duì)靜態(tài)變量無法注入的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-07-07Java?Spring框架創(chuàng)建項(xiàng)目與Bean的存儲(chǔ)與讀取詳解
本篇文章將介紹Spring項(xiàng)目的創(chuàng)建,IDEA國內(nèi)源的配置以及Bean的存儲(chǔ)與讀取,所謂的Bean其實(shí)就是對(duì)象的意思,更詳細(xì)地說Spring Bean是被實(shí)例的,組裝的及被Spring 容器管理的Java對(duì)象2022-07-07JavaWeb購物車項(xiàng)目開發(fā)實(shí)戰(zhàn)指南
之前沒有接觸過購物車的東東,也不知道購物車應(yīng)該怎么做,所以在查詢了很多資料,總結(jié)一下購物車的功能實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于JavaWeb購物車項(xiàng)目開發(fā)的相關(guān)資料,需要的朋友可以參考下2022-06-06Spring JPA聯(lián)表查詢之OneToOne源碼詳解
這篇文章主要為大家介紹了Spring JPA聯(lián)表查詢之OneToOne源碼詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04springboot集成sensitive-word實(shí)現(xiàn)敏感詞過濾的兩種方案
敏感詞過濾通常是指從文本中檢測并移除或替換掉被認(rèn)為是不適當(dāng)、冒犯性或違反特定社區(qū)準(zhǔn)則的詞匯,這篇文章主要介紹了springboot集成sensitive-word實(shí)現(xiàn)敏感詞過濾,需要的朋友可以參考下2024-08-08全面匯總SpringBoot和SpringClould常用注解
Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說明、配置的功能,這篇文章就帶你來了解一下2021-08-08