Adds converter modules and sorters
All checks were successful
KnarCraft/FFmpegConvert/pipeline/head This commit looks good

Converters are now the result of combining multiple modules, and running them in the selected sequence. I hope to be able to completely remove converters by replacing them with templates that simply run some modules in a sequence, before running FFmpeg. Then I want to be able to parse a command into a template, so users have full control of what a template does.

Sorters each sort a list of streams after a single criteria. They can be chained in order to create complex chained sorters.
This commit is contained in:
2024-04-12 15:31:34 +02:00
parent 376d5655f2
commit 461c7552b3
51 changed files with 1819 additions and 579 deletions

View File

@@ -2,10 +2,14 @@ package net.knarcraft.ffmpegconverter.converter;
import net.knarcraft.ffmpegconverter.container.FFMpegCommand;
import net.knarcraft.ffmpegconverter.container.StreamProbeResult;
import net.knarcraft.ffmpegconverter.streams.AudioStream;
import net.knarcraft.ffmpegconverter.streams.StreamObject;
import net.knarcraft.ffmpegconverter.streams.SubtitleStream;
import net.knarcraft.ffmpegconverter.streams.VideoStream;
import net.knarcraft.ffmpegconverter.converter.module.ConverterModule;
import net.knarcraft.ffmpegconverter.converter.module.DebugModule;
import net.knarcraft.ffmpegconverter.converter.module.ModuleExecutor;
import net.knarcraft.ffmpegconverter.converter.module.mapping.NthAudioStreamModule;
import net.knarcraft.ffmpegconverter.converter.module.mapping.NthSubtitleStreamModule;
import net.knarcraft.ffmpegconverter.converter.module.mapping.NthVideoStreamModule;
import net.knarcraft.ffmpegconverter.converter.module.output.CopyAllModule;
import net.knarcraft.ffmpegconverter.converter.module.output.SetOutputFileModule;
import net.knarcraft.ffmpegconverter.utility.FFMpegHelper;
import org.jetbrains.annotations.NotNull;
@@ -49,34 +53,29 @@ public class MKVToMP4Transcoder extends AbstractConverter {
public String[] generateConversionCommand(@NotNull String executable, @NotNull StreamProbeResult probeResult,
@NotNull String outFile) {
FFMpegCommand command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, probeResult.parsedFiles());
List<StreamObject> streams = probeResult.parsedStreams();
List<ConverterModule> modules = new ArrayList<>();
if (this.debug) {
FFMpegHelper.addDebugArguments(command, 50, 120);
}
//Get the nth audio stream
List<AudioStream> audioStreams = filterStreamsByType(streams, AudioStream.class);
AudioStream audioStream = getNthAudioSteam(new ArrayList<>(audioStreams), Math.max(this.audioStreamIndex, 0));
//Get the nth subtitle stream
List<SubtitleStream> allSubtitleStreams = filterStreamsByType(streams, SubtitleStream.class);
SubtitleStream subtitleStream = getNthSubtitleStream(new ArrayList<>(allSubtitleStreams),
Math.max(this.subtitleStreamIndex, 0));
//Get the nth video stream
VideoStream videoStream = getNthVideoStream(streams, Math.max(this.videoStreamIndex, 0));
if (videoStream == null) {
throw new IllegalArgumentException("The selected video stream was not found");
modules.add(new DebugModule(0, 0));
}
// Copy stream info
command.addOutputFileOption("-c", "copy");
modules.add(new CopyAllModule());
//Add streams to output file
FFMpegHelper.addAudioStream(command, audioStream, false);
FFMpegHelper.addSubtitleAndVideoStream(command, subtitleStream, videoStream);
if (!probeResult.getAudioStreams().isEmpty()) {
modules.add(new NthAudioStreamModule(probeResult.getAudioStreams(), this.audioStreamIndex));
}
if (!probeResult.getVideoStreams().isEmpty()) {
modules.add(new NthVideoStreamModule(probeResult.getVideoStreams(), this.videoStreamIndex));
}
if (!probeResult.getSubtitleStreams().isEmpty()) {
modules.add(new NthSubtitleStreamModule(probeResult.getSubtitleStreams(), this.subtitleStreamIndex));
}
command.setOutputFile(outFile);
modules.add(new SetOutputFileModule(outFile));
new ModuleExecutor(command, modules).execute();
return command.getResult();
}