该程序需要用到ffmpeg
链接:https://pan.baidu.com/s/1GEc6CwC7_QEF44SHw6X5hA
提取码:w4do
该项目就不发了
只发主要代码
package sample;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.text.Text;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ResourceBundle;
/*
* author:L
* time:2021/12/22
* context:新加功能自定义格式的输入*/
/*
* author:L
* time:2021/12/23
* context:将for循环改成了递归处理
* 好处:不用再规定几层文件夹了
* */
/*
* author:L
* time:2021/12/27
* context:将裁剪视频功能和进度功能单独做成两个线程,排除在主线程之外
* 好处:若用主线程裁剪视频会导致主线程一直运行裁剪,从而导致界面卡住。
* 虽然进度单开了一个线程且线程内的数据在更新,但是界面卡住了,进度
* 线程内更新的数据无法显示。现在裁剪视频也单独用一个线程而非是主线
* 程,这样界面不会卡住,进度线程更新的数据就能实时在界面上显示了。
* */
public class Controller implements Initializable{
public static int jinduNum;
static boolean isEnd = false;
String getfilepath;
String zidingyiCanShu = "100:100";
@FXML
private TextField XText;//自定义x坐标点输入框
@FXML
private TextField YText;//自定义y坐标点输入框
@FXML
private ProgressBar jindu;//进度条
@FXML
private Button bth2;
@FXML
private Text process3;
@FXML
private Button But1;
@Override
public void initialize(URL location, ResourceBundle resources) {
bth2.setOnAction(e->getUpdateFliePathDemo(e));//按钮注册事件处理函数
}
/*开始计数按钮对应方法
用于提示进度
*/
public void getUpdateFliePathDemo(ActionEvent e){
Service<String> service=new Service<String>() {
@Override
protected Task<String> createTask() {
return new Task<String>() {
@Override
protected String call() throws Exception {
for (int a = 1; a <= 1000000000; a++) {
if(isEnd){
break;
}
// //更新service的value属性
updateValue("正在处理第 " + jinduNum + " 个");
Thread.sleep(10000);
}
return "完成:一共处理 "+jinduNum+" 个视频";
}
};
}
};
//绑定process3的text属性为service的text属性
process3.textProperty().bind(service.valueProperty());
//任务完成时会调用
service.setOnSucceeded((WorkerStateEvent event) -> {
System.out.println("任务处理完成!");
});
//启动任务start()一定是最后才调用的
service.start();
}
//目录按钮对应的方法
public void getFilePathDemo() {
DirectoryChooser directoryChooser = new DirectoryChooser();
//默认打开的路径
directoryChooser.setInitialDirectory(new File("C:\\"));
Stage stage = new Stage();
//页面传入的路径
this.getfilepath = directoryChooser.showDialog(stage).toString();
File file = new File(this.getfilepath);
//获取自定义的格式
String x1 = this.XText.getText();
String y1 = this.YText.getText();
if (!"".equals(x1) && !"".equals(y1)) {
this.zidingyiCanShu = x1 + ":" + y1;
}
//进行裁剪视频操作
new Thread(){
@Override
public void run() {
super.run();
getFilePath(file);
isEnd = true;
}
//递归搜寻可见光,红外,自定义文件夹
public void getFilePath(File file){
if(file.isDirectory()){
if(file.getName().equals("可见光")){
videoTypeCut(file.getPath(),file.listFiles(),"可见光","kejianguang");
}else if(file.getName().equals("红外")){
videoTypeCut(file.getPath(),file.listFiles(),"红外","hongwai");
}else if(file.getName().equals("自定义")){
videoTypeCut(file.getPath(),file.listFiles(),"自定义","zidingyi");
}else{
File[] files = file.listFiles();
if(files.length>0){
for(int i=0;i<files.length;i++){
getFilePath(files[i]);
}
}
}
}
}
//判断保存文件夹是否有,调用裁剪视频代码
public void videoTypeCut(String thisPath,File[] visibleLightPaths,String typeName,String type){
//判断裁剪可见光文件夹有没有,没有就创建
String newPath = thisPath.replaceAll(typeName,"剪切"+typeName);
File caiJianFile = new File(newPath);
if(!caiJianFile.exists()){
caiJianFile.mkdir();
}
for(int i=0;i<visibleLightPaths.length;i++){
String thisFileName = visibleLightPaths[i].getName();
try {
splitVideo(thisPath+"\\"+thisFileName, newPath+"\\", thisFileName, type);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//执行按钮对应方法
public void splitVideo(String finalPath, String outPath, String fileName, String type) throws Exception {
jinduNum++;
System.out.println(finalPath + " 裁剪开始");
System.out.println("正在裁剪,请勿操作或中断");
String cmd = "";
if (type == "kejianguang") {
cmd = "ffmpeg -i " + finalPath + " -vf crop=1920:960:0:0 " + outPath + fileName + " -y";
} else if (type == "hongwai") {
cmd = "ffmpeg -i " + finalPath + " -vf crop=720:520:0:0 " + outPath + fileName + " -y";
} else if (type == "zidingyi") {
cmd = "ffmpeg -i " + finalPath + " -vf crop=" + zidingyiCanShu + ":0:0 " + outPath + fileName + " -y";
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = br.readLine()) != null) {
// System.out.println(line);
}
boolean btnSet = true;
process.waitFor();
System.out.println(finalPath + " 裁剪结束");
System.out.println();
}
}.start();
System.out.println("程序结束,请查看结果");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="/sample/sty.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Label layoutX="120.0" layoutY="43.0" text="视频分辨率裁剪工具">
<font>
<Font size="24.0" />
</font>
</Label>
<Label layoutX="110.0" layoutY="193.0" text="目标目录:" />
<Button fx:id="But1" layoutX="178.0" layoutY="186.0" mnemonicParsing="false" onAction="#getFilePathDemo" text="选择文件夹">
<font>
<Font size="14.0" />
</font>
</Button>
<Label layoutX="108.0" layoutY="135.0" text="自定义格式:" />
<Label layoutX="175.0" layoutY="135.0" text="x" />
<TextField fx:id="XText" layoutX="187.0" layoutY="131.0" prefHeight="23.0" prefWidth="72.0" />
<Label layoutX="264.0" layoutY="135.0" text="y" />
<TextField fx:id="YText" layoutX="277.0" layoutY="131.0" prefHeight="23.0" prefWidth="72.0" />
<Button fx:id="bth2" layoutX="283.0" layoutY="189.0" mnemonicParsing="false" text="开始计数" />
<Label layoutX="43.0" layoutY="304.0" text="提示:" textFill="#fc0000">
<font>
<Font size="18.0" />
</font>
</Label>
<Label layoutX="94.0" layoutY="309.0" text="如有自定义格式,请先选择填写自定义格式,然后选择目标目录。" />
<Label layoutX="94.0" layoutY="328.0" text="选择好文件夹,点击计数后就不要动了,程序已经在裁剪视频了。" />
<!-- <ProgressBar fx:id="jindu" layoutX="201.0" layoutY="191.0" prefWidth="200.0" progress="0" />-->
<Text fx:id="process3" layoutX="114.0" layoutY="268.0" strokeType="OUTSIDE" strokeWidth="0.0" text="当前未开始裁剪" wrappingWidth="401.6513671875" />
<Label layoutX="151.0" layoutY="171.0" />
<!-- <Button fx:id="bth3" layoutX="244.0" layoutY="237.0" mnemonicParsing="false" onAction="#splitVideo" text="准备就绪开始执行" />-->
</children>
</AnchorPane>