视频截图 使用ffmpeg_mencoder

VideoConvert_CutPic.java

import java.io.File;  
import java.util.ArrayList;  
import java.util.Calendar;  
import java.util.List;  
/**
 * 视频转码_截图
 */
public class VideoConvert_CutPic {
    private final static String srcFilePath = "D:/ffmpeg_mencoder_File/sourceVideos/短视频.mp4";  //源视频文件路径
      
    public static void main(String[] args) {  
        if (!is_File(srcFilePath)) {   //判断路径是不是一个文件
            System.out.println(srcFilePath + " is not file");  
            return;  
        }  
        if (executeCodecs()) {        //执行转码任务
            System.out.println("ok");  
        }  
    }  
    /**
     * 判断路径是不是一个文件
     *
     * @param file
     *            源视频文件路径
     */
    private static boolean is_File(String path) {  
        File file = new File(path);  
        if (!file.isFile()) {  
            return false;  
        }  
        return true;  
    }
    
    /**
     * 判断视频格式
     */
    private static int is_VideoType() {  
        String type = srcFilePath.substring(srcFilePath.lastIndexOf(".") + 1, srcFilePath.length()).toLowerCase();  
        // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
        if (type.equals("avi")) {  
            return 0;  
        } else if (type.equals("mpg")) {  
            return 0;  
        } else if (type.equals("wmv")) {  
            return 0;  
        } else if (type.equals("3gp")) {  
            return 0;  
        } else if (type.equals("mov")) {  
            return 0;  
        } else if (type.equals("mp4")) {  
            return 0;  
        } else if (type.equals("asf")) {  
            return 0;  
        } else if (type.equals("asx")) {  
            return 0;  
        } else if (type.equals("flv")) {  
            return 0;  
        }  
        // 对ffmpeg.exe无法解析的文件格式(wmv9,rm,rmvb等),可以先用别的工具(mencoder.exe)转换为.avi(ffmpeg能解析的格式).  
        else if (type.equals("wmv9")) {  
            return 1;  
        } else if (type.equals("rm")) {  
            return 1;  
        } else if (type.equals("rmvb")) {  
            return 1;  
        }  
        return 9;  
    }
    /**
     * 源视频转换成AVI格式
     *
     * @param type
     *            视频格式
     */
    // 对ffmpeg.exe无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder.exe)转换为avi(ffmpeg能解析的)格式.  
    private static String convertToAVI(int type) {  
        List<String> commend = new ArrayList<String>();  
        commend.add("D:\\ffmpeg_mencoder_File\\Tools\\mencoder.exe");  
        commend.add(srcFilePath);  
        commend.add("-oac");  
        commend.add("lavc");  
        commend.add("-lavcopts");  
        commend.add("acodec=mp3:abitrate=64");  
        commend.add("-ovc");  
        commend.add("xvid");  
        commend.add("-xvidencopts");  
        commend.add("bitrate=600");  
        commend.add("-of");  
        commend.add("avi");  
        commend.add("-o");  
        commend.add("D:\\ffmpeg_mencoder_File\\targetVideos\\oneRedioAfter.avi"); //【存放转码后视频的路径,记住一定是.avi后缀的文件名】
        try {  
            //调用线程命令启动转码
            ProcessBuilder builder = new ProcessBuilder();  
            builder.command(commend);  
            builder.start();  
            return "D:\\ffmpeg_mencoder_File\\targetVideos\\oneRedioAfter.avi";  //【存放转码后视频的路径,记住一定是.avi后缀的文件名】
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
 
    /**
     * 源视频转换成FLV格式
     * @param srcFilePathParam
     *            源:用于指定要转换格式的文件,要截图的源视频文件路径
     */
    // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
    private static boolean convertToFLV(String srcFilePathParam) {  
          if (!is_File(srcFilePath)) {  
            System.out.println(srcFilePathParam + " is not file");  
            return false;  
        }  
        // 文件命名  
        Calendar c = Calendar.getInstance();  
        String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);  
        List<String> commend = new ArrayList<String>();  
        commend.add("D:\\ffmpeg_mencoder_File\\Tools\\ffmpeg.exe");  
        commend.add("-i");  
        commend.add(srcFilePathParam);  
        commend.add("-ab");  
        commend.add("56");  
        commend.add("-ar");  
        commend.add("22050");  
        commend.add("-qscale");  
        commend.add("8");  
        commend.add("-r");  
        commend.add("15");  
        commend.add("-s");  
        commend.add("600x500");  
        commend.add("D:\\ffmpeg_mencoder_File\\targetVideos\\oneRedioAfter.flv");  //【存放转码后视频的路径,记住一定是.flv后缀的文件名】
        try {  
            Runtime runtime = Runtime.getRuntime();  
            Process proce = null;
            String cutPicPath = "     D:\\ffmpeg_mencoder_File\\Tools\\ffmpeg.exe   -i   "  
                    + srcFilePathParam  
                    + "   -y   -f   image2   -ss   2   -t   0.001   -s   600x500   d:\\ffmpeg_mencoder_File\\cutPicture\\"  
                    + "oneCutPic.jpg";  //截图文件的保存路径  
            proce = runtime.exec(cutPicPath);
            //调用线程命令进行转码
            ProcessBuilder builder = new ProcessBuilder(commend);                 
            builder.command(commend);  
            builder.start();  
            return true;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return false;  
        }  
    }
    /**
     * 视频转码(mencoder.exe或ffmpeg.exe执行编码解码)
     */
    private static boolean executeCodecs() {
        // 判断视频的类型
        int type = is_VideoType();  
        boolean status = false;  
        //如果是ffmpeg可以转换的类型直接转码,否则先用mencoder转码成AVI
        if (type == 0) {  
            System.out.println("直接将文件转为flv文件");  
            status = convertToFLV(srcFilePath);// 直接将文件转为flv文件  
        } else if (type == 1) {  //
            String codcFilePath = convertToAVI(type); //视频格式转换后的目标视频文件路径
            if (codcFilePath == null){
                return false;// avi文件没有得到  
            }    
            status = convertToFLV(codcFilePath);// 将avi转为flv  
        }  
        return status;  
    }
}
/**
 * 参考
 * java-ffmpeg_mencoder(一) 实现视频的转码和截图功能https://www.cnblogs.com/tohxyblog/p/6640786.html
 * 命令格式:
普通转码:
ffmpeg -i [输入文件名] [参数选项] -f [格式] [输出文件]
比如:MP4转avi    D:\\ffmpeg_mencoder_File\\Tools\\ffmpeg.exe -i
                    D:/ffmpeg_mencoder_File/sourceVideos/短视频.mp4 -f avi
                    D:\\ffmpeg_mencoder_File\\targetVideos\\oneRedioAfter.avi
参数:-an 去掉音频
-b 1000K 压缩码率为1000K
-s 800*500 压缩尺寸为800*500
-aspect 宽高比,格式 16:9 或 1.778
(当源尺寸是16:9,要压缩成非16:9的,一方面要设定 -s,另一方面要给出 -aspect)
-ss 开始时间​
-t 持续时长
 */

VideoPicTest.java

import ljx.dao.VideoPicDao;
import ljx.service.VideoPicService;

public class VideoPicServiceImpl implements VideoPicService{
	  private VideoPicDao videoPicDao;
	  
