Fixes subtitle mapping for video with only external subtitles
All checks were successful
KnarCraft/FFmpegConvert/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2023-08-12 22:14:46 +02:00
parent 5d94cabca0
commit 56f5e31934
3 changed files with 45 additions and 16 deletions

View File

@ -56,7 +56,7 @@ public class MkvH264Converter extends AbstractConverter {
} }
// Map subtitles if present // Map subtitles if present
if (!filterStreamsByType(streams, SubtitleStream.class).isEmpty()) { if (hasInternalStreams(streams)) {
command.add("-map"); command.add("-map");
command.add("0:s"); command.add("0:s");
command.add("-c:s"); command.add("-c:s");
@ -72,4 +72,20 @@ public class MkvH264Converter extends AbstractConverter {
return command.toArray(new String[0]); 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;
}
} }

View File

@ -9,6 +9,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
final private String file; final private String file;
final private boolean isFullSubtitle; final private boolean isFullSubtitle;
final private boolean isImageSubtitle; final private boolean isImageSubtitle;
final private boolean isInternalStream;
/** /**
* Instantiates a new subtitle stream * Instantiates a new subtitle stream
@ -19,9 +20,10 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
* @param language <p>The language of the subtitle stream.</p> * @param language <p>The language of the subtitle stream.</p>
* @param title <p>The title of the subtitle stream.</p> * @param title <p>The title of the subtitle stream.</p>
* @param file <p>The file containing the subtitle.</p> * @param file <p>The file containing the subtitle.</p>
* @param isInternalStream <p>Whether this subtitle stream is in the video file itself</p>
*/ */
public SubtitleStream(String codecName, int absoluteIndex, int relativeIndex, String language, String title, public SubtitleStream(String codecName, int absoluteIndex, int relativeIndex, String language, String title,
String file) { String file, boolean isInternalStream) {
this.codecName = codecName; this.codecName = codecName;
this.absoluteIndex = absoluteIndex; this.absoluteIndex = absoluteIndex;
this.language = language; this.language = language;
@ -29,6 +31,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
this.isFullSubtitle = isFullSubtitle(); this.isFullSubtitle = isFullSubtitle();
this.relativeIndex = relativeIndex; this.relativeIndex = relativeIndex;
this.isImageSubtitle = isImageSubtitle(); this.isImageSubtitle = isImageSubtitle();
this.isInternalStream = isInternalStream;
this.file = file; this.file = file;
} }
@ -50,6 +53,15 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
return this.file; 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;
}
/** /**
* Gets whether the subtitle is an image subtitle * Gets whether the subtitle is an image subtitle
* *

View File

@ -285,7 +285,7 @@ public final class FFMpegHelper {
} else if (stream.contains("codec_type=audio")) { } else if (stream.contains("codec_type=audio")) {
parsedStreams.add(parseAudioStream(streamParts, relativeAudioIndex++)); parsedStreams.add(parseAudioStream(streamParts, relativeAudioIndex++));
} else if (stream.contains("codec_type=subtitle")) { } else if (stream.contains("codec_type=subtitle")) {
parsedStreams.add(parseSubtitleStream(streamParts, relativeSubtitleIndex++, file.getName())); parsedStreams.add(parseSubtitleStream(streamParts, relativeSubtitleIndex++, file.getName(), true));
} }
} }
List<StreamObject> externalSubtitles = getExternalSubtitles(ffprobePath, file.getParentFile(), file.getName()); List<StreamObject> externalSubtitles = getExternalSubtitles(ffprobePath, file.getParentFile(), file.getName());
@ -323,7 +323,7 @@ public final class FFMpegHelper {
String[] streams = probeForStreams(ffprobePath, subtitleFile); String[] streams = probeForStreams(ffprobePath, subtitleFile);
for (String stream : streams) { for (String stream : streams) {
String[] streamParts = stream.split(PROBE_SPLIT_CHARACTER); String[] streamParts = stream.split(PROBE_SPLIT_CHARACTER);
parsedStreams.add(parseSubtitleStream(streamParts, 0, subtitleFile.getName())); parsedStreams.add(parseSubtitleStream(streamParts, 0, subtitleFile.getName(), false));
} }
} }
return parsedStreams; return parsedStreams;
@ -408,11 +408,12 @@ public final class FFMpegHelper {
* @param streamParts <p>A list of parameters belonging to a subtitle stream.</p> * @param streamParts <p>A list of parameters belonging to a subtitle stream.</p>
* @param relativeIndex <p>The relative index of the subtitle.</p> * @param relativeIndex <p>The relative index of the subtitle.</p>
* @param file <p>The file currently being converted.</p> * @param file <p>The file currently being converted.</p>
* @param isInternalStream <p>Whether the subtitle stream is in the main video file</p>
* @return <p>A SubtitleStream object.</p> * @return <p>A SubtitleStream object.</p>
* @throws NumberFormatException <p>If codec index contains a non-numeric value.</p> * @throws NumberFormatException <p>If codec index contains a non-numeric value.</p>
*/ */
private static SubtitleStream parseSubtitleStream(String[] streamParts, int relativeIndex, String file) private static SubtitleStream parseSubtitleStream(String[] streamParts, int relativeIndex, String file,
throws NumberFormatException { boolean isInternalStream) throws NumberFormatException {
String codecName = null; String codecName = null;
int absoluteIndex = -1; int absoluteIndex = -1;
String language = null; String language = null;
@ -428,7 +429,7 @@ public final class FFMpegHelper {
title = streamPart.replace("TAG:title=", ""); title = streamPart.replace("TAG:title=", "");
} }
} }
return new SubtitleStream(codecName, absoluteIndex, relativeIndex, language, title, file); return new SubtitleStream(codecName, absoluteIndex, relativeIndex, language, title, file, isInternalStream);
} }
} }