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:
2024-04-08 20:00:09 +02:00
parent be88845731
commit 376d5655f2
20 changed files with 537 additions and 450 deletions

View File

@ -1,6 +1,5 @@
package net.knarcraft.ffmpegconverter.streams;
import net.knarcraft.ffmpegconverter.utility.FileUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
@ -10,51 +9,21 @@ import java.util.Map;
*/
public class SubtitleStream extends AbstractStream implements StreamObject {
final private String file;
final private boolean isFullSubtitle;
final private boolean isImageSubtitle;
final private boolean isInternalStream;
/**
* Instantiates a new subtitle stream
*
* @param streamInfo <p>All info about the stream</p>
* @param relativeIndex <p>The index of the subtitle stream relative to other subtitle streams.</p>
* @param file <p>The file containing the subtitle.</p>
* @param isInternalStream <p>Whether this subtitle stream is in the video file itself</p>
* @param streamInfo <p>All info about the stream</p>
* @param inputIndex <p>The index of the input file containing this stream</p>
* @param relativeIndex <p>The index of the subtitle stream relative to other subtitle streams.</p>
*/
public SubtitleStream(@NotNull Map<StreamTag, String> streamInfo, int relativeIndex,
@NotNull String file, boolean isInternalStream) {
super(streamInfo, relativeIndex);
public SubtitleStream(@NotNull Map<StreamTag, String> streamInfo, int inputIndex, int relativeIndex) {
super(streamInfo, inputIndex, relativeIndex);
this.isFullSubtitle = isFullSubtitle();
this.isImageSubtitle = isImageSubtitle();
this.isInternalStream = isInternalStream;
this.file = file;
if (this.language == null || this.language.isEmpty()) {
String possibleLanguage = FileUtil.getLanguage(file);
if (possibleLanguage != null) {
this.language = possibleLanguage;
}
}
}
/**
* Gets the file name of the file containing this subtitle
*
* @return <p>The file name containing the subtitle stream.</p>
*/
public String getFile() {
return this.file;
}
/**
* Gets whether this subtitle stream is an internal stream, not an external one
*
* @return <p>True if this stream is an internal stream</p>
*/
public boolean isInternalSubtitle() {
return this.isInternalStream;
this.isImageSubtitle = codecName != null &&
(getCodecName().equals("hdmv_pgs_subtitle") || getCodecName().equals("dvd_subtitle"));
}
/**
@ -75,25 +44,12 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
return this.isFullSubtitle;
}
/**
* Checks whether a subtitle is image based (as opposed to text based)
*
* @return <p>True if the subtitle is image based.</p>
*/
private boolean isImageSubtitle() {
return codecName != null && (getCodecName().equals("hdmv_pgs_subtitle")
|| getCodecName().equals("dvd_subtitle"));
}
/**
* Checks whether the subtitle translates everything (as opposed to just songs and signs)
*
* @return <p>True if the subtitle translates everything.</p>
*/
private boolean isFullSubtitle() {
if (getTitle() == null) {
return false;
}
String titleLowercase = getTitle().toLowerCase();
return !titleLowercase.matches(".*si(ng|gn)s?[ &/a-z]+songs?.*") &&
!titleLowercase.matches(".*songs?[ &/a-z]+si(gn|ng)s?.*") &&
@ -101,7 +57,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
!titleLowercase.matches(".*s&s.*") &&
!titleLowercase.matches("signs?") &&
!titleLowercase.matches("songs?") &&
!titleLowercase.contains("signs only");
!titleLowercase.matches(".*signs only.*");
}
@Override