ffmpeg转码、截图、截取视频

来源:互联网 发布:服装行业利润知乎 编辑:程序博客网 时间:2024/05/11 17:05

终于初步把java上传视频后,调用ffmpeg处理视频完成的差不多了,困扰我的主要有两个问题,第一个是:怎么控制转码之后再进行截取视频,第二个是:进程以及线程的处理问题。目前都已解决,以下均是大白话,资深人士莫要笑话。ffmpeg.exe链接:http://download.csdn.net/detail/jiaxiaoteng/8175987,源代码链接:http://download.csdn.net/detail/jiaxiaoteng/8175787,源代码要了一分,实在是穷呐,大家莫怪啊,下载后直接用MyEclipse导入运行即可。好了,废话不多说了,直接贴代码开搞:

java上传视频:(这个没啥说的,就是最简单的上传,上传完之后调用视频处理类)

package dealwithVideo;
import java.io.File;
import java.io.IOException;
import java.util.*;




import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 * 
 * @author jxt
 * 
 * @date 2011-2014-10-10
 * 
 */
public class FileUploadServlet extends HttpServlet {


private static final long serialVersionUID = -7744625344830285257L;
// private ServletContext sc;
// private String savePath;


public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}




public void init(ServletConfig config) {
// 在web.xml中设置的一个初始化参数
// savePath = config.getInitParameter("savePath");
// sc = config.getServletContext();
}


public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
@SuppressWarnings("rawtypes")
List items;
FileItem item =null;
try {
items = upload.parseRequest(request);
@SuppressWarnings("rawtypes")
Iterator itr = items.iterator();
while (itr.hasNext()) {
item = (FileItem) itr.next();
if (item.isFormField()) {
// System.out.println("表单参数名:" + item.getFieldName() + ",表单参数值:" + item.getString("UTF-8"));
} else {
if (item.getName() != null && !item.getName().equals("")) {
// System.out.println("上传文件的大小:" + item.getSize());
// System.out.println("上传文件的类型:" + item.getContentType());
// // item.getName()返回上传文件在客户端的完整路径名称
// System.out.println("上传文件的名称:" + item.getName());


File tempFile = new File(item.getName());

//上传文件的保存路径
// String wholePath=sc.getRealPath("\\") + savePath+"\\";
String wholePath = "e:\\ffmpeg\\";
String wholeFilename = tempFile.getName();

File file = new File(wholePath, wholeFilename);
System.out.println("开始上传");
item.write(file);
System.out.println("上传完成\t文件上传到---"+wholePath+wholeFilename);

ConvertVideo cv = new ConvertVideo();
cv.dealVideo(wholePath, tempFile.getName());
request.setAttribute("upload.message", "OK");
}else{
request.setAttribute("upload.message", "没有选择上传文件!");
}
}
}

}catch(FileUploadException e){
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("upload.message", "Excel文件错误,上传文件失败!");
}
request.getRequestDispatcher("/uploadResult.jsp").forward(request, response);
}
}


ConvertVideo视频处理类:(这个类中我想说的有两点,第一个是new PrintStream()的作用:在调用ffmpeg转码时,会不停的往inputstream和errorstream中写数据,如果不及时读取,jvm内存满了,就会导致写不进去,进程全面堵车,死掉------(进程堵塞)。第二个是waitfor(),这个方法作用是当前进程完成(返回)后,在进行其他进程------(进程等待))

package dealwithVideo;
import java.io.File;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;
import java.util.regex.Pattern;


