java简单封装ffmpeg

ffmpeg在C和C++下有直接可以使用的API,但是在JAVA上没找到很好用的开源包。

于是我对其进行了很简单的封装。实际上我是在基于操作系统命令行层面的封装,利用java的跨平台性,可以在windows和linux下使用。



基本上思想就是调用命令行的ffmpeg可执行文件,然后重定位输出,抓取分析输出内容来实现我们的需求。



/**
*
*/
package com.nvvideo.util;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.nvvideo.util.cmd.CmdExecuter;
import com.nvvideo.util.cmd.IStringGetter;

/**
* FFMpegUntil
* <p>Title: FFMpeg工具类</p>
* <p>Description: 本类封装FFMpeg对视频的操作</p>
* <p>Date: 2010-7-14</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: novel-supertv.com</p>
* @author chenggong
* @version 1.0
*/
public class FFMpegUtil implements IStringGetter{

private int runtime = 0;
private String ffmpegUri;//ffmpeg地址
private String originFileUri; //视频源文件地址
private enum FFMpegUtilStatus { Empty, CheckingFile, GettingRuntime };
private FFMpegUtilStatus status = FFMpegUtilStatus.Empty;

/**
* 构造函数
* @param ffmpegUri ffmpeg的全路径
* 如e:/ffmpeg/ffmpeg.exe 或 /root/ffmpeg/bin/ffmpeg
* @param originFileUri 所操作视频文件的全路径
* 如e:/upload/temp/test.wmv
*/
public FFMpegUtil( String ffmpegUri, String originFileUri ){
this.ffmpegUri = ffmpegUri;
this.originFileUri = originFileUri;
}

/**
* 获取视频时长
* @return
*/
public int getRuntime(){
runtime = 0;
status = FFMpegUtilStatus.GettingRuntime;
cmd.clear();
cmd.add(ffmpegUri);
cmd.add("-i");
cmd.add(originFileUri);
CmdExecuter.exec(cmd, this);
return runtime;
}

/**
* 检测文件是否是支持的格式
* 将检测视频文件本身,而不是扩展名
* @return
*/
public boolean isSupported(){
isSupported = true;
status = FFMpegUtilStatus.CheckingFile;
cmd.clear();
cmd.add(ffmpegUri);
cmd.add("-i");
cmd.add(originFileUri);
CmdExecuter.exec(cmd, this);
return isSupported;
}

private boolean isSupported;

/**
* 生成视频截图
* @param imageSavePath 截图文件保存全路径
* @param screenSize 截图大小 如640x480
*/
public void makeScreenCut( String imageSavePath , String screenSize ){
cmd.clear();
cmd.add(ffmpegUri);
cmd.add("-i");
cmd.add(originFileUri);
cmd.add("-y");
cmd.add("-f");
cmd.add("image2");
cmd.add("-ss");
cmd.add("8");
cmd.add("-t");
cmd.add("0.001");
cmd.add("-s");
cmd.add(screenSize);
cmd.add(imageSavePath);
CmdExecuter.exec(cmd, null);
}

/**
* 视频转换
* @param fileSavePath 文件保存全路径(包括扩展名)如 e:/abc/test.flv
* @param screenSize 视频分辨率 如640x480
* @param audioByte 音频比特率
* @param audioCollection 音频采样率
* @param quality 视频质量(0.01-255)越低质量越好
* @param fps 每秒帧数(15或29.97)
*/
public void videoTransfer(
String fileSavePath,
String screenSize,
int audioByte,
int audioCollection,
double quality,
double fps ){
cmd.clear();
cmd.add(ffmpegUri);
cmd.add("-i");
cmd.add(originFileUri);
cmd.add("-y");
cmd.add("-ab");
cmd.add( Integer.toString(audioByte) );
cmd.add("-ar");
cmd.add( Integer.toString(audioCollection) );
cmd.add("-qscale");
cmd.add( Double.toString(quality) );
cmd.add("-r");
cmd.add( Double.toString(fps) );
cmd.add("-s");
cmd.add(screenSize);
cmd.add( fileSavePath );
CmdExecuter.exec(cmd, null);
}

private List<String> cmd = new ArrayList<String>();

@Override
public void dealString( String str ){

switch( status )
{
case Empty:
break;
case CheckingFile:{
Matcher m = Pattern.compile("Unknown format").matcher(str);
if( m.find() )
this.isSupported = false;
break;
}
case GettingRuntime:{
Matcher m = Pattern.compile("Duration: \\w+:\\w+:\\w+").matcher(str);
while (m.find())
{
String msg = m.group();
msg = msg.replace("Duration: ", "");
runtime = TimeUtil.runtimeToSecond(msg);
}
break;
}
}//switch
}
}




用到另外封装的一个命令行执行器




/**
*
*/
package com.nvvideo.util.cmd;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;


/**
* CmdExecuter
* <p>Title: 命令执行器</p>
* <p>Description: 封装对操作系统命令行发送指令相关操作</p>
* <p>Date: 2010-7-14</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: novel-supertv.com</p>
* @author chenggong
* @version 1.0
*/
public class CmdExecuter {

/**
* 执行指令
* @param cmd 执行指令
* @param getter 指令返回处理接口,若为null则不处理输出
*/
static public void exec( List<String> cmd, IStringGetter getter ){
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(cmd);
builder.redirectErrorStream(true);
Process proc = builder.start();
BufferedReader stdout = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = stdout.readLine()) != null) {
if( getter != null )
getter.dealString(line);
}
proc.waitFor();
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}




当做回调函数的接口(JAVA没有回调,没有委托……只会用接口)


/**
*
*/
package com.nvvideo.util.cmd;

/**
* IStringGetter
* <p>Title: 字符串接收者接口</p>
* <p>Description: </p>
* <p>Date: 2010-7-14</p>
* <p>Copyright: Copyright (c) 2010</p>
* <p>Company: novel-supertv.com</p>
* @author chenggong
* @version 1.0
*/
public interface IStringGetter {
/**
* 处理字符串
* @param str
*/
public void dealString( String str );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值