Java使用FFmpeg(自定义cmd)

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,项目自动依赖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>

cmd方式调用ffmpeg(封装):

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ws.schild.jave.process.ProcessKiller;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;
/**
 * 
 * @Description:(cmd方式调用ffmpeg)   
 * @author: HeShengjin
 * @date:   2021年6月22日 下午5:31:38    
 * @Copyright:
 */
public class FfmpegCmd {
	
	      private static final Logger LOG = LoggerFactory.getLogger(ProcessWrapper.class);

		  /** The process representing the ffmpeg execution. */
		  private Process ffmpeg = null;
	
		  /**
		   * A process killer to kill the ffmpeg process with a shutdown hook, useful if the jvm execution
		   * is shutted down during an ongoing encoding process.
		   */
		  private ProcessKiller ffmpegKiller = null;
	
		  /** A stream reading from the ffmpeg process standard output channel. */
		  private InputStream inputStream = null;
	
		  /** A stream writing in the ffmpeg process standard input channel. */
		  private OutputStream outputStream = null;
	
		  /** A stream reading from the ffmpeg process standard error channel. */
		  private InputStream errorStream = null;
			 
		  /**
		   * Executes the ffmpeg process with the previous given arguments.
		   *
		   * @param destroyOnRuntimeShutdown destroy process if the runtime VM is shutdown
		   * @param openIOStreams Open IO streams for input/output and errorout, should be false when
		   *     destroyOnRuntimeShutdown is false too
		   * @param ffmpegCmd  windows such as (mp4 transform to mov): 
		   *     " -i C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer.mp4 -c copy C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer_test.mov "
		   * @throws IOException If the process call fails.
		   */
			public void execute(boolean destroyOnRuntimeShutdown, boolean openIOStreams, String ffmpegCmd) throws IOException {
		    	DefaultFFMPEGLocator defaultFFMPEGLocator = new DefaultFFMPEGLocator();
		  	  
		  	    StringBuffer cmd = new StringBuffer(defaultFFMPEGLocator.getExecutablePath());
		  	    //insert blank for delimiter
		  	    cmd.append(" ");
		  	    cmd.append(ffmpegCmd);
		  	    String cmdStr = String.format("ffmpegCmd final is :%s", cmd.toString());
		  	    System.out.println(cmdStr);
		  	    LOG.info(cmdStr);
		  	    
		    	Runtime runtime = Runtime.getRuntime();
			    try {			    	   
			    	    ffmpeg = runtime.exec(cmd.toString());
			    	
			    	    if (destroyOnRuntimeShutdown) {
			    	      ffmpegKiller = new ProcessKiller(ffmpeg);
			    	      runtime.addShutdownHook(ffmpegKiller);
			    	    }
	
			    	    if (openIOStreams) {
			    	      inputStream = ffmpeg.getInputStream();
			    	      outputStream = ffmpeg.getOutputStream();
			    	      errorStream = ffmpeg.getErrorStream();
			    	    }
				} catch (Exception e) {
					e.printStackTrace();
				}
			}   
		    
		    /**
		     * Returns a stream reading from the ffmpeg process standard output channel.
		     *
		     * @return A stream reading from the ffmpeg process standard output channel.
		     */
		    public InputStream getInputStream() {
		      return inputStream;
		    }

		    /**
		     * Returns a stream writing in the ffmpeg process standard input channel.
		     *
		     * @return A stream writing in the ffmpeg process standard input channel.
		     */
		    public OutputStream getOutputStream() {
		      return outputStream;
		    }

		    /**
		     * Returns a stream reading from the ffmpeg process standard error channel.
		     *
		     * @return A stream reading from the ffmpeg process standard error channel.
		     */
		    public InputStream getErrorStream() {
		      return errorStream;
		    }

		    /** If there's a ffmpeg execution in progress, it kills it. */
		    public void destroy() {
		      if (inputStream != null) {
		        try {
		          inputStream.close();
		        } catch (Throwable t) {
		          LOG.warn("Error closing input stream", t);
		        }
		        inputStream = null;
		      }

		      if (outputStream != null) {
		        try {
		          outputStream.close();
		        } catch (Throwable t) {
		          LOG.warn("Error closing output stream", t);
		        }
		        outputStream = null;
		      }

		      if (errorStream != null) {
		        try {
		          errorStream.close();
		        } catch (Throwable t) {
		          LOG.warn("Error closing error stream", t);
		        }
		        errorStream = null;
		      }

		      if (ffmpeg != null) {
		        ffmpeg.destroy();
		        ffmpeg = null;
		      }

		      if (ffmpegKiller != null) {
		        Runtime runtime = Runtime.getRuntime();
		        runtime.removeShutdownHook(ffmpegKiller);
		        ffmpegKiller = null;
		      }
		    }

