您的位置:首页 > 运维架构 > Linux

window下使用ffmpeg转换视频,linux安装和使用ffmpeg

2010-12-31 15:18 681 查看
最近做了一个项目,其中有一个需求是要将用户上传的视频转换成flv格式,使其能在网上进行观看。发现现在比较主流的视频转换工具是使用mencoder或者ffmpeg。于是开始研究ffmepg和mencoder了。发现貌似mencoder和ffmepg差不多吧。只是参数稍微不同,而且ffmepg的转换速度比mencoder快一点,但是mencoder比ffmepg支持的格式多一点(wmv9,rm,rmvb等)

下面是mencoder的参数:

-oac mp3lame:oac=output audio codec,输出音频编码器,这里用的mp3lame;

-lameopts abr:br=56:lame options,是专门针对mp3lame的参数设置,abr:br=56,是设置音

频比特率为56(比特率:每秒钟输出的音频大小,单位kb/s);

-ovc lavc:ovc=output video codec,输出视频编码器,lavc表示one of libavcodec’s

video codec,输出格式为libavformat之一,编码器当然也是libavcodec之一啦,至于

libavodec里都有哪些编码器,可以查看Mplayer的官方文档;

-lavcopts

vcodec=flv:vbitrate=500:mbd=2:mv0:v4mv:trell:cbp:last_pred=3:dia=4:cmp=6:vb_strategy

=1:对lavc进行一些设置,详细介绍如下:
vcodec=flv:指定视频编码器为flv;
vbitrate=500:指定视频比特率为500,这个参数很重要,vbitrate大了可以让视频品质增加,

但会让文件变的很大(可以参考flash8自带的转换工具的参数:低品质为150kb/s,中等品质为

400kb/s,高品质为700kb/s)。
mbd:宏模块选择算法,值为0~2默认为0,值越大转换越缓慢,但在品质和文件大小方面有好处


mv0:编译每个宏模块并选择最好的一个,当mbd=0时无效;
v4mv:会稍微增加品质,mbd>0时效果更明显;
trell:量子化网格搜索,对每8×8block找到最优化编码;
cbp:只能和trell一期使用,评估失真的图像块编码;
last_pred=3:与上一帧相比的移动数量预测,值为0~99,1~3比较合适,大于3时对品质的提

高已经无关紧要,但却会降低速度;
dia=4:移动搜索范围,值为-99~6,对于快速转换,-1是个不错的值,如果不是很重视速度,

可以考虑2~4;
cmp=6:值为1~2000,默认为0,设置用于全象素移动预算的比较函数
vb_strategy=1:对动作很大的场景会有帮助,对有些视频,设置vmax_b_frames会有损品质,加

上vb_strategy=1会好点。

以上是对-lavcopts的详细解释,接下来继续说明mencoder的参数:

-vf scale=512:-3:-vf表示视频格式,scale是缩放,512:-3表示强制将宽度设置为512,高度

写为-3表示保持高宽比,也可以设置为-1或-2,具体表示什么,有兴趣的可以尝试一下。如果要

强制转化为统一大小,可以直接写-vf scale=640:480,但笔者个人建议用-3来保持高宽比。-vf

里还有expand和crop参数,例如:-vf scale=512:384,expand=512:384:::1,crop=512:384:0:0

,expand表示膨胀,crop表示裁剪;

-ofps 12:输出视频的帧频,一般,用于flash播放的视频帧频高了没有没有意义,反而会增加

视频文件大小,但如果ofps设置的不合适,比如源视频帧频不是ofps的整数倍,可能会导致转换

后的视频、音频不同步,似乎可以将这一参数改为-noskip来解决这一问题;

-srate 22050:音频采样率一般为22050或44100。

首先,写了一个简单的批处理文件,看下转换效果
f://ffmpeg.exe -i e://test//111.mpg -ab 128 -acodec libmp3lame -ac 1 -ar 22050 -r

29.97 -b 512 -y e://test//zz.flv
这样转换的效果大小是小了,但是质量上不是很满意。
调整了几个参数
f://ffmpeg.exe -i e://test//111.mpg -ab 128 -acodec mp3 -ac 1 -qscale 8 -ar 22050 -b

1500 -r 29.97 -y e://test//zz.flv
这样转换的效果其实还可以的。我的111.mpg132MB转换成flv才30多MB,压缩的很厉害,质量上虽然不如原来的,但是还算可以的。没有那些马赛克之类的东西,而且速度还挺快的。
但是我当转换asf格式的视频时候,发现80MB的视频转成200多MB,质量还很差,速度更加慢的要死。(后面才了解asf是已经压缩过的,转换的时候要先解码,在转码,所以速度上变的慢。质量上边的比较模糊)经过几番调试,最终用了mencoder来转换asf,找到一个大小和质量都还过得去的平衡点
e://ffmpeg//mencoder.exe e://test//lesbian.asf -oac mp3lame -lameopts abr:br=56 -

srate 22050 -af channels=2 -ovc lavc -vf crop=1024:768:0:0 -lavcopts

vcodec=flv:vbitrate=300:mbd=2:trell:v4mv:turbo:keyint=45:dia=-1:cmp=3:vb_strategy=1

-ofps 12 -xvidencopts bitrate=440 -of lavf mp4 -o e://79.flv

ok,既然批处理文件可以转换了,那就写入java程序转换。网络上有一个转换的程序,写的很好的。直接拿过来用。(鲁迅大侠的拿来主义。。呵呵)
// 用java程序调用ffmpeg执行视频文件格式转换flv 收藏
//用java小例题说明更直观:(可以直接编译运行)
//环境我在windows平台下测试的。。。
//需要在e:/下有ffmpeg.exe;mencoder.exe;drv43260.dll;pncrt.dll共4个文件。
//如何得到这4个文件参考文章http://blog.sina.com.cn/u/4a424eca010005kb
//还要在e:/input下放各种文件名为a的以下各种视频文件;还要e:/output;java程序执行后能

