packagecom.octopus;importjava.awt.FlowLayout;importjava.awt.Font;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.io.File;importjava.io.IOException;importjava.io.InputStream;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;importjava.util.Timer;importjava.util.TimerTask;importjavax.swing.JButton;importjavax.swing.JFileChooser;importjavax.swing.JFrame;importjavax.swing.JLabel;importjavax.swing.JOptionPane;importjavax.swing.JScrollPane;importjavax.swing.JTextArea;importjavax.swing.JTextField;/*** 利用FFmpeg实现视频格式批量转化的工具
*
*@authorhw
**/
public classFfmpegConvertUtil {private String lastMessage = "";//当前最后一条消息
private String currentFile = "";//当前操作的文件//转换过程中的消息
private StringBuffer sbMessages = newStringBuffer();//ffmpeg的实际路径,请在path中配置对应的bin
private String ffmpegPath = null;private boolean isRunning = false;public static voidmain(String[] args) {
FfmpegConvertUtil util= newFfmpegConvertUtil();
util.newMainFrame(util);
}/*** 处理某个文件夹*/
public voidstartProcess(String basepath) {if (ffmpegPath == null) {//在path环境变量中搜索ffmpeg程序的路径
String path = System.getenv("path");
String[] paths= path.split(";");for(String p : paths) {
File file= newFile(p);
File[] files=file.listFiles();if (files != null && files.length > 0) {for(File f : files) {if (f.getAbsolutePath().toLowerCase().endsWith("ffmpeg.exe")) {
ffmpegPath=f.getAbsolutePath();break;
}
}
}if(ffmpegPath!=null) {//无需再找
break;
}
}if (ffmpegPath == null) {
JOptionPane.showMessageDialog(null, "找不到转换程序,请设置ffmpeg到path环境变量");
}
}//使用timer作为多线程的使用方式
Timer timer = newTimer();
ConvertTask task= newConvertTask();
task.basePath=basepath;
timer.schedule(task,1000, 10000);
}public class ConvertTask extendsTimerTask {publicFfmpegConvertUtil util;publicString basePath;
@Overridepublic voidrun() {
isRunning= true;int count = 0;
List autoGenerateMp4 =findFilesToConvert(basePath);for(String path : autoGenerateMp4) {
currentFile= path + "(一共有文件:" + autoGenerateMp4.size() + "剩余文件数:" + (autoGenerateMp4.size() - count)+")";
convertAllOthersToMp4(path);
count++;
currentFile= "";
}
sbMessages.append(basePath+ "当前文件夹下面内容已经处理完成\r\n");
isRunning= false;
}
}/*** 得到需要转换的文件的列表
*
*@parambase 起始路径*/
public ListfindFilesToConvert(String base) {
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sbMessages.append(sdf.format(new Date()) + ":" + base + "文件搜索开始\r\n");
List files = new ArrayList();
List filesToConvert = new ArrayList();
listAllVideoFile(newFile(base), files);for(File f : files) {
filesToConvert.add(f.getAbsolutePath());
sbMessages.append(sdf.format(new Date()) + ":" + f.getAbsolutePath() + "加入清单\r\n");
}
sbMessages.append(sdf.format(new Date()) + ":" + base + "文件搜索结束,共找到需要转换文件" + filesToConvert.size() + "个\r\n");returnfilesToConvert;
}/*** 将一个视频文件转化为对应的mp4格式
*@paramfilepath 要转的文件的绝对路径*/
public voidconvertAllOthersToMp4(String filepath) {
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");if (filepath == null) {return;
}if (filepath.toLowerCase().endsWith(".mp4")) {
sbMessages.append("************" + sdf.format(new Date()) + ":" + filepath + "是mp4文件,跳过转换。\r\n");return;
}
sbMessages.append("************" + sdf.format(new Date()) + ":" + filepath + "转换开始\r\n");
String path= filepath.substring(0, filepath.lastIndexOf('.')) + ".mp4";byte[] buff = new byte[4096];try{
String cmd= ffmpegPath + " -y -i \"" + filepath + "\" \"" + path + "\"";
Process process=Runtime.getRuntime().exec(cmd);
InputStream inputStream=process.getInputStream();
InputStream errorStream=process.getErrorStream();while(process.isAlive()) {try{
Thread.sleep(10);
}catch(InterruptedException e) {
}int len = inputStream.available() > 0 ? inputStream.read(buff) : 0;if (len > 0) {
lastMessage= new String(buff, 0, len);
}
len= errorStream.available() > 0 ? errorStream.read(buff) : 0;if (len > 0) {
lastMessage= new String(buff, 0, len);
}
}
}catch(IOException e) {
sbMessages.append("************" + "转换文件:" + path + "执行失败:" + e.getMessage() + "\r\n");
}
sbMessages.append("************" + sdf.format(new Date()) + ":" + filepath + "转换开始" + "\r\n");
}/*** 根据后缀名判断是不是视频文件
*@paramfileName 要判断的文件名
*@return是否为视频文件*/
public booleanisVideoFile(String fileName) {
String[] videoExts= new String[] { "vob", "wmv", "avi", "rmvb", "mov", "rm"};for(String ext : videoExts) {if(fileName.endsWith(ext)) {return true;
}
}return false;
}/*** 获取指定文件夹下指定文件类型的所有文件的完整路径
*
*@paramparent 起始文件夹
*@paramfiles 存放数据的集合*/
public void listAllVideoFile(File parent, Listfiles) {
File[] listFiles=parent.listFiles();if (listFiles != null) {for(File f : listFiles) {if (f.isFile() &&isVideoFile(f.getName().toLowerCase())) {
files.add(f);
}else{
listAllVideoFile(f, files);
}
}
}
}/*** 窗体
*@authorAdministrator
**/
public class MainFrame extendsJFrame {/****/
private static final long serialVersionUID = 1L;privateJButton btnChooseRootDir;privateJTextArea txtMessages;privateJLabel lblMessage;privateJTextField txtCurrentFile;privateJLabel lblCurrentFile;privateJTextField txtChoosenDir;privateJLabel lblChoosenDir;privateJButton btnOpenDir;privatejavax.swing.Timer timerDisplay;publicMainFrame(FfmpegConvertUtil util) {//使用代码构建界面
this.getRootPane().setLayout(new FlowLayout(FlowLayout.LEFT, 10, 5));this.setDefaultCloseOperation(EXIT_ON_CLOSE);
btnChooseRootDir= new JButton(" 选择转换文件夹 ");
btnChooseRootDir.setSize(200, 30);
btnChooseRootDir.addActionListener(newActionListener() {
@Overridepublic voidactionPerformed(ActionEvent e) {
JFileChooser chooser= newJFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);int result = chooser.showOpenDialog(MainFrame.this);if (result ==JFileChooser.APPROVE_OPTION) {
txtChoosenDir.setText(chooser.getSelectedFile().getAbsolutePath());
util.startProcess(txtChoosenDir.getText());
}
}
});
btnOpenDir= new JButton(" 打开文件夹 ");
btnOpenDir.setSize(200, 30);
btnOpenDir.addActionListener(newActionListener() {
@Overridepublic voidactionPerformed(ActionEvent e) {try{
Runtime.getRuntime().exec("explorer \"" + txtChoosenDir.getText() + "\"");
}catch(IOException e1) {
e1.printStackTrace();
}
}
});
txtCurrentFile= newJTextField();
txtCurrentFile.setColumns(80);
txtCurrentFile.setFont(new Font("微软雅黑", Font.PLAIN, 16));
JLabel lblTemp= new JLabel(" "
+ " ");
lblTemp.setFont(new Font("微软雅黑", Font.PLAIN, 16));
lblCurrentFile= new JLabel("当前处理中文件");
lblCurrentFile.setFont(new Font("微软雅黑", Font.PLAIN, 16));
txtChoosenDir= newJTextField();
txtChoosenDir.setColumns(80);
txtChoosenDir.setFont(new Font("微软雅黑", Font.PLAIN, 16));
lblChoosenDir= new JLabel("当前处理的文件夹");
lblChoosenDir.setFont(new Font("微软雅黑", Font.PLAIN, 16));
lblMessage= new JLabel("处理消息显示");
lblMessage.setFont(new Font("微软雅黑", Font.PLAIN, 16));
txtMessages= new JTextArea(30, 105);
JScrollPane pane= newJScrollPane(txtMessages, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
timerDisplay= new javax.swing.Timer(5000, newActionListener() {
@Overridepublic voidactionPerformed(ActionEvent e) {if(isRunning) {if (sbMessages.length() > 8096) {
sbMessages.delete(0, lastMessage.length());
}if (lastMessage != null) {
sbMessages.append(lastMessage+ "\r\n");
lastMessage= null;
}
txtCurrentFile.setText(currentFile);
txtMessages.setText(sbMessages.toString());
}else{
}
}
});
timerDisplay.start();this.getRootPane().add(btnChooseRootDir);this.getRootPane().add(btnOpenDir);this.getRootPane().add(lblTemp);this.getRootPane().add(lblChoosenDir);this.getRootPane().add(txtChoosenDir);this.getRootPane().add(lblCurrentFile);this.getRootPane().add(txtCurrentFile);this.getRootPane().add(lblMessage);this.getRootPane().add(pane);this.setSize(1200, 800);this.setResizable(false);this.setVisible(true);
}
}
}