public class ConvertVideo {  


// private final static String PATH = "F:\\ffmpeg\\1.mp4";  
//处理视频
public void dealVideo(String wholePath,String filename) {  
String videoPath = wholePath+filename;//视频路径+视频名称
if (!checkfile(videoPath)) {  //检查视频是否存在
System.out.println(videoPath + " is not file");  
return;  

if (process(wholePath,filename)) {  
System.out.println("转码并截图完成");  
}  
//截取视频
String filenameBef = filename.substring(0, filename.length()-4);
System.out.println("开始截取视频");
String cutVideosStatus = new CutVideo().cutVideos(wholePath,filenameBef);
System.out.println(cutVideosStatus);
}  
//检查视频是否存在
private static boolean checkfile(String path) {  
File file = new File(path);  
if (!file.isFile()) {  
return false;  
}  
return true;  
}  
//转码并截图
private static boolean process(String wholePath,String filename) {
int type = checkContentType(filename); //查看视频类型
if(type==0){//如果不是flv,则转码为flv并获取缩略图
System.out.println("视频格式不是flv,进行转码....");
return processFLV(wholePath,filename);// 将其他格式转为flv 
}
else{
System.out.println("视频格式是flv,开始截图....");
return getPic(wholePath,filename);//如果是flv格式则直接获取缩略图
}

}  
//查看视频类型 type=0为其他类型,9为flv
private static int checkContentType(String filename) {  
String type = filename.substring(filename.length()-3,filename.length());
System.out.println("查看视频类型:"+type);
// 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;  
}   
return 9;  
}




private static boolean getPic(String wholePath,String filename){
String filenameBef = filename.substring(0, filename.length()-4);
//截取缩略图
List<String> commend1 = new ArrayList<String>();  
commend1.add("F:\\ffmpeg\\ffmpeg.exe");  
commend1.add("-i");  
commend1.add(wholePath+filename);  
commend1.add("-y");
// commend1.add("-f");  
commend1.add("image2");  
commend1.add("-ss");  
commend1.add("8");  
commend1.add("-s");  
commend1.add("600x500");  
commend1.add("f:\\ffmpeg\\"+filenameBef+".jpg");  
// System.out.println(commend1);

try {  
Runtime runtime = Runtime.getRuntime();  
       Process proce = null;
String ffmpegStr = "E:\\ffmpeg\\ffmpeg.exe -i "+wholePath+filename+"  -f image2 " +
"-ss  5 -s 600*500 " +
  "e:\\ffmpeg\\"+filenameBef+".jpg";
proce = runtime.exec(ffmpegStr);
        
//获取视频总时长
Scanner sc = new Scanner(proce.getErrorStream());
       // Find duration
       Pattern durPattern = Pattern.compile("(?<=Duration: )[^,]*");
       String dur = sc.findWithinHorizon(durPattern, 0);
       if (dur == null)
         throw new RuntimeException("Could not parse duration.");
       String[] hms = dur.split(":");
       double totalSecs = Integer.parseInt(hms[0]) * 3600
                        + Integer.parseInt(hms[1]) *   60
                        + Double.parseDouble(hms[2]);
       System.out.println("视频总时长: " + totalSecs + "秒");
       new PrintStream(proce.getErrorStream()).start();
       new PrintStream(proce.getInputStream()).start();
       proce.waitFor();
return true;  
} catch (Exception e) {  
e.printStackTrace();  
return false;  
}  

}


// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
private static boolean processFLV(String wholePath,String filename) {  


if (!checkfile(wholePath+filename)) {  
System.out.println(wholePath+filename+ " is not file");  
return false;  
}  
String filenameBef = filename.substring(0, filename.length()-4);
// 文件命名  
// Calendar c = Calendar.getInstance();  
// String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);  
//转化视频
List<String> commend = new ArrayList<String>();  
commend.add("E:\\ffmpeg\\ffmpeg.exe");  
commend.add("-i");  
commend.add(wholePath+filename);  
commend.add("-b");  
commend.add("512");
commend.add("-ab");  
commend.add("128");  
commend.add("-ar");  
commend.add("44100");  
commend.add("-qscale");  
commend.add("8");  
commend.add("-r");  
commend.add("25");  
// commend.add("-s");  
// commend.add("600x500"); 
commend.add("-aspect");  
commend.add("4:3"); 
commend.add("e:\\ffmpeg\\"+filenameBef+".flv"); 
try {  
Runtime runtime = Runtime.getRuntime();  
Process proce = null;  
            String cmd = "";  
            String cut = "     e:\\ffmpeg\\ffmpeg.exe   -i   "  
                    +   wholePath+filename
                    + "      -f   image2   -ss   5   -s   600x480   e:\\ffmpeg\\"  
                    + filenameBef+".jpg";  
            String cutCmd = cmd + cut;  
            proce = runtime.exec(cutCmd);
            
//            ProcessBuilder builder = new ProcessBuilder(commend);  
//             builder.command(commend);  
//            builder.start(); 
            Process videoProcess = new ProcessBuilder(commend).start();
            new PrintStream(videoProcess.getErrorStream()).start();
            new PrintStream(videoProcess.getInputStream()).start();
          //获取视频总时长
Scanner sc = new Scanner(proce.getErrorStream());
       // Find duration
       Pattern durPattern = Pattern.compile("(?<=Duration: )[^,]*");
       String dur = sc.findWithinHorizon(durPattern, 0);
       if (dur == null)
         throw new RuntimeException("Could not parse duration.");
       String[] hms = dur.split(":");
       double totalSecs = Integer.parseInt(hms[0]) * 3600
                        + Integer.parseInt(hms[1]) *   60
                        + Double.parseDouble(hms[2]);
       System.out.println("视频总时长: " + totalSecs + "秒");
       videoProcess.waitFor();
return true;  
} catch (Exception e) {  
e.printStackTrace();  
return false;  
}  

}  
}  

视频截取类

package dealwithVideo;


public class CutVideo {
public String cutVideos(String wholePath,String filename){


// String filenameBef = filename.substring(0, filename.length()-4);
try {  
Runtime runtime = Runtime.getRuntime();  
Process proce = null;
String ffmpegStr = "E:\\ffmpeg\\ffmpeg.exe -ss 00:00:00 -i "+wholePath+filename+".flv " +
" -acodec copy -vcodec copy -t 00:00:10 " +
wholePath+filename+"-jiequ.flv";
proce = runtime.exec(ffmpegStr);
new PrintStream(proce.getErrorStream()).start();
new PrintStream(proce.getInputStream()).start();
proce.waitFor();
return "视频截取成功,截取时长为10秒";  
} catch (Exception e) {  
e.printStackTrace();  
return "视频截取失败";  
}  


}
}

PrintStream类

package dealwithVideo;


import java.io.InputStream;


public class PrintStream extends Thread{
InputStream ism = null;
public PrintStream(InputStream is){
ism = is;
}
public void run(){
try{
while(this != null){
int ch = ism.read();
if(ch!=-1){
System.out.print((char)ch);
}else{
break;
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}

还有一个小问题,就是在上传的时候,点了提交按钮,直到视频处理完后才会跳转,这个好解决,在jsp页面引用jQuery-from.js,java上传类中上传完成后先不要调用视频处理类,在前台判断上传完成后再由前台ajax调用视频处理类,即可达到上传完成立马页面跳转,后台开始处理视频。

0 0
原创粉丝点击