Improves FFMpeg command generation
Adds an object for storing FFmpeg variables. This allows any argument type to be added at any time, removing the limitation of having to add to the command in a specific order. Makes stream objects store the index of the input file they belong to. Saves the result of probes to a record that's easy to pass around. Always passes all probed files to the input files of ffmpeg. Makes it easier to enable h26x encoding/decoding when necessary. Removes the hard-coded behavior for external subtitles, and allows any stream to be an external stream.
This commit is contained in:
@ -1,13 +1,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.utility.FFMpegHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -33,73 +34,50 @@ public class MkvH264Converter extends AbstractConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] generateConversionCommand(String executable, File file, List<StreamObject> streams,
|
||||
String outFile) {
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(executable);
|
||||
command.add("-hwaccel");
|
||||
command.add("cuda");
|
||||
command.add("-hwaccel_output_format");
|
||||
command.add("cuda");
|
||||
command.add("-i");
|
||||
command.add(file.getName());
|
||||
public String[] generateConversionCommand(@NotNull String executable, @NotNull StreamProbeResult probeResult,
|
||||
@NotNull String outFile) {
|
||||
FFMpegCommand command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, probeResult.parsedFiles());
|
||||
List<StreamObject> streams = probeResult.parsedStreams();
|
||||
|
||||
if (this.debug) {
|
||||
FFMpegHelper.addDebugArguments(command, 50, 120);
|
||||
}
|
||||
|
||||
// Map video if present
|
||||
if (!filterStreamsByType(streams, VideoStream.class).isEmpty()) {
|
||||
command.add("-map");
|
||||
command.add("0:v");
|
||||
command.add("-crf");
|
||||
command.add("28");
|
||||
command.add("-codec:v");
|
||||
command.add("h264_nvenc");
|
||||
command.add("-preset");
|
||||
command.add("slow");
|
||||
command.add("-movflags");
|
||||
command.add("+faststart");
|
||||
List<StreamObject> videoStreams = filterStreamsByType(streams, VideoStream.class);
|
||||
if (!videoStreams.isEmpty()) {
|
||||
for (StreamObject streamObject : videoStreams) {
|
||||
if (!streamObject.getCodecName().equals("h264") && !streamObject.getCodecName().equals("h266")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFMpegHelper.addH26xHardwareDecoding(command);
|
||||
break;
|
||||
}
|
||||
|
||||
FFMpegHelper.mapAllStreams(command, videoStreams);
|
||||
FFMpegHelper.addH264HardwareEncoding(command, 17);
|
||||
command.addOutputFileOption("-movflags", "+faststart");
|
||||
}
|
||||
|
||||
// Map audio if present
|
||||
if (!filterStreamsByType(streams, AudioStream.class).isEmpty()) {
|
||||
command.add("-map");
|
||||
command.add("0:a");
|
||||
command.add("-c:a");
|
||||
command.add("copy");
|
||||
List<StreamObject> audioStreams = filterStreamsByType(streams, AudioStream.class);
|
||||
if (!audioStreams.isEmpty()) {
|
||||
FFMpegHelper.mapAllStreams(command, audioStreams);
|
||||
command.addOutputFileOption("-c:a", "copy");
|
||||
}
|
||||
|
||||
// Map subtitles if present
|
||||
if (hasInternalStreams(streams)) {
|
||||
command.add("-map");
|
||||
command.add("0:s");
|
||||
command.add("-c:s");
|
||||
command.add("copy");
|
||||
List<StreamObject> subtitleStreams = filterStreamsByType(streams, SubtitleStream.class);
|
||||
if (!subtitleStreams.isEmpty()) {
|
||||
FFMpegHelper.mapAllStreams(command, subtitleStreams);
|
||||
command.addOutputFileOption("-c:s", "copy");
|
||||
}
|
||||
|
||||
command.add("-map_metadata");
|
||||
command.add("0");
|
||||
command.add("-movflags");
|
||||
command.add("use_metadata_tags");
|
||||
command.addOutputFileOption("-f", "matroska");
|
||||
|
||||
command.add(outFile);
|
||||
return command.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the processed file has any internal subtitle streams
|
||||
*
|
||||
* @param streams <p>All parsed streams for the video file</p>
|
||||
* @return <p>True if the file has at least one internal subtitle stream</p>
|
||||
*/
|
||||
private boolean hasInternalStreams(List<StreamObject> streams) {
|
||||
for (StreamObject subtitleStream : filterStreamsByType(streams, SubtitleStream.class)) {
|
||||
if (((SubtitleStream) subtitleStream).isInternalSubtitle()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
command.setOutputFile(outFile);
|
||||
return command.getResult();
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user