Java使用FFmpeg(自定义cmd)系列之获取视频/音频时长(File文件方式)

ffmpeg系列

Java使用FFmpeg(自定义cmd)
Java使用FFmpeg(自定义cmd)系列之获取视频/音频时长
Java使用FFmpeg(自定义cmd)系列之官方API获取视频/音频信息(File方式)
Java使用FFmpeg(自定义cmd)系列之官方API获取视频/音频信息(URL方式)
Java使用FFmpeg(自定义cmd)系列之获取视频/音频时长(File文件方式)
Java使用FFmpeg(自定义cmd)系列之mp4转hsl编码m3u8
Java使用FFmpeg(自定义cmd)系列之MP4 转码 HLS m3u8 AES128 加密

使用ffmpeg 自定义的cmd命令获取时长,废话不多说,代码说话:
不用我们安装FFmpeg,项目自动依赖ffmpeg,已经有开源实现:https://github.com/a-schild/jave2

下面的代码基于:3.1.1 version

maven坐标:

<dependency>
 <groupId>ws.schild</groupId>
 <artifactId>jave-all-deps</artifactId>
 <version>3.1.1</version>
</dependency>
package com.hsj.demo;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.hsj.cmd.FfmpegCmd;
import com.hsj.threadpool.ThreadPoolExecutorUtils;

/**
 * 
 * @Description:(获取视频/音频时长---使用File文件方式)   
 * @author: HeShengjin
 * @date:   2021年6月23日 下午1:24:43    
 * @Copyright:
 */
public class FfmpegCmdFile4DurationTest {
	private final static String DURATION_START = "Duration:";
	
	private final static String KEY_FOR_HOUR = "hour";
	private final static String KEY_FOR_MINUTE = "minute";
	private final static String KEY_FOR_SECONED = "seconed";
	private final static String KEY_FOR_MILLSECONED = "millseconed";
	
	//小时 * 60 = 分
	//分 * 60 = 秒
	private final static BigDecimal GAP_60 = new BigDecimal("60");
	//秒* 1000 = 毫秒
	private final static BigDecimal GAP_1000 = new BigDecimal("1000");
	
	/**
	 *  TYPE_0:小时
	 *  TYPE_1:分钟
	 *  TYPE_2:秒钟
	 *  TYPE_3:毫秒 
	 */
	public final static int TYPE_0 = 0;
	public final static int TYPE_1 = 1;
	public final static int TYPE_2 = 2;
	public final static int TYPE_3 = 3;
	
	//ffmpeg执行命令
	private final static String file_absolute_path = "I:\\荣耀视频测试.mp4";
	private final static String cmd_4_info = "-i $FileAbsolutePath";

	public static void main(String[] args) {
	  try {
		System.out.println(String.format("获取时长:%s 小时", duration4File(new File(file_absolute_path),TYPE_0).doubleValue()));
		System.out.println(String.format("获取时长:%s 分钟", duration4File(new File(file_absolute_path),TYPE_1).doubleValue()));
		System.out.println(String.format("获取时长:%s 秒钟", duration4File(new File(file_absolute_path),TYPE_2).doubleValue()));
		System.out.println(String.format("获取时长:%s 毫秒", duration4File(new File(file_absolute_path),TYPE_3).doubleValue()));
		System.out.println("");
		System.out.println(String.format("获取时长(格式化):%s", durationFormat4File(new File(file_absolute_path))));
	} catch (Exception e) {
		e.printStackTrace();
	}
	}
	/**
	 * 
	 * @Description: (获取格式化的时间duration:such as:00:01:03.32)   
	 * @param: @param File file
	 * @param: @return
	 * @param: @throws Exception      
	 * @return: BigDecimal      
	 * @throws
	 */
	public static String durationFormat4File(final File file) throws Exception {
		String duration = null;
		Map<String,String> map = null;
		try {
			CompletableFuture<String> completableFutureTask = CompletableFuture.supplyAsync(() ->{	
				                String durationStr = null;
				                //执行ffmpeg命令
								StringBuffer sText = getErrorStreamText(cmd_4_info.replace("$FileAbsolutePath", file.getAbsolutePath()));
								if(null != sText && sText.indexOf(DURATION_START) > -1) {
									String stextOriginal = sText.toString();
									//正则解析时间
									Matcher matcher = patternDuration().matcher(stextOriginal);
							        //正则提取字符串
									while(matcher.find()){
										//such as:00:01:03.32
										durationStr = matcher.group(1);
										break;
									}
								}
								return durationStr;
				   }, ThreadPoolExecutorUtils.pool);

			duration = completableFutureTask.get();

		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		return duration;
	}
	/**
	 * 
	 * @Description: (获取时长)   
	 * @param: @param File file ffmpeg命令,如:-i I:\\荣耀视频测试.mp4
	 * @param: @param type 类型:
	 *                        TYPE_0:小时
	 *                        TYPE_1:分钟
	 *                        TYPE_2:秒钟
	 *                        TYPE_3:毫秒
	 * @param: @return      
	 * @return: BigDecimal      
	 * @throws Exception 
	 * @throws
	 */
	public static BigDecimal duration4File(final File file, int type) throws Exception {
		BigDecimal duration = new BigDecimal("00");
		Map<String,String> map = null;
		try {
			CompletableFuture<Map<String,String>> completableFutureTask = CompletableFuture.supplyAsync(() ->{		  	  
				                Map<String,String> mapTmp = null;
				                //执行ffmpeg命令
								StringBuffer sText = getErrorStreamText(cmd_4_info.replace("$FileAbsolutePath", file.getAbsolutePath()));
								if(null != sText && sText.indexOf(DURATION_START) > -1) {
									String stextOriginal = sText.toString();
									//正则解析时间
									Matcher matcher = patternDuration().matcher(stextOriginal);
							        //正则提取字符串
									while(matcher.find()){
										//such as:00:01:03.32
										String durationStr = matcher.group(1);
										mapTmp = getHourMinuteSeconedMillseconed(durationStr);
										break;
									}
								}
								return mapTmp;
				   }, ThreadPoolExecutorUtils.pool);

			map = completableFutureTask.get();
			if(null != map && map.size() > 0) {
				switch (type) {
				case TYPE_0:
					//小时
					duration = duration.add(new BigDecimal(map.get(KEY_FOR_HOUR)));
					break;
				case TYPE_1:
					//分钟
					duration = duration.add(new BigDecimal(map.get(KEY_FOR_HOUR)).multiply(GAP_60))
					                   .add(new BigDecimal(map.get(KEY_FOR_MINUTE)));
					break;
				case TYPE_2:
					//秒
					duration = duration.add(new BigDecimal(map.get(KEY_FOR_HOUR)).multiply(GAP_60).multiply(GAP_60))
	                                   .add(new BigDecimal(map.get(KEY_FOR_MINUTE)).multiply(GAP_60))
	                                   .add(new BigDecimal(map.get(KEY_FOR_SECONED)));
					break;
				case TYPE_3:
					//毫秒
					duration = duration.add(new BigDecimal(map.get(KEY_FOR_HOUR)).multiply(GAP_60).multiply(GAP_60).multiply(GAP_1000))
	                                   .add(new BigDecimal(map.get(KEY_FOR_MINUTE)).multiply(GAP_60).multiply(GAP_1000))
	                                   .add(new BigDecimal(map.get(KEY_FOR_SECONED)).multiply(GAP_1000))
	                                   .add(new BigDecimal(map.get(KEY_FOR_MILLSECONED)));
					break;
				default:
					throw new Exception("未知的类型!");
				} 
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		return duration;
	}
	
	//模式
	public static Pattern patternDuration() {
		//"(?i)duration:\\s*([0-9\\:\\.]+)"-->匹配到时分秒即可,毫秒不需要
		return Pattern.compile("(?i)duration:\\s*([0-9\\:\\.]+)");
	}
	/**
	 * 
	 * @Description: (获取错误流)   
	 * @param: @param cmd_4_info
	 * @param: @return      
	 * @return: StringBuffer      
	 * @throws
	 */
	private static StringBuffer getErrorStreamText(String cmdStr) {
		  //返回的text
		  StringBuffer sText = new StringBuffer();
		  FfmpegCmd ffmpegCmd = new FfmpegCmd();			  			  		
		  try {
;	
				 //错误流
				 InputStream errorStream = null;
				//destroyOnRuntimeShutdown表示是否立即关闭Runtime
				//如果ffmpeg命令需要长时间执行,destroyOnRuntimeShutdown = false
			
				//openIOStreams表示是不是需要打开输入输出流:
				//	       inputStream = processWrapper.getInputStream();
				//	       outputStream = processWrapper.getOutputStream();
				//	       errorStream = processWrapper.getErrorStream();
			   ffmpegCmd.execute(false, true, cmdStr);
			   errorStream = ffmpegCmd.getErrorStream();		   
			   
			    //打印过程
			    int len = 0;
		        while ((len=errorStream.read())!=-1){
		        	char t = (char)len;
//		            System.out.print(t);
		            sText.append(t);
		        }
			   
			   //code=0表示正常
		       ffmpegCmd.getProcessExitCode();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				//关闭资源
				ffmpegCmd.close();
			}
		  //返回
		  return sText;
	}
	
	/**
	 * 
	 * @Description: (获取duration的时分秒毫秒)   
	 * @param: durationStr  such as:00:01:03.32
	 * @return: Map      
	 * @throws
	 */
	private static Map<String,String> getHourMinuteSeconedMillseconed(String durationStr){
		HashMap<String,String> map = new HashMap<>(4);
		if(null != durationStr && durationStr.length() > 0) {
			String[] durationStrArr = durationStr.split("\\:");
			String hour = durationStrArr[0];
			String minute = durationStrArr[1];
			//特殊
			String seconed = "00";
			String millseconed = "00";
			String seconedTmp = durationStrArr[2];
			if(seconedTmp.contains("\\.")) {
				String[] seconedTmpArr = seconedTmp.split("\\.");
				seconed = seconedTmpArr[0];
				millseconed = seconedTmpArr[1];
			}
			else {
				seconed = seconedTmp;
			}
			map.put(KEY_FOR_HOUR, hour);
			map.put(KEY_FOR_MINUTE, minute);
			map.put(KEY_FOR_SECONED, seconed);
			map.put(KEY_FOR_MILLSECONED, millseconed);
		}
		return map;
	}

}

在这里插入图片描述
gitee:https://gitee.com/hsjjsh123/test-ffmpeg

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值