[地球人]都知道,ffmpeg可以用來生成一圖流視頻,但是,一個很禿的一點是,ffmpeg生成視頻需要手動輸入視頻時間.然後如果單純的用bat執行的話沒法獲得音頻的時間,所以我就傻了.
無奈於是只好考慮寫一個程序解決掉.[地球人]都知道.java裏面可以用Rumtime.getRuntime.exec("cmd /c "+command)來執行cmd命令,所以問題的關鍵就是,如何獲取要處理的音頻的長度.
一開始,我準備用javax.sound.sample.AudioFileFormat來獲取音頻的時間長度,結果後來很快發現,AudioFileFormat竟然連mp3格式都不支持,於是我就傻了
要 處理mp3格式還需要額外安置解碼器,出於節省cpu消耗的考慮我最後果斷放棄了AudioFileFormat,轉而考慮mediainfo.一開始我 考慮的是運行mediainfo.exe,獲取其stderr,并進行字符串處理獲取時間長度.不過很禿的是我懶得寫字符串處理,於是我最後決定使用 mediainfo.dll,藉助mediainfo直接獲取音頻長度.
[地球人]都知道,java要使用dll需要JNI,或者 JNative.爲了方便,於是我選用的JNative.mediainfo在其dll的下載包中附帶了一個 MediaInfoDLL.JNative.java,作為java調用mediainfo的API.有了這個,程序就好寫多了.獲取音頻長度之後運行 ffmpeg,程序的主體就完成了.
最後再加點細節,程序最後就完工了
package JMake; import java.io.*; import java.util.*; import java.util.regex.*; import javax.sound.sampled.*; import org.xvolks.jnative.*; import org.xvolks.jnative.exceptions.*; import org.xvolks.jnative.pointers.*; import JMake.*; public class JMake{ static MediaInfo mediainfo; static int find(String args[],String s){ if(args==null) return -1; if(s==null) return -1; for(int i=0;i<args.length;i++) if(s.compareTo(args[i])==0) return i; return -1; } static ArrayList getPatternFiles(File file,Pattern p,boolean subDir){ if(file==null) return null; if(file.isFile()){ Matcher fMatcher=p.matcher(file.getName()); if(fMatcher.matches()){ ArrayList list=new ArrayList(); list.add(file); return list; } } if(file.isDirectory()){ File[] files=file.listFiles(); if((files!=null)&&(files.length>0)){ ArrayList list=new ArrayList(); for(int i=0;i<files.length;i++){ if(files[i].isDirectory()&&(!subDir)) continue; ArrayList tmp=getPatternFiles(files[i],p,subDir); if(tmp!=null) list.addAll(tmp); } return list; } } return null; } static File[] getFiles(String dir,String s,boolean subDir){ File file=new File(dir); s=s.replace('.','#'); s=s.replaceAll("#", "\\\\."); s=s.replace('*','#'); s=s.replaceAll("#",".*"); s=s.replace('?','#'); s=s.replaceAll("#",".?"); s="^"+s+"$"; Pattern p=Pattern.compile(s); ArrayList files=getPatternFiles(file,p,subDir); File[] ret=new File[files.size()]; files.toArray(ret); return ret; } static void runCommand(Runtime run,String s)throws Exception{ Process process=run.exec("cmd /c "+s); Scanner in=new Scanner(process.getErrorStream()); for(;in.hasNext();System.out.println(in.nextLine())); in.close(); process.waitFor(); return; } static void generateFLV(String pic,String audio)throws Exception{ long len=0; mediainfo.Open(audio); mediainfo.Option("Complete","0"); String len1=mediainfo.Get(MediaInfo.Stream_General,0,"Duration",MediaInfo.Info_Text,MediaInfo.Info_Name); len=(long)(Math.floor((Long.parseLong(len1)/1000)))+1; StringBuffer command1=new StringBuffer("ffmpeg "); command1.append("-loop_input -r 1 -t "+Long.toString(len)+" "); command1.append("-i \""+pic+"\" "); command1.append("-vcodec libx264 "); command1.append("-crf 24 -coder 1 -flags +loop -cmp +chroma "); command1.append("-partitions +parti8x8+parti4x4+partp8x8+partb8x8 -me_method umh -subq 7 -me_range 16 "); command1.append("-g 250 -keyint_min 1 -sc_threshold 40 -b_strategy 2 -bf 0 -refs 6 "); command1.append("-qcomp 0.6 -qdiff 4 "); command1.append("-directpred 3 -trellis 2 -flags2 +wpred+mixed_refs+dct8x8+fastpskip "); command1.append("-y -f mp4 \""+audio+".mp4\""); StringBuffer command2=new StringBuffer("ffmpeg "); command2.append("-vcodec copy -i \""+audio+".mp4\" "); command2.append("-acodec copy -i \""+audio+"\" "); command2.append("-y -f flv \""+audio+".flv\""); System.out.println(command1); System.out.println(command2); Runtime run=Runtime.getRuntime(); runCommand(run,command1.toString()); runCommand(run,command2.toString()); return; } public static void main(String args[])throws Exception{ int picPattern=find(args,"--pic")+1; if(picPattern==0) return; int audioPattern=find(args,"--audio")+1; if(audioPattern==0) return; boolean subPicDir=(find(args,"--sub-pic-dir")+1!=0); boolean subAudioDir=(find(args,"--sub-audio-dir")+1!=0); File tmpPic=new File(args[picPattern]); File[] pics=getFiles(tmpPic.getParent(),tmpPic.getName(),subPicDir); File tmpAudio=new File(args[audioPattern]); File[] audios=getFiles(tmpAudio.getParent(),tmpAudio.getName(),subAudioDir); String dllPath="MediaInfo.dll"; mediainfo=new MediaInfo(dllPath); for(int i=0;i<Math.min(pics.length,audios.length);i++) generateFLV(pics[i].getPath(),audios[i].getPath()); if(pics.length<audios.length) for(int i=pics.length;i<audios.length;i++) generateFLV(pics[pics.length-1].getPath(),audios[i].getPath()); if(pics.length>audios.length) for(int i=audios.length;i<pics.length;i++) generateFLV(pics[i].getPath(),audios[audios.length-1].getPath()); return; } }