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-11
springboot?加載本地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-01
SpringBoot使用@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-10
SpringMVC之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