		    /**
		     * Return the exit code of the ffmpeg process If the process is not yet terminated, it waits for
		     * the termination of the process
		     *
		     * @return process exit code
		     */
		    public int getProcessExitCode() {
		      // Make sure it's terminated
		      try {
		        ffmpeg.waitFor();
		      } catch (InterruptedException ex) {
		        LOG.warn("Interrupted during waiting on process, forced shutdown?", ex);
		      }
		      return ffmpeg.exitValue();
		    }

		    /**close**/
		    public void close() {
		      destroy();
		    }    
		
}

cmd方式调用ffmpeg(使用):


import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 
 * @Description:(cmd方式调用ffmpeg使用)   
 * @author: HeShengjin
 * @date:   2021年6月22日 下午5:32:31    
 * @Copyright:
 */
public class FfmpegCmdTest {
	//执行成功0,失败1
	private static int CODE_SUCCESS = 0;
	private static int CODE_FAIL = 1;
	//将荣耀视频测试.mp4转换荣耀视频测试_转码.mov格式
	private static String cmd_mp4_2_mov = " -i I:\\荣耀视频测试.mp4 -c copy I:\\荣耀视频测试_转码.mov ";	
	//将荣耀视频测试_转码.mov添加水印([email protected])荣耀视频测试_转码_水印.mov
	private static String cmd_mov_water = " -i I:\\荣耀视频测试_转码.mov -vf \"drawtext=fontfile=Arial.ttf:text='[email protected]':y=h-line_h-20:x=(w-text_w)/2:fontsize=34:fontcolor=yellow:shadowy=2\" -b:v 3000k I:\\\\荣耀视频测试_转码_水印.mov ";

	//多线程
	private static int core = Runtime.getRuntime().availableProcessors();
	private static ExecutorService pool = new ThreadPoolExecutor(core,//核心
			core * 2,//最大
            0L,//空闲立即退出
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),//无边界阻塞队列
            new ThreadPoolExecutor.AbortPolicy());
	/**
	 * 第一步:mp4转mov
	 * 第二步:mov添加水印
	 * @param: @param args      
	 * @return: void      
	 * @throws
	 */
    public static void main(String[] args) {
	  
	  //异步执行,获取执行结果code
	  CompletableFuture<Integer> completableFutureTask = CompletableFuture.supplyAsync(() ->{		  	  
	        return cmdExecut(cmd_mp4_2_mov);
	  }, pool)
	  .thenApplyAsync((Integer code)->{
		  if(CODE_SUCCESS != code) {return CODE_FAIL;}
		  System.out.println("第一步:mp4转mov,成功!");
		  Integer codeTmp =  cmdExecut(cmd_mov_water);
		  if(CODE_SUCCESS != codeTmp) {return CODE_FAIL;}
		  System.out.println("第二步:mov添加水印,成功!");
		  return codeTmp;
	  }, pool);
	  
	    //获取执行结果
	    //code=0表示正常
	    try {
		    System.out.println(String.format("获取最终执行结果:%s", completableFutureTask.get() == CODE_SUCCESS ? "成功!" : "失败!"));
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	    
    }
    
    /**
     * 
     * @Description: (执行ffmpeg自定义命令)   
     * @param: @param cmdStr
     * @param: @return      
     * @return: Integer      
     * @throws
     */
    public static Integer cmdExecut(String cmdStr) {
		  //code=0表示正常
	      Integer code  = null;	   
		  FfmpegCmd ffmpegCmd = new FfmpegCmd();			  			  
		  /**
		   * 错误流
		   */
		  InputStream errorStream = null;		
		  try {
				//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){
		            System.out.print((char)len);
		        }
			   
			   //code=0表示正常
			   code = ffmpegCmd.getProcessExitCode();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				//关闭资源
				ffmpegCmd.close();
			}
		  //返回
		  return code;
    }
    
}

Java使用FFmpeg(自定义cmd)_第1张图片
在这里插入图片描述

Java使用FFmpeg(自定义cmd)_第2张图片
Java使用FFmpeg(自定义cmd)_第3张图片

Java使用FFmpeg(自定义cmd)_第4张图片

我的小站:
http://www.binarydance.top//aticle_view.html?aticle_id=587710507340017664&t=1620287576763

gitee:
https://gitee.com/hsjjsh123/test-ffmpeg

你可能感兴趣的:(java,ffmpeg)