得到一个a.flv的已转换的文件。
//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格

式的视频文件。。。
//
//java文件的内容如下:

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class ConvertVideo {

private final static String PATH = "e://test//[下载库www.xzk.cc]让子弹飞.rmvb";
public static void main(String[] args) {
if(!checkfile(PATH)){
System.out.println(PATH+" is not file");
return;
}
if (process()) {
System.out.println("ok");
}
}

private static boolean process() {
int type = checkContentType();
boolean status = false;
if (type==0) {
status = processFLV(PATH);// 直接将文件转为flv文件
} else if (type==1) {
String avifilepath = processAVI(type);
if (avifilepath == null)
return false;// avi文件没有得到
status = processFLV(avifilepath);// 将avi转为flv
}
return status;
}
private static int checkContentType() {
String type = PATH.substring(PATH.lastIndexOf(".") + 1,
PATH.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无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)

转换为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;
}

private static boolean checkfile(String path){
File file=new File(path);
if(!file.isFile()){
return false;
}
return true;
}
//  对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为

avi(ffmpeg能解析的)格式.
private static String processAVI(int type) {
List<String> commend=new java.util.ArrayList<String>();
commend.add("e://ffmpeg//mencoder");
commend.add(PATH);
//        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("-oac");
commend.add("mp3lame");
commend.add("-lameopts");
commend.add("preset=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("e://home//123.avi");

try{
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
doWaitFor(p);
p.destroy();
return "e://home//123.avi";
}catch(Exception e){
e.printStackTrace();
return null;
}
}
//  ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
private static boolean processFLV(String oldfilepath) {

if(!checkfile(PATH)){
System.out.println(oldfilepath+" is not file");
return false;
}

List<String> commend=new java.util.ArrayList<String>();
commend.add("e://ffmpeg//ffmpeg");
commend.add("-i");
commend.add(oldfilepath);
commend.add("-ab");
commend.add("128");
//        commend.add("-acodec");
//        commend.add("mp3");
commend.add("-ac");
commend.add("1");
commend.add("-qscale");
commend.add("8");
commend.add("-ar");
commend.add("22050");
commend.add("-b");
commend.add("1500");
commend.add("-r");
commend.add("29.97");
commend.add("-y");
commend.add("rrrmmmbb.flv");
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
doWaitFor(p);
p.destroy();
//     deleteFile(oldfilepath);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static int doWaitFor(Process p)

{
InputStream in = null;
InputStream err=null;
int exitValue = -1; // returned to caller when p is finished
try {
System.out.println("comeing");
in = p.getInputStream();
err = p.getErrorStream();
boolean finished = false; // Set to true when p is finished

while (!finished) {
try {
while (in.available() > 0) {
// Print the output of our system call
Character c = new Character((char) in.read());
System.out.print(c);
}
while (err.available() > 0) {
// Print the output of our system call
Character c = new Character((char) err.read());
System.out.print(c);
}

// Ask the process for its exitValue. If the process
// is not finished, an IllegalThreadStateException
// is thrown. If it is finished, we fall through and
// the variable finished is set to true.
exitValue = p.exitValue();
finished = true;

} catch (IllegalThreadStateException e) {
// Process is not finished yet;
// Sleep a little to save on CPU cycles
Thread.currentThread().sleep(500);
}
}
} catch (Exception e) {
// unexpected exception! print it out for debugging...
System.err.println("doWaitFor();: unexpected exception - "
+ e.getMessage());
} finally {
try {
if(in!=null)
{
in.close();
}

} catch (IOException e) {
System.out.println(e.getMessage());
}
if(err!=null)
{
try {
err.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
// return completion status to caller
return exitValue;
}

public static void deleteFile(String filepath) {
File file = new File(filepath);
if (PATH.equals(filepath)) {
if (file.delete()) {
System.out.println("文件" + filepath + "已删除");
}
} else {
if (file.delete()) {
System.out.println("文件" + filepath + "已删除 ");
}
File filedelete2 = new File(PATH);
if (filedelete2.delete()) {
System.out.println("文件" + PATH + "已删除");
}
}
}

}


试了一下,可以运行的。既然window已经行了的话,那么接下来就跑到linux下面去执行了,众所周知linux下面没有exe文件,所以就要先安装ffmpeg和mencoder。当初装的时候参照http://www.360doc.com/content/10/0917/13/474846_54350311.shtml这里的内容装,下了13文件,安装了N久,前面12个文件安装成功,最后在安装ffmpeg的时候,杯具发生了,安装失败,不知道是版本问题还是什么问题,我恨呐。。最后一步居然出这种错。最后才用yum命令安装的,什么文件都不用下,系统自动帮你下载安装的,而且不用担心什么版本问题。
一.下载rpm文件
rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
二. 安装 Install ffmpeg, mplayer, mencoder 等模块
yum -y install ffmpeg
安装好ffmpeg和mencoder,那么接下来把java文件放入linux下面运行。这时候又出现问题了:linux下面-acodec mp3 这个属性报错,这下不明白了,为什么这个参数报错呢,难道是linux下面不支持mp3格式的?但是换了几个值也不行。一气之下就把这个参数给注释掉(小样,跟哥嚣张,哥就不要你了。)这样一运行,发现运行结果也还不错。
好,行的话,那就先这样咯。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: