From 1dc489a6f843167a8a7d9419cfb217b839195865 Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Wed, 29 May 2024 17:06:32 +0200 Subject: [PATCH] Adds a de-interlace module and stuff Adds a module to de-interlace when converting a video. It's enabled by a new configuration option. Fixes some bugs in the letterbox cropper Adds mpeg4 to video formats --- .../ffmpegconverter/config/ConfigKey.java | 5 +++++ .../ffmpegconverter/config/Configuration.java | 11 +++++++++++ .../converter/AbstractConverter.java | 8 ++++++++ .../converter/AnimeConverter.java | 2 +- .../converter/AudioConverter.java | 2 +- .../converter/DownScaleConverter.java | 2 +- .../converter/LetterboxCropper.java | 6 +++--- .../converter/MKVToMP4Transcoder.java | 2 +- .../converter/MkvH264Converter.java | 2 +- .../converter/MkvH265ReducedConverter.java | 2 +- .../converter/StreamOrderConverter.java | 2 +- .../ffmpegconverter/converter/SubtitleEmbed.java | 2 +- .../converter/VideoConverter.java | 2 +- .../converter/WebAnimeConverter.java | 2 +- .../converter/WebVideoConverter.java | 2 +- .../converter/module/DeInterlaceModule.java | 16 ++++++++++++++++ .../converter/module/DebugModule.java | 7 +++++++ .../ffmpegconverter/utility/FFMpegHelper.java | 4 ++-- src/main/resources/conf/config.properties | 4 +++- src/main/resources/video_formats.txt | 3 ++- 20 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 src/main/java/net/knarcraft/ffmpegconverter/converter/module/DeInterlaceModule.java diff --git a/src/main/java/net/knarcraft/ffmpegconverter/config/ConfigKey.java b/src/main/java/net/knarcraft/ffmpegconverter/config/ConfigKey.java index 18ee56b..69a72f2 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/config/ConfigKey.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/config/ConfigKey.java @@ -52,6 +52,11 @@ public class ConfigKey { */ public static final ConfigKey MINIMAL_SUBTITLE_PREFERENCE = createKey("minimal-subtitle-preference", String.class, "AVOID"); + /** + * The configuration key for whether to de-interlace video streams + */ + public static final ConfigKey DE_INTERLACE_VIDEO = createKey("de-interlace-video", Boolean.class, false); + private final String configKey; private final T defaultValue; private final Class type; diff --git a/src/main/java/net/knarcraft/ffmpegconverter/config/Configuration.java b/src/main/java/net/knarcraft/ffmpegconverter/config/Configuration.java index 422aaa0..2f7b28b 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/config/Configuration.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/config/Configuration.java @@ -21,6 +21,7 @@ public class Configuration { private List animeAudioLanguages; private List animeSubtitleLanguages; private MinimalSubtitlePreference minimalSubtitlePreference; + private boolean deInterlaceVideo; /** * Instantiates and loads a new configuration @@ -53,6 +54,7 @@ public class Configuration { alwaysEncodeFlac = ConfigHelper.asBoolean(configHandler.getValue(ConfigKey.ENCODE_FLAC_ALWAYS)); animeAudioLanguages = ConfigHelper.asStringList(configHandler.getValue(ConfigKey.AUDIO_LANGUAGES_ANIME)); animeSubtitleLanguages = ConfigHelper.asStringList(configHandler.getValue(ConfigKey.SUBTITLE_LANGUAGES_ANIME)); + deInterlaceVideo = ConfigHelper.asBoolean(configHandler.getValue(ConfigKey.DE_INTERLACE_VIDEO)); try { minimalSubtitlePreference = MinimalSubtitlePreference.valueOf(String.valueOf(configHandler.getValue( ConfigKey.MINIMAL_SUBTITLE_PREFERENCE))); @@ -147,4 +149,13 @@ public class Configuration { return this.minimalSubtitlePreference; } + /** + * Gets whether video streams should be de-interlaced + * + * @return

Whether to de-interlace streams

+ */ + public boolean deInterlaceVideo() { + return this.deInterlaceVideo; + } + } diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/AbstractConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/AbstractConverter.java index 5e117d1..1868cfb 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/AbstractConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/AbstractConverter.java @@ -3,6 +3,8 @@ package net.knarcraft.ffmpegconverter.converter; import net.knarcraft.ffmpegconverter.FFMpegConvert; import net.knarcraft.ffmpegconverter.container.FFMpegCommand; import net.knarcraft.ffmpegconverter.container.StreamProbeResult; +import net.knarcraft.ffmpegconverter.converter.module.DeInterlaceModule; +import net.knarcraft.ffmpegconverter.converter.module.ModuleExecutor; import net.knarcraft.ffmpegconverter.handler.AvailableHardwareEncoderHandler; import net.knarcraft.ffmpegconverter.streams.StreamObject; import net.knarcraft.ffmpegconverter.utility.FFMpegHelper; @@ -68,6 +70,12 @@ public abstract class AbstractConverter implements Converter { return; } + // De-interlace the video if enabled + if (FFMpegConvert.getConfiguration().deInterlaceVideo() && + (outExtension.equalsIgnoreCase("mkv") || outExtension.equalsIgnoreCase("mp4"))) { + new ModuleExecutor(ffMpegCommand, List.of(new DeInterlaceModule())).execute(); + } + String[] command = ffMpegCommand.getResult(); // If no commands were given, no conversion is necessary if (command.length == 0) { diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java index bdbae11..9916966 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java @@ -90,7 +90,7 @@ public class AnimeConverter extends AbstractConverter { FFMpegCommand command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, probeResult.parsedFiles()); List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(90, 120)); + modules.add(new DebugModule()); } modules.add(new FastStartModule()); diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java index e12d7f1..8c64887 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java @@ -40,7 +40,7 @@ public class AudioConverter extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } //Gets the first audio stream from the file and adds it to the output file diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/DownScaleConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/DownScaleConverter.java index 5e79c0e..662daa6 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/DownScaleConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/DownScaleConverter.java @@ -64,7 +64,7 @@ public class DownScaleConverter extends AbstractConverter { FFMpegCommand command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, probeResult.parsedFiles()); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } //Add all streams without re-encoding diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/LetterboxCropper.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/LetterboxCropper.java index 7202e53..173877c 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/LetterboxCropper.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/LetterboxCropper.java @@ -112,7 +112,7 @@ public class LetterboxCropper extends AbstractConverter { FFMpegCommand convertCommand = new FFMpegCommand(ffmpegPath); - convertCommand.addInputFileOption(inputFile.getName()); + convertCommand.addInputFile(inputFile.getName()); convertCommand.addOutputFileOption("-vf", "crop=" + crop); convertCommand.addOutputFileOption("-c:v", "libx265"); convertCommand.addOutputFileOption("-crf", "22"); @@ -142,7 +142,7 @@ public class LetterboxCropper extends AbstractConverter { Map cropValues = new HashMap<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } FFMpegCommand probeCommand = new FFMpegCommand(ffmpegPath); @@ -166,7 +166,7 @@ public class LetterboxCropper extends AbstractConverter { FFMpegCommand clone = probeCommand.clone(); clone.addInputFileOption("-ss", String.valueOf(i)); - ProcessBuilder processBuilder = new ProcessBuilder(probeCommand.getResult()); + ProcessBuilder processBuilder = new ProcessBuilder(clone.getResult()); ProcessResult result = null; try { result = FFMpegHelper.runProcess(processBuilder, inputFile.getParentFile(), SPACER, false); diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/MKVToMP4Transcoder.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/MKVToMP4Transcoder.java index 6fd4d32..fc33a36 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/MKVToMP4Transcoder.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/MKVToMP4Transcoder.java @@ -60,7 +60,7 @@ public class MKVToMP4Transcoder extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } // Copy stream info diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH264Converter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH264Converter.java index 624f186..2e3121c 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH264Converter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH264Converter.java @@ -52,7 +52,7 @@ public class MkvH264Converter extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } // Map video if present diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH265ReducedConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH265ReducedConverter.java index 33fba68..15c6df9 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH265ReducedConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/MkvH265ReducedConverter.java @@ -53,7 +53,7 @@ public class MkvH265ReducedConverter extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } // Map video if present diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/StreamOrderConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/StreamOrderConverter.java index 9d39b40..fb411eb 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/StreamOrderConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/StreamOrderConverter.java @@ -73,7 +73,7 @@ public class StreamOrderConverter extends AbstractConverter { FFMpegCommand command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, probeResult.parsedFiles()); List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(90, 120)); + modules.add(new DebugModule()); } modules.add(new FastStartModule()); diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/SubtitleEmbed.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/SubtitleEmbed.java index a91ed0b..87c6e9a 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/SubtitleEmbed.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/SubtitleEmbed.java @@ -50,7 +50,7 @@ public class SubtitleEmbed extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } modules.add(new MapAllModule<>(probeResult.parsedStreams())); diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java index e8cfdec..001c225 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java @@ -44,7 +44,7 @@ public class VideoConverter extends AbstractConverter { List streams = probeResult.parsedStreams(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } //Add all streams without re-encoding diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/WebAnimeConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/WebAnimeConverter.java index c3f0442..01d40d0 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/WebAnimeConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/WebAnimeConverter.java @@ -76,7 +76,7 @@ public class WebAnimeConverter extends AbstractConverter { FFMpegCommand command = FFMpegHelper.getFFMpegWebVideoCommand(executable, probeResult.parsedFiles()); List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } //Get the first audio stream in accordance with chosen languages diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/WebVideoConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/WebVideoConverter.java index 64cf077..17104b6 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/WebVideoConverter.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/WebVideoConverter.java @@ -53,7 +53,7 @@ public class WebVideoConverter extends AbstractConverter { List modules = new ArrayList<>(); if (this.debug) { - modules.add(new DebugModule(0, 0)); + modules.add(new DebugModule()); } //Get first streams from the file diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DeInterlaceModule.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DeInterlaceModule.java new file mode 100644 index 0000000..910400f --- /dev/null +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DeInterlaceModule.java @@ -0,0 +1,16 @@ +package net.knarcraft.ffmpegconverter.converter.module; + +import net.knarcraft.ffmpegconverter.container.FFMpegCommand; +import org.jetbrains.annotations.NotNull; + +/** + * A converter module for adding de-interlacing + */ +public class DeInterlaceModule implements ConverterModule { + + @Override + public void addArguments(@NotNull FFMpegCommand command) { + command.addOutputFileOption("-filter:v", "bwdif=mode=send_field"); + } + +} diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DebugModule.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DebugModule.java index d2a3ac9..35f5dd2 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DebugModule.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/module/DebugModule.java @@ -11,6 +11,13 @@ public class DebugModule implements ConverterModule { private double startTime = 50; private double duration = 120; + /** + * Instantiates a new debug module that starts at 50 seconds, and lasts until 120 seconds + */ + public DebugModule() { + + } + /** * Instantiates a new debug module * diff --git a/src/main/java/net/knarcraft/ffmpegconverter/utility/FFMpegHelper.java b/src/main/java/net/knarcraft/ffmpegconverter/utility/FFMpegHelper.java index 623aee1..d200723 100644 --- a/src/main/java/net/knarcraft/ffmpegconverter/utility/FFMpegHelper.java +++ b/src/main/java/net/knarcraft/ffmpegconverter/utility/FFMpegHelper.java @@ -184,8 +184,8 @@ public final class FFMpegHelper { * @param stream

The stream to map

*/ public static void mapStream(@NotNull FFMpegCommand command, @NotNull StreamObject stream) { - command.addOutputFileOption("-map", String.format("%d:%d", - stream.getInputIndex(), stream.getAbsoluteIndex())); + command.addOutputFileOption("-map", String.format("%d:%d", stream.getInputIndex(), + stream.getAbsoluteIndex())); } /** diff --git a/src/main/resources/conf/config.properties b/src/main/resources/conf/config.properties index e23f1ec..d562906 100644 --- a/src/main/resources/conf/config.properties +++ b/src/main/resources/conf/config.properties @@ -15,4 +15,6 @@ audio-languages-anime=jpn,eng,* # The preference for subtitle languages when converting anime (0 = undefined, * = any) subtitle-languages-anime=eng,* # The preference for minimal subtitles, AKA Signs & Songs (REQUIRE/PREFER/NO_PREFERENCE/AVOID/REJECT) -minimal-subtitle-preference=AVOID \ No newline at end of file +minimal-subtitle-preference=AVOID +# The preference for whether video streams should be de-interlaced. It is recommended to only enable this when you notice that a video file is interlaced. +de-interlace-video=false \ No newline at end of file diff --git a/src/main/resources/video_formats.txt b/src/main/resources/video_formats.txt index 074e447..78d6cab 100644 --- a/src/main/resources/video_formats.txt +++ b/src/main/resources/video_formats.txt @@ -28,4 +28,5 @@ m2v svi 3g2 roq -nsv \ No newline at end of file +nsv +mpeg4 \ No newline at end of file