	  public VideoPicDao getVideoPicDao() {
	    return videoPicDao;
	  }
	 
	  public void setVideoPicDao(VideoPicDao videoPicDao) {
	    this.videoPicDao = videoPicDao;
	  }
	 
	  public boolean executeCodecs(String srcFilePath, String codcFilePath,
	      String mediaPicPath) {
	    return videoPicDao.executeCodecs(srcFilePath, codcFilePath, mediaPicPath);
	  }
}

VideoPicService.java

public interface VideoPicService {
	/**
	   * 视频转码
	   * @param srcFilePath  用于指定要转换格式的文件,要截图的视频源文件
	   * @param codcFilePath 格式转换后的的文件保存路径
	   * @param mediaPicPath 截图保存路径
	   * @return
	   */
	public boolean executeCodecs(String srcFilePath, String codcFilePath, String mediaPicPath);
}

VideoPicServiceImpl.java

import ljx.dao.VideoPicDao;
import ljx.service.VideoPicService;

public class VideoPicServiceImpl implements VideoPicService{
	  private VideoPicDao videoPicDao;
	  
	  public VideoPicDao getVideoPicDao() {
	    return videoPicDao;
	  }
	 
	  public void setVideoPicDao(VideoPicDao videoPicDao) {
	    this.videoPicDao = videoPicDao;
	  }
	 
