Java獲取視頻時(shí)長(zhǎng)和封面截圖
java視頻時(shí)長(zhǎng)的計(jì)算以及視頻封面圖截取
本人使用的maven進(jìn)行下載對(duì)應(yīng)的jar包,其中代碼適用window環(huán)境和linux環(huán)境,親自測(cè)過(guò),沒(méi)問(wèn)題。
maven需要用到的groupId和artifactId以及版本,如下所示:
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> <version>3.4.1-1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>3.4.2-1.4.1</version> </dependency>
java代碼
import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; /** * 視頻工具 * @author * */ public class VideoUtil { /** * 獲取指定視頻的幀并保存為圖片至指定目錄 * @param file 源視頻文件 * @param framefile 截取幀的圖片存放路徑 * @throws Exception */ public static void fetchPic(File file, String framefile) throws Exception{ FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); ff.start(); int lenght = ff.getLengthInFrames(); File targetFile = new File(framefile); int i = 0; Frame frame = null; while (i < lenght) { // 過(guò)濾前5幀,避免出現(xiàn)全黑的圖片,依自己情況而定 frame = ff.grabFrame(); if ((i > 5) && (frame.image != null)) { break; } i++; } String imgSuffix = "jpg"; if(framefile.indexOf('.') != -1){ String[] arr = framefile.split("\\."); if(arr.length>=2){ imgSuffix = arr[1]; } } Java2DFrameConverter converter =new Java2DFrameConverter(); BufferedImage srcBi =converter.getBufferedImage(frame); int owidth = srcBi.getWidth(); int oheight = srcBi.getHeight(); // 對(duì)截取的幀進(jìn)行等比例縮放 int width = 800; int height = (int) (((double) width / owidth) * oheight); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH),0, 0, null); try { ImageIO.write(bi, imgSuffix, targetFile); }catch (Exception e) { e.printStackTrace(); } ff.stop(); } /** * 獲取視頻時(shí)長(zhǎng),單位為秒 * @param file * @return 時(shí)長(zhǎng)(s) */ public static Long getVideoTime(File file){ Long times = 0L; try { FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); ff.start(); times = ff.getLengthInTime()/(1000*1000); ff.stop(); } catch (Exception e) { e.printStackTrace(); } return times; } }
以上就是java獲取視頻的時(shí)長(zhǎng),以及視頻獲取其中封面截圖。
除了上文的方法,小編還為大家整理了其他java獲取視頻時(shí)長(zhǎng)(實(shí)測(cè)可行)的方法,希望對(duì)大家有所幫助
下面是完整代碼
pom.xml
<!-- mp3文件支持(如語(yǔ)音時(shí)長(zhǎng))--> <dependency> <groupId>org</groupId> <artifactId>jaudiotagger</artifactId> <version>2.0.1</version> </dependency> <!-- mp4文件支持(如語(yǔ)音時(shí)長(zhǎng))--> <dependency> <groupId>com.googlecode.mp4parser</groupId> <artifactId>isoparser</artifactId> <version>1.1.22</version> </dependency>
單元測(cè)試
package com.opensourceteams.modules.java.util.video; import org.junit.Test; import java.io.IOException; import static org.junit.Assert.*; public class VideoUtilTest { @Test public void getDuration() throws IOException { String path = "/Users/liuwen/Downloads/temp/語(yǔ)音測(cè)試文件/xiaoshizi.mp3" ; /*path 為本地地址 */ long result = VideoUtil.getDuration(path); System.out.println(result); } }
工具類
package com.opensourceteams.modules.java.util.video; import com.coremedia.iso.IsoFile; import java.io.IOException; public class VideoUtil { /** * 獲取視頻文件的播放長(zhǎng)度(mp4、mov格式) * @param videoPath * @return 單位為毫秒 */ public static long getMp4Duration(String videoPath) throws IOException { IsoFile isoFile = new IsoFile(videoPath); long lengthInSeconds = isoFile.getMovieBox().getMovieHeaderBox().getDuration() / isoFile.getMovieBox().getMovieHeaderBox().getTimescale(); return lengthInSeconds; } /** * 得到語(yǔ)音或視頻文件時(shí)長(zhǎng),單位秒 * @param filePath * @return * @throws IOException */ public static long getDuration(String filePath) throws IOException { String format = getVideoFormat(filePath); long result = 0; if("wav".equals(format)){ result = AudioUtil.getDuration(filePath).intValue(); }else if("mp3".equals(format)){ result = AudioUtil.getMp3Duration(filePath).intValue(); }else if("m4a".equals(format)) { result = VideoUtil.getMp4Duration(filePath); }else if("mov".equals(format)){ result = VideoUtil.getMp4Duration(filePath); }else if("mp4".equals(format)){ result = VideoUtil.getMp4Duration(filePath); } return result; } /** * 得到語(yǔ)音或視頻文件時(shí)長(zhǎng),單位秒 * @param filePath * @return * @throws IOException */ public static long getDuration(String filePath,String format) throws IOException { long result = 0; if("wav".equals(format)){ result = AudioUtil.getDuration(filePath).intValue(); }else if("mp3".equals(format)){ result = AudioUtil.getMp3Duration(filePath).intValue(); }else if("m4a".equals(format)) { result = VideoUtil.getMp4Duration(filePath); }else if("mov".equals(format)){ result = VideoUtil.getMp4Duration(filePath); }else if("mp4".equals(format)){ result = VideoUtil.getMp4Duration(filePath); } return result; } /** * 得到文件格式 * @param path * @return */ public static String getVideoFormat(String path){ return path.toLowerCase().substring(path.toLowerCase().lastIndexOf(".") + 1); } }
package com.opensourceteams.modules.java.util.video; import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.mp3.MP3AudioHeader; import org.jaudiotagger.audio.mp3.MP3File; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import java.io.File; public class AudioUtil { /** * 獲取語(yǔ)音文件播放時(shí)長(zhǎng)(秒) 支持wav 格式 * @param filePath * @return */ public static Float getDuration(String filePath){ try{ File destFile = new File(filePath); AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(destFile); AudioFormat format = audioInputStream.getFormat(); long audioFileLength = destFile.length(); int frameSize = format.getFrameSize(); float frameRate = format.getFrameRate(); float durationInSeconds = (audioFileLength / (frameSize * frameRate)); return durationInSeconds; }catch (Exception e){ e.printStackTrace(); return 0f; } } /** * 獲取mp3語(yǔ)音文件播放時(shí)長(zhǎng)(秒) mp3 * @param filePath * @return */ public static Float getMp3Duration(String filePath){ try { File mp3File = new File(filePath); MP3File f = (MP3File) AudioFileIO.read(mp3File); MP3AudioHeader audioHeader = (MP3AudioHeader)f.getAudioHeader(); return Float.parseFloat(audioHeader.getTrackLength()+""); } catch(Exception e) { e.printStackTrace(); return 0f; } } /** * 獲取mp3語(yǔ)音文件播放時(shí)長(zhǎng)(秒) * @param mp3File * @return */ public static Float getMp3Duration(File mp3File){ try { //File mp3File = new File(filePath); MP3File f = (MP3File) AudioFileIO.read(mp3File); MP3AudioHeader audioHeader = (MP3AudioHeader)f.getAudioHeader(); return Float.parseFloat(audioHeader.getTrackLength()+""); } catch(Exception e) { e.printStackTrace(); return 0f; } } /** * 得到pcm文件的毫秒數(shù) * * pcm文件音頻時(shí)長(zhǎng)計(jì)算 * 同圖像bmp文件一樣,pcm文件保存的是未壓縮的音頻信息。 16bits 編碼是指,每次采樣的音頻信息用2個(gè)字節(jié)保存。可以對(duì)比下bmp文件用分別用2個(gè)字節(jié)保存RGB顏色的信息。 16000采樣率 是指 1秒鐘采樣 16000次。常見(jiàn)的音頻是44100HZ,即一秒采樣44100次。 單聲道: 只有一個(gè)聲道。 * * 根據(jù)這些信息,我們可以計(jì)算: 1秒的16000采樣率音頻文件大小是 2*16000 = 32000字節(jié) ,約為32K 1秒的8000采樣率音頻文件大小是 2*8000 = 16000字節(jié) ,約為 16K * * 如果已知錄音時(shí)長(zhǎng),可以根據(jù)文件的大小計(jì)算采樣率是否正常。 * @param filePath * @return */ public static long getPCMDurationMilliSecond(String filePath) { File file = new File(filePath); //得到多少秒 long second = file.length() / 32000 ; long milliSecond = Math.round((file.length() % 32000) / 32000.0 * 1000 ) ; return second * 1000 + milliSecond; } }
因?yàn)槲覀兪歉鶕?jù)在線url獲取視頻時(shí)長(zhǎng)的
還需要再添加一步: 本地臨時(shí)存儲(chǔ)文件
public void getDuration() throws IOException { File file = getFileByUrl("https://video-ecook.oss-cn-hangzhou.aliyuncs.com/76bd353630be47f0b5447ec06201ee56.mp4"); String path = file.getCanonicalPath(); ; System.out.println(path); long result = VideoUtil.getDuration(path); System.out.println(result + "s"); }
public static File getFileByUrl(String url) throws IOException { File tmpFile = File.createTempFile("temp", ".mp4");//創(chuàng)建臨時(shí)文件 Image2Binary.toBDFile(url, tmpFile.getCanonicalPath()); return tmpFile; }
到此這篇關(guān)于Java獲取視頻時(shí)長(zhǎng)和封面截圖的文章就介紹到這了,更多相關(guān)Java獲取視頻時(shí)長(zhǎng)和封面內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot公共字段填充及ThreadLocal模塊改進(jìn)方案
這篇文章主要為大家介紹了Springboot公共字段填充及ThreadLocal模塊改進(jìn)方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11springboot?加載本地jar到maven的實(shí)現(xiàn)方法
如何在SpringBoot項(xiàng)目中加載本地jar到Maven本地倉(cāng)庫(kù),使用Maven的install-file目標(biāo)來(lái)實(shí)現(xiàn),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2025-01-01SpringBoot使用@Slf4j注解實(shí)現(xiàn)日志輸出的示例代碼
@Slf4j 是 Lombok 庫(kù)中的一個(gè)注解,它極大地簡(jiǎn)化了日志記錄的代碼,通過(guò)使用這個(gè)注解,Lombok 會(huì)自動(dòng)在你的類中注入一個(gè)靜態(tài)的日志對(duì)象,本文給大家介紹了SpringBoot使用@Slf4j注解實(shí)現(xiàn)日志輸出的方法,需要的朋友可以參考下2024-10-10SpringMVC之RequestContextHolder詳細(xì)解析
這篇文章主要介紹了SpringMVC之RequestContextHolder詳細(xì)解析,正常來(lái)說(shuō)在service層是沒(méi)有request的,然而直接從controlller傳過(guò)來(lái)的話解決方法太粗暴,后來(lái)發(fā)現(xiàn)了SpringMVC提供的RequestContextHolder,需要的朋友可以參考下2023-11-11