java调用ffmpeg实现转换视频
最近由于项目需要把不同格式的视频转换为ts流,故研究了一下ffmpeg。在网上找了很多资料,主要参考了Java+Windows+ffmpeg实现视频转换功能。
期间也加了几个qq群,咨询了各大高手,其中在代码中关于ffmpeg的命令就是来自其中一个qq群里面的大神。
下载相关文件
ffmpeg地址,我下载是windows64位static版本。
xuggler下载地址
下面的代码我上传到了github,需要的可以下载下来看看。
步骤:
1.研究java如何调用外部程序
2.研究ffmpeg转换视频格式的命令
3.利用xuggle获取ffmpeg解析的ts流的时长、分辨率以及文件大小。
下面直接上代码:
1.ffmpeg转换实现
packagevedio.ffmpeg; importjava.io.File; importjava.util.ArrayList; importjava.util.List; publicclassFfmpegUtil{ publicstaticBooleanffmpeg(StringffmpegPath,StringinputPath,StringoutputPath)throwsFFmpegException{ if(!checkfile(inputPath)){ thrownewFFmpegException("文件格式不合法"); } inttype=checkContentType(inputPath); Listcommand=getFfmpegCommand(type,ffmpegPath,inputPath,outputPath); if(null!=command&&command.size()>0){ returnprocess(command); } returnfalse; } privatestaticintcheckContentType(StringinputPath){ Stringtype=inputPath.substring(inputPath.lastIndexOf(".")+1,inputPath.length()).toLowerCase(); //ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) if(type.equals("avi")){ return1; }elseif(type.equals("mpg")){ return1; }elseif(type.equals("wmv")){ return1; }elseif(type.equals("3gp")){ return1; }elseif(type.equals("mov")){ return1; }elseif(type.equals("mp4")){ return1; }elseif(type.equals("mkv")){ return1; }elseif(type.equals("asf")){ return0; }elseif(type.equals("flv")){ return0; }elseif(type.equals("rm")){ return0; }elseif(type.equals("rmvb")){ return1; } return9; } privatestaticbooleancheckfile(Stringpath){ Filefile=newFile(path); if(!file.isFile()){ returnfalse; } returntrue; } privatestaticbooleanprocess(Listcommand)throwsFFmpegException{ try{ if(null==command||command.size()==0) returnfalse; ProcessvideoProcess=newProcessBuilder(command).redirectErrorStream(true).start(); newPrintStream(videoProcess.getErrorStream()).start(); newPrintStream(videoProcess.getInputStream()).start(); intexitcode=videoProcess.waitFor(); if(exitcode==1){ returnfalse; } returntrue; }catch(Exceptione){ thrownewFFmpegException("fileuploadfailed",e); } } privatestaticListgetFfmpegCommand(inttype,StringffmpegPath,Stringoldfilepath,StringoutputPath)throwsFFmpegException{ Listcommand=newArrayList(); if(type==1){ command.add(ffmpegPath+"\\ffmpeg"); command.add("-i"); command.add(oldfilepath); command.add("-c:v"); command.add("libx264"); command.add("-x264opts"); command.add("force-cfr=1"); command.add("-c:a"); command.add("mp2"); command.add("-b:a"); command.add("256k"); command.add("-vsync"); command.add("cfr"); command.add("-f"); command.add("mpegts"); command.add(outputPath); }elseif(type==0){ command.add(ffmpegPath+"\\ffmpeg"); command.add("-i"); command.add(oldfilepath); command.add("-c:v"); command.add("libx264"); command.add("-x264opts"); command.add("force-cfr=1"); command.add("-vsync"); command.add("cfr"); command.add("-vf"); command.add("idet,yadif=deint=interlaced"); command.add("-filter_complex"); command.add("aresample=async=1000"); command.add("-c:a"); command.add("libmp3lame"); command.add("-b:a"); command.add("192k"); command.add("-pix_fmt"); command.add("yuv420p"); command.add("-f"); command.add("mpegts"); command.add(outputPath); }else{ thrownewFFmpegException("不支持当前上传的文件格式"); } returncommand; } } classPrintStreamextendsThread{ java.io.InputStream__is=null; publicPrintStream(java.io.InputStreamis){ __is=is; } publicvoidrun(){ try{ while(this!=null){ int_ch=__is.read(); if(_ch==-1){ break; }else{ System.out.print((char)_ch); } } }catch(Exceptione){ e.printStackTrace(); } } }
2.调用测试类
packagevedio.ffmpeg; publicclassConvertVedio{ publicstaticvoidconvertVedio(StringinputPath){ StringffmpegPath=getFfmpegPath(); StringoutputPath=getOutputPath(inputPath); try{ FfmpegUtil.ffmpeg(ffmpegPath,inputPath,outputPath); }catch(FFmpegExceptione){ e.printStackTrace(); } } privatestaticStringgetFfmpegPath(){ return"ffmpeg"; } privatestaticStringgetOutputPath(StringinputPath){ returninputPath.substring(0,inputPath.lastIndexOf(".")).toLowerCase()+".ts"; } }
3.自定义的异常类
packagevedio.ffmpeg; publicclassFFmpegExceptionextendsException{ privatestaticfinallongserialVersionUID=1L; publicFFmpegException(){ super(); } publicFFmpegException(Stringmessage){ super(message); } publicFFmpegException(Throwablecause){ super(cause); } publicFFmpegException(Stringmessage,Throwablecause){ super(message,cause); } }
4.获取ts流的时长、大小以及分辨率(用到了Xuggle,需要下载对应jar包)
importcom.xuggle.xuggler.ICodec; importcom.xuggle.xuggler.IContainer; importcom.xuggle.xuggler.IStream; importcom.xuggle.xuggler.IStreamCoder; */ publicstaticvoidgetVedioInfo(Stringfilename){ //firstwecreateaXugglercontainerobject IContainercontainer=IContainer.make(); //weattempttoopenupthecontainer intresult=container.open(filename,IContainer.Type.READ,null); //checkiftheoperationwassuccessful if(result<0) return; //queryhowmanystreamsthecalltoopenfound intnumStreams=container.getNumStreams(); //queryforthetotalduration longduration=container.getDuration(); //queryforthefilesize longfileSize=container.getFileSize(); longsecondDuration=duration/1000000; System.out.println("时长:"+secondDuration+"秒"); System.out.println("文件大小:"+fileSize+"M"); for(inti=0;i IStreamstream=container.getStream(i); IStreamCodercoder=stream.getStreamCoder(); if(coder.getCodecType()==ICodec.Type.CODEC_TYPE_VIDEO){ System.out.println("视频宽度:"+coder.getWidth()); System.out.println("视频高度:"+coder.getHeight()); } } }
以上就是在开发过程中做的全部,希望大家多多学习,交流!