- author:fanfq(xiaoban)
Email:fangqing.fan#gmail.com
link:http://fanfq.iteye.com/admin/blogs/655569
changelog:
有很多朋友發郵件問我關於ffmpeg視頻轉碼的相關問題,我也嘗試了幫助他們去解決這些問題,由於個人精力有限就blog上總結一下大家所遇到的一些問題。
以下代碼只要是使用的我的包是肯定沒有問題的,但是至限於*-》flv,因為不同格式的視頻轉碼所對應的參數也是不一樣的,想要達到效果教好的視頻的話就得修改這些參數,但是我們有一個通用的方式,只要是ffmpeg支持的視頻的話。使用 ffmpeg -i form.** to.** 就可以了,但是這只局限與測試。
windows環境測試
一.磨刀不誤砍柴工
1.ffmpeg下載地址:https://ffmpeg.zeranoe.com/builds/,下載解壓如下圖所示:
在C:盤下創建一個文件夾C:\ffmpeg\,然后將上面截圖的內容復制進去。
ffmpeg.exe能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
對ffmpeg.exe無法解析的文件格式(wmv9,rm,rmvb等),
可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式;
mencoder.exe;drv43260.dll;pncrt.dll這3個文件是為文件格式(wmv9,rm,rmvb等)
轉換為avi(ffmpeg能解析的)格式准備的;再把轉換好的avi文件再用ffmpeg.exe轉換成flv格式的視頻文件。。。
視頻格式轉換:
-
1 import java.io.File; 2 import java.util.ArrayList; 3 import java.util.Calendar; 4 import java.util.List; 5 6 public class Test { 7 private final static String PATH = "c:\\ffmpeg\\input\\c.mp4"; 8 9 public static void main(String[] args) { 10 if (!checkfile(PATH)) { 11 System.out.println(PATH + " is not file"); 12 return; 13 } 14 if (process()) { 15 System.out.println("ok"); 16 } 17 } 18 19 private static boolean process() { 20 int type = checkContentType(); 21 boolean status = false; 22 if (type == 0) { 23 System.out.println("直接將文件轉為flv文件"); 24 status = processFLV(PATH);// 直接將文件轉為flv文件 25 } else if (type == 1) { 26 String avifilepath = processAVI(type); 27 if (avifilepath == null) 28 return false;// avi文件沒有得到 29 status = processFLV(avifilepath);// 將avi轉為flv 30 } 31 return status; 32 } 33 34 private static int checkContentType() { 35 String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length()).toLowerCase(); 36 // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) 37 if (type.equals("avi")) { 38 return 0; 39 } else if (type.equals("mpg")) { 40 return 0; 41 } else if (type.equals("wmv")) { 42 return 0; 43 } else if (type.equals("3gp")) { 44 return 0; 45 } else if (type.equals("mov")) { 46 return 0; 47 } else if (type.equals("mp4")) { 48 return 0; 49 } else if (type.equals("asf")) { 50 return 0; 51 } else if (type.equals("asx")) { 52 return 0; 53 } else if (type.equals("flv")) { 54 return 0; 55 } 56 // 對ffmpeg無法解析的文件格式(wmv9,rm,rmvb等), 57 // 可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式. 58 else if (type.equals("wmv9")) { 59 return 1; 60 } else if (type.equals("rm")) { 61 return 1; 62 } else if (type.equals("rmvb")) { 63 return 1; 64 } 65 return 9; 66 } 67 68 private static boolean checkfile(String path) { 69 File file = new File(path); 70 if (!file.isFile()) { 71 return false; 72 } 73 return true; 74 } 75 76 // 對ffmpeg無法解析的文件格式(wmv9,rm,rmvb等), 可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式. 77 private static String processAVI(int type) { 78 List<String> commend = new ArrayList<String>(); 79 commend.add("c:\\ffmpeg\\mencoder"); 80 commend.add(PATH); 81 commend.add("-oac"); 82 commend.add("lavc"); 83 commend.add("-lavcopts"); 84 commend.add("acodec=mp3:abitrate=64"); 85 commend.add("-ovc"); 86 commend.add("xvid"); 87 commend.add("-xvidencopts"); 88 commend.add("bitrate=600"); 89 commend.add("-of"); 90 commend.add("avi"); 91 commend.add("-o"); 92 commend.add("c:\\ffmpeg\\output\\a.avi"); 93 try { 94 ProcessBuilder builder = new ProcessBuilder(); 95 builder.command(commend); 96 builder.start(); 97 return "c:\\ffmpeg\\output\\a.avi"; 98 } catch (Exception e) { 99 e.printStackTrace(); 100 return null; 101 } 102 } 103 104 // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) 105 private static boolean processFLV(String oldfilepath) { 106 if (!checkfile(PATH)) { 107 System.out.println(oldfilepath + " is not file"); 108 return false; 109 } 110 // 文件命名 111 Calendar c = Calendar.getInstance(); 112 String savename = String.valueOf(c.getTimeInMillis()) + Math.round(Math.random() * 100000); 113 List<String> commend = new ArrayList<String>(); 114 commend.add("c:\\ffmpeg\\ffmpeg"); 115 commend.add("-i"); 116 commend.add(oldfilepath); 117 commend.add("-ab"); 118 commend.add("56"); 119 commend.add("-ar"); 120 commend.add("22050"); 121 commend.add("-qscale"); 122 commend.add("8"); 123 commend.add("-r"); 124 commend.add("15"); 125 commend.add("-s"); 126 commend.add("600x500"); 127 commend.add("c:\\ffmpeg\\output\\a.flv"); 128 try { 129 Runtime runtime = Runtime.getRuntime(); 130 Process proce = null; 131 String cmd = ""; 132 String cut = " c:\\ffmpeg\\ffmpeg.exe -i " + oldfilepath 133 + " -y -f image2 -ss 8 -t 0.001 -s 600x500 c:\\ffmpeg\\output\\" + "a.jpg"; 134 String cutCmd = cmd + cut; 135 proce = runtime.exec(cutCmd); 136 ProcessBuilder builder = new ProcessBuilder(commend); 137 builder.command(commend); 138 builder.start(); 139 return true; 140 } catch (Exception e) { 141 e.printStackTrace(); 142 return false; 143 } 144 } 145 }
視頻截圖:
import java.io.IOException; import java.io.InputStream; import java.util.List; public class Ffmpeg { public static void main(String[] args) { // 視頻文件 String videoRealPath = "E:\\Eclipse2\\a.avi"; // 截圖的路徑(輸出路徑) String imageRealPath = "E:\\Eclipse2\\atest.jpg"; // 方法一:調用批處理程序,調用批處理文件ffmpeg.bat轉換視頻格式 // try { // //調用批處理文件 // Runtime.getRuntime().exec("cmd /c start // C:\\Users\\Administrator\\Desktop\\test\\ffmpeg.bat " + videoRealPath // + " " + imageRealPath); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // 方法二:通過命令提示符來調用需要添加系統路徑(Path),調用menconder轉換視頻各種 // commendF // .add("cmd.exe /c mencoder E:\\Eclipse2\\test.flv -o // e:\\Eclipse2\\test.avi // -oac mp3lame -lameopts cbr:br=32 // -ovc x264 -x264encopts bitrate=440 -vf scale=448:-3"); // 方法三:調用系統中的可執行程序調用ffmpeg 提取視屏縮略圖 List<String> commend = new java.util.ArrayList<String>(); commend.add("E:\\Eclipse2\\Mplayer\\ffmpeg-git-4082198-win32-static\\bin\\ffmpeg.exe"); commend.add("-i"); commend.add(videoRealPath); commend.add("-y"); commend.add("-f"); commend.add("image2"); commend.add("-ss"); commend.add("8"); commend.add("-t"); commend.add("0.001"); commend.add("-s"); commend.add(imageRealPath); try { ProcessBuilder builder = new ProcessBuilder(); builder.command(commend); builder.redirectErrorStream(true); System.out.println("視頻截圖開始..."); // builder.start(); Process process = builder.start(); InputStream in = process.getInputStream(); byte[] re = new byte[1024]; System.out.print("正在進行截圖,請稍候"); while (in.read(re) != -1) { System.out.print("."); } System.out.println(""); in.close(); System.out.println("視頻截圖完成..."); } catch (Exception e) { e.printStackTrace(); System.out.println("視頻截圖失敗!"); } } }