	  public boolean executeCodecs(String srcFilePath, String codcFilePath,
	      String mediaPicPath) {
	    return videoPicDao.executeCodecs(srcFilePath, codcFilePath, mediaPicPath);
	  }
}

VideoPicDao.java

public interface VideoPicDao {
	/**
	 * 视频转码(mencoder.exe或ffmpeg.exe执行编码解码)
	 * 
	 * @param srcFilePath
	 *            源:用于指定要转换格式的文件,要截图的源视频文件路径
	 * @param codcFilePath
	 *            目标:视频格式转换后的的目标视频文件保存路径
	 * @param mediaPicPath
	 *            截图保存路径
	 * @return
	 */
	public boolean executeCodecs(String srcFilePath, String codcFilePath, String mediaPicPath);
}

VideoPicDaoImpl.java

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import ljx.dao.VideoPicDao;

public class VideoPicDaoImpl implements VideoPicDao{
	/**
	 * 判断源视频文件格式是ffmpeg.exe能解析的格式
	 * 
	 * @param file
	 *            源视频文件路径
	 */
	public boolean is_ffmpegVideoType(String file) {
		boolean result = false;
		String ext = file.substring(file.lastIndexOf(".") + 1, file.length()).toLowerCase();
		// ffmpeg.exe能解析并相互转换的的源文件格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
		// 对ffmpeg.exe无法解析的源文件格式(wmv9,rm,rmvb等),可以先用别的工具(mencoder.exe)解析;然后转换为.avi(ffmpeg.exe能解析的格式).
		if (ext.equals("avi")) {
			result = true;
		} else if (ext.equals("mpg")) {
			result = true;
		} else if (ext.equals("wmv")) {
			result = true;
		} else if (ext.equals("3gp")) {
			result = true;
		} else if (ext.equals("mov")) {
			result = true;
		} else if (ext.equals("mp4")) {
			result = true;
		} else if (ext.equals("asf")) {
			result = true;
		} else if (ext.equals("asx")) {
			result = true;
		} else if (ext.equals("flv")) {
			result = true;
		}
		return result;
	}
	/**
	 * 判断源视频文件格式是mencoder.exe能解析的格式
	 * 
	 * @param file
	 *            源视频文件路径
	 */
	public boolean is_mencoderVideoType(String file) {
		boolean result = false;
		String ext = file.substring(file.lastIndexOf(".") + 1, file.length()).toLowerCase();
		if (ext.equals("wmv9")) {
			result = true;
		} else if (ext.equals("rm")) {
			result = true;
		} else if (ext.equals("rmvb")) {
			result = true;
		}
		return result;
	}

