2023年5月24日16:13:58 视频转码

master
zhangmeng 2023-05-24 16:14:18 +08:00
parent 36ab8a1624
commit 7b5993bcc4
2 changed files with 64 additions and 9 deletions

View File

@ -5,6 +5,8 @@ import com.zhangmeng.tools.utils.ImagePath;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -12,21 +14,27 @@ import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media; import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.bytedeco.ffmpeg.global.avcodec; import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*; import org.bytedeco.javacv.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import static org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_MPEG4; import static org.bytedeco.ffmpeg.global.avcodec.*;
/** /**
* @author : * @author :
@ -60,15 +68,32 @@ public class VideoTranscoderController {
public SimpleObjectProperty<File> in_file = new SimpleObjectProperty<>(); public SimpleObjectProperty<File> in_file = new SimpleObjectProperty<>();
public SimpleObjectProperty<File> out_file = new SimpleObjectProperty<>(); public SimpleObjectProperty<File> out_file = new SimpleObjectProperty<>();
@FXML
public MediaView mv;
@FXML
public AnchorPane mv_root;
@FXML @FXML
public void initialize() { public void initialize() {
// 绑定MediaView的宽度和高度到父容器的宽度和高度
this.mv.setPreserveRatio(false);
this.mv.fitHeightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("fitHeightProperty:" + newValue.doubleValue());
}
});
init_but(input_file_button); init_but(input_file_button);
init_but(output_file_button); init_but(output_file_button);
init_choose_dir_manager(); init_choose_dir_manager();
init_choose_file_manager(); init_choose_file_manager();
this.start_button.setOnAction(event -> { this.start_button.setOnAction(event -> {
this.mv.setFitWidth(mv_root.getWidth());
this.mv.setFitHeight(mv_root.getHeight());
if (input_file.getText().length() == 0){ if (input_file.getText().length() == 0){
AlertUtils.alert_warning("请选择转码文件!"); AlertUtils.alert_warning("请选择转码文件!");
return; return;
@ -149,13 +174,27 @@ public class VideoTranscoderController {
protected Void call() throws Exception { protected Void call() throws Exception {
try { try {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(in_file.get()); FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(in_file.get());
grabber.setVideoCodec(AV_CODEC_ID_MPEG4);
grabber.start(); grabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(out_file.get(), grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels()); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(out_file.get(), grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.setFormat("avi"); String extension = FilenameUtils.getExtension(out_file.get().getName());
recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4); recorder.setFormat(extension);
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.setVideoBitrate(grabber.getVideoBitrate());
recorder.setAudioCodec(grabber.getAudioCodec());
recorder.setAudioBitrate(grabber.getAudioCodec());
recorder.setFrameRate(grabber.getFrameRate()); recorder.setFrameRate(grabber.getFrameRate());
if (extension.equals("mp4")){
recorder.setVideoCodec(AV_CODEC_ID_MPEG4);
}
if (extension.equals("avi")){
recorder.setVideoCodec(AV_CODEC_ID_HUFFYUV);
}
if (extension.equals("flv")){
recorder.setVideoCodec(AV_CODEC_ID_FLV1);
}
recorder.start(); recorder.start();
int totalFrames = grabber.getLengthInFrames(); int totalFrames = grabber.getLengthInFrames();
@ -170,7 +209,10 @@ public class VideoTranscoderController {
} }
grabber.stop(); grabber.stop();
grabber.release();
recorder.stop(); recorder.stop();
recorder.release();
} catch (FrameGrabber.Exception | FrameRecorder.Exception e) { } catch (FrameGrabber.Exception | FrameRecorder.Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -181,6 +223,15 @@ public class VideoTranscoderController {
protected void succeeded() { protected void succeeded() {
progressbar.setProgress(1); progressbar.setProgress(1);
AlertUtils.alert_msg("转码完成!"); AlertUtils.alert_msg("转码完成!");
try {
Media media = new Media(out_file.get().toURI().toASCIIString());
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
mediaPlayer.setOnEndOfMedia(mediaPlayer::dispose);
mv.setMediaPlayer(mediaPlayer);
} catch (Exception e) {
e.printStackTrace();
}
} }
@Override @Override

View File

@ -7,7 +7,7 @@
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.media.MediaView?> <?import javafx.scene.media.MediaView?>
<?import javafx.scene.layout.StackPane?>
<AnchorPane prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.VideoTranscoderController"> <AnchorPane prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.VideoTranscoderController">
<children> <children>
<Label layoutX="89.0" layoutY="47.0" text="请选择将要转码的视频文件:" /> <Label layoutX="89.0" layoutY="47.0" text="请选择将要转码的视频文件:" />
@ -18,8 +18,12 @@
<TextField fx:id="output_file_name" layoutX="871.0" layoutY="93.0" /> <TextField fx:id="output_file_name" layoutX="871.0" layoutY="93.0" />
<Button fx:id="output_file_button" layoutX="264.0" layoutY="93.0" mnemonicParsing="false" text="Button" /> <Button fx:id="output_file_button" layoutX="264.0" layoutY="93.0" mnemonicParsing="false" text="Button" />
<Button fx:id="input_file_button" layoutX="264.0" layoutY="43.0" mnemonicParsing="false" text="Button" /> <Button fx:id="input_file_button" layoutX="264.0" layoutY="43.0" mnemonicParsing="false" text="Button" />
<Button fx:id="start_button" layoutX="496.0" layoutY="477.0" mnemonicParsing="false" text="开始转码" /> <Button fx:id="start_button" layoutX="574.0" layoutY="544.0" mnemonicParsing="false" text="开始转码" AnchorPane.bottomAnchor="80.0" />
<ProgressBar fx:id="progressbar" layoutX="56.0" layoutY="156.0" prefHeight="9.0" prefWidth="1100.0" progress="0.0" AnchorPane.leftAnchor="56.0" AnchorPane.rightAnchor="44.0" /> <ProgressBar fx:id="progressbar" layoutX="56.0" layoutY="504.0" prefHeight="9.0" prefWidth="1100.0" progress="0.0" AnchorPane.bottomAnchor="136.0" AnchorPane.leftAnchor="56.0" AnchorPane.rightAnchor="44.0" />
<MediaView fitHeight="200.0" fitWidth="649.0" layoutX="56.0" layoutY="212.0" AnchorPane.leftAnchor="56.0" AnchorPane.rightAnchor="56.0" /> <AnchorPane fx:id="mv_root" layoutX="56.0" layoutY="140.0" prefHeight="339.0" prefWidth="1088.0" style="-fx-border-color: #eeee07;-fx-border-width: 1px;" AnchorPane.bottomAnchor="170.0" AnchorPane.leftAnchor="56.0" AnchorPane.rightAnchor="56.0" AnchorPane.topAnchor="140.0">
<children>
<MediaView fx:id="mv" style="-fx-border-color: red" />
</children>
</AnchorPane>
</children> </children>
</AnchorPane> </AnchorPane>