java多线程视频转码_Java也疯狂-分享利用ffmpeg做视频转换的工具

这是一个使用Java多线程和FFmpeg库实现的视频转码工具,能够批量将不同格式的视频转换为MP4格式。程序首先搜索指定文件夹中的视频文件,然后通过FFmpeg进行转换,并在转换过程中显示实时进度和消息。
摘要由CSDN通过智能技术生成

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);

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值