	/**
	 * 源视频转换成FLV格式
	 * 
	 * @param ffmpegPath
	 *            ffmpeg.exe转换工具路径
	 * @param srcFilePath
	 *            源:用于指定要转换格式的文件,要截图的源视频文件路径
	 * @param codcFilePath
	 *            目标:视频格式转换后的的目标视频文件保存路径
	 */
	private boolean convertToFLV(String ffmpegPath, String srcFilePath,String codcFilePath) {
		File file = new File(ffmpegPath);
		File srcFile = new File(srcFilePath);
		if (file.exists()) {
			System.out.println("转换工具存在");
		}
		if (srcFile.exists()) {
			System.out.println("源视频存在");
		}
		// 创建一个List集合来保存转换视频文件为flv格式的命令
		List<String> convert = new ArrayList<String>();
		convert.add(ffmpegPath); // 添加转换工具路径
		convert.add("-i"); // 添加参数"-i",该参数指定要转换的文件
		convert.add(srcFilePath); // 添加要转换格式的视频文件的路径
		convert.add("-ab"); // 设置音频码率
		convert.add("128");
		convert.add("-ac"); // 设置声道数
		convert.add("2");
		convert.add("-qscale");
		convert.add("6");
		convert.add("-ar"); // 设置声音的采样频率
		convert.add("22050");
		convert.add("-r"); // 设置帧频
		convert.add("29.97");
		convert.add("-b");
		convert.add("5942.13");
		convert.add("-s");
		convert.add("1280x720");
		convert.add("-y"); // 添加参数"-y",该参数指定将覆盖已存在的文件
		convert.add(codcFilePath);

		boolean mark = true;
		try {
			Process proc = new ProcessBuilder(convert).redirectErrorStream(true).start();
			BufferedReader stdout = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			String line;
			while ((line = stdout.readLine()) != null) {
				System.out.println(line);
			}
		} catch (Exception e) {
			mark = false;
			System.out.println(e);
			e.printStackTrace();
		}
		return mark;
	}



	/**
	 * 源视频转换成AVI格式
	 * 
	 * @param mencoderPath
	 *            mencoder.exe转换工具路径
	 * @param srcFilePath
	 *            源:用于指定要转换格式的文件,要截图的源视频文件路径
	 * @param codcFilePath
	 *            目标:视频格式转换后的的目标视频文件保存路径
	 */
	private boolean convertToAVI(String mencoderPath, String srcFilePath,String codcFilePath) {
		List<String> commend = new ArrayList<String>();
		commend.add(mencoderPath);
		commend.add(srcFilePath);
		commend.add("-oac");
		commend.add("lavc");
		commend.add("-lavcopts");
		commend.add("acodec=mp3:abitrate=64");
		commend.add("-ovc");
		commend.add("xvid");
		commend.add("-xvidencopts");
		commend.add("bitrate=600");
		commend.add("-of");
		commend.add("avi");
		commend.add("-o");
		commend.add(codcFilePath);
		try {
			ProcessBuilder builder = new ProcessBuilder();
			builder.command(commend);
			builder.redirectErrorStream(true);// 后续子进程错误输出与标准输出合并
			Process p = builder.start();
			p.getInputStream();
			// 后续进程等待Mencoder进程转换结束后才可进行
			p.waitFor();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 从指定的视频文件(即可以是源视频文件,也可以是转换后的目标视频文件)中截图
	 * 
	 * @param ffmpegPath
	 *            ffmpeg.exe转换工具路径
	 * @param srcFilePath
	 *            源:用于指定要转换格式的文件,要截图的源视频文件路径
	 * @param mediaPicPath
	 *            截图保存路径
	 */
	private Boolean cutPic(String ffmpegPath, String srcFilePath,String mediaPicPath) {
		// 创建一个List集合来保存从视频中截取图片的命令
		List<String> cutpic = new ArrayList<String>();
		cutpic.add(ffmpegPath);
		cutpic.add("-i");
		cutpic.add(srcFilePath); // 同上(指定的文件即可以是转换为flv格式之前的文件,也可以是转换的flv文件)
		cutpic.add("-y");
		cutpic.add("-f");
		cutpic.add("image2");
		cutpic.add("-ss"); // 添加参数"-ss",该参数指定截取的起始时间
		cutpic.add("1"); // 添加起始时间为第11秒
		cutpic.add("-t"); // 添加参数"-t",该参数指定持续时间
		cutpic.add("0.001"); // 添加持续时间为1毫秒
		cutpic.add("-s"); // 添加参数"-s",该参数指定截取的图片大小
		cutpic.add("800*280"); // 添加截取的图片大小为350*240
		cutpic.add(mediaPicPath); // 添加截取的图片的保存路径

		boolean mark = true;
		ProcessBuilder builder = new ProcessBuilder();
		try {
			builder.command(cutpic);
			builder.redirectErrorStream(true);
			// 如果此属性为 true,则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并,
			// 因此两者均可使用 Process.getInputStream() 方法读取。这使得关联错误消息和相应的输出变得更容易
			builder.start();
		} catch (Exception e) {
			mark = false;
			System.out.println(e);
			e.printStackTrace();
		}
		return mark;
	}

	/**
	   * 删除转换后的目标视频文件
	   * @param tempFile  转换后的目标视频文件
	   */
	public void deleteAVIFile(String tempFile) {
		File file = new File(tempFile);
		if (file.exists()) {
			file.delete();
		}
	}

	/**
	 * 视频转码(mencoder.exe或ffmpeg.exe执行编码解码)
	 * 
	 * @param srcFilePath
	 *            源:用于指定要转换格式的文件,要截图的源视频文件路径
	 * @param codcFilePath
	 *            目标:视频格式转换后的的目标视频文件保存路径
	 * @param mediaPicPath
	 *            截图保存路径
	 * @return
	 */
	public boolean executeCodecs(String srcFilePath, String codcFilePath,String mediaPicPath) {
		String basePath = System.getProperty("user.dir");// 当前工程路径		
		String mencoderPath = "D:\\ffmpeg_mencoder_File\\Tools\\mencoder.exe";	
		String ffmpegPath = "D:\\ffmpeg_mencoder_File\\Tools\\ffmpeg.exe";// 转换工具路径
		boolean mark = true;
		String tempPath = basePath + File.separator + "temp" + File.separator + String.valueOf(System.currentTimeMillis()) + ".avi";		
		if (is_mencoderVideoType(srcFilePath)) {//判断是否可转换为AVI视频文件
			// mencoder.exe能解析并转换的源文件格式:(wmv9,rm,rmvb等)
			mark = this.convertToAVI(mencoderPath, srcFilePath, tempPath); 
			srcFilePath = tempPath;
		}
		if (is_ffmpegVideoType(srcFilePath) && mark) {//判断是否可转换为FLV视频文件
			// ffmpeg.exe能解析并转换的源文件格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
			mark = this.convertToFLV(ffmpegPath, srcFilePath, codcFilePath);
			mark = this.cutPic(ffmpegPath, srcFilePath, mediaPicPath);
		} else {
			System.out.println("该视频格式无法转换");
			mark = false;
		}
		this.deleteAVIFile(tempPath);
		return mark;
	}
}

CutPic.jsp

  <body>
    <img src="http://localhost:8081/virtualCutPicUrl/oneCutPic.jpg" alt="图片预览2" > <br><!--虚拟路径-->
  </body>

<!-- 备注
1.tomcat 下server.xml文件中需要配置

<HOST>

    <!--增加的下面这行中path="/虚拟名" docBase="虚拟路径,为本地物理路径" -->
    <Context path="/virtualCutPicUrl" docBase="D:\ffmpeg_mencoder_File\cutPicture\" reloadable="true"></Context>

</HOST>

2.CutPic.jsp文件中,格式为
<img src='http://ip+端口/虚拟路径/文件夹/文件名'>  
-->

<!--参考
 网站实现视频上传、转码、截图及在线播放功能https://blog.csdn.net/autumn20080101/article/details/51171442

-->

百度云链接链接:https://pan.baidu.com/s/1VB7IBX1MqHOqY991udMO-A 密码:5k7g

猜你喜欢

转载自blog.csdn.net/LaOngDaoxing/article/details/82222879