Adds filtering for audio description tracks
All checks were successful
KnarCraft/FFmpegConvert/pipeline/head This commit looks good
All checks were successful
KnarCraft/FFmpegConvert/pipeline/head This commit looks good
This commit is contained in:
parent
d46f12e690
commit
dae93b9f81
@ -20,6 +20,7 @@ import net.knarcraft.ffmpegconverter.converter.module.output.SetVideoCodecModule
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.AudioLanguageSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.ForcedFirstSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.MinimalSubtitleSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.SpecialAudioSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.StreamSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.SubtitleLanguageSorter;
|
||||
import net.knarcraft.ffmpegconverter.converter.sorter.SubtitleTitleSorter;
|
||||
@ -95,8 +96,9 @@ public class AnimeConverter extends AbstractConverter {
|
||||
modules.add(new MapAllModule<>(probeResult.getVideoStreams()));
|
||||
|
||||
//Get the first audio stream in accordance with chosen languages
|
||||
StreamSorter<AudioStream> audioSorter = new AudioLanguageSorter(this.audioLanguages).append(
|
||||
new ForcedFirstSorter<>(this.forcedAudioIndex));
|
||||
StreamSorter<AudioStream> audioSorter = new AudioLanguageSorter(this.audioLanguages)
|
||||
.append(new ForcedFirstSorter<>(this.forcedAudioIndex))
|
||||
.append(new SpecialAudioSorter(MinimalSubtitlePreference.REJECT));
|
||||
List<AudioStream> sortedAudio = audioSorter.chainSort(probeResult.getAudioStreams());
|
||||
modules.add(new MapAllModule<>(sortedAudio));
|
||||
modules.add(new SetDefaultStreamModule<>(sortedAudio, 0));
|
||||
|
@ -36,7 +36,7 @@ public class BurnSubtitleModule implements ConverterModule {
|
||||
FFMpegHelper.mapStream(command, videoStream);
|
||||
}
|
||||
|
||||
if (subtitleStream.getIsImageSubtitle()) {
|
||||
if (subtitleStream.isImageSubtitle()) {
|
||||
command.addOutputFileOption("-filter_complex",
|
||||
String.format("[%d:%d]scale=width=%d:height=%d,crop=w=%d:h=%d:x=0:y=out_h[sub];[%d:%d][sub]overlay",
|
||||
subtitleStream.getInputIndex(), subtitleStream.getAbsoluteIndex(), videoStream.getWidth(),
|
||||
|
@ -29,7 +29,7 @@ public class MinimalSubtitleSorter extends AbstractSorter<SubtitleStream> {
|
||||
List<SubtitleStream> fullSubtitles = new ArrayList<>();
|
||||
List<SubtitleStream> minimalSubtitles = new ArrayList<>();
|
||||
for (SubtitleStream subtitleStream : input) {
|
||||
if (subtitleStream.getIsFullSubtitle()) {
|
||||
if (subtitleStream.isFullSubtitle()) {
|
||||
fullSubtitles.add(subtitleStream);
|
||||
} else {
|
||||
minimalSubtitles.add(subtitleStream);
|
||||
|
@ -0,0 +1,67 @@
|
||||
package net.knarcraft.ffmpegconverter.converter.sorter;
|
||||
|
||||
import net.knarcraft.ffmpegconverter.property.MinimalSubtitlePreference;
|
||||
import net.knarcraft.ffmpegconverter.streams.AudioStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A sorter for sorting/filtering subtitles by a minimal subtitle preference
|
||||
*/
|
||||
public class SpecialAudioSorter extends AbstractSorter<AudioStream> {
|
||||
|
||||
private final MinimalSubtitlePreference minimalSubtitlePreference;
|
||||
|
||||
/**
|
||||
* Instantiates a new special audio preference sorter
|
||||
*
|
||||
* @param minimalSubtitlePreference <p>The minimal subtitle preference sort/filter by</p>
|
||||
*/
|
||||
public SpecialAudioSorter(@NotNull MinimalSubtitlePreference minimalSubtitlePreference) {
|
||||
this.minimalSubtitlePreference = minimalSubtitlePreference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<AudioStream> sort(@NotNull List<AudioStream> input) {
|
||||
// Split all subtitles into full and minimal
|
||||
List<AudioStream> normalAudio = new ArrayList<>();
|
||||
List<AudioStream> specialAudio = new ArrayList<>();
|
||||
for (AudioStream audioStream : input) {
|
||||
if (audioStream.isSpecialAudio()) {
|
||||
specialAudio.add(audioStream);
|
||||
} else {
|
||||
normalAudio.add(audioStream);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort/filter subtitles based on full and minimal
|
||||
switch (this.minimalSubtitlePreference) {
|
||||
case REJECT -> {
|
||||
// Only return full subtitles
|
||||
return normalAudio;
|
||||
}
|
||||
case REQUIRE -> {
|
||||
// Only return minimal subtitles
|
||||
return specialAudio;
|
||||
}
|
||||
case NO_PREFERENCE -> {
|
||||
// Don't change order
|
||||
return input;
|
||||
}
|
||||
case PREFER -> {
|
||||
// Sort minimal subtitles first, and full subtitles last
|
||||
specialAudio.addAll(normalAudio);
|
||||
return specialAudio;
|
||||
}
|
||||
case AVOID -> {
|
||||
// Sort full subtitles first, and minimal subtitles last
|
||||
normalAudio.addAll(specialAudio);
|
||||
return normalAudio;
|
||||
}
|
||||
default -> throw new IllegalStateException("Unknown enum value encountered");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ import java.util.Map;
|
||||
public class AudioStream extends AbstractStream implements StreamObject {
|
||||
|
||||
private final int channels;
|
||||
private final boolean isSpecialAudio;
|
||||
|
||||
/**
|
||||
* Instantiates a new audio stream
|
||||
@ -22,6 +23,16 @@ public class AudioStream extends AbstractStream implements StreamObject {
|
||||
public AudioStream(@NotNull Map<StreamTag, String> streamInfo, int inputIndex, int relativeIndex) {
|
||||
super(streamInfo, inputIndex, relativeIndex);
|
||||
this.channels = ValueParsingHelper.parseInt(streamInfo.get(StreamTag.CHANNELS), 0);
|
||||
this.isSpecialAudio = checkIfIsSpecialAudio();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this audio stream is a special audio stream such as audio description or music only
|
||||
*
|
||||
* @return <p>True if this audio stream is a special audio stream</p>
|
||||
*/
|
||||
public boolean isSpecialAudio() {
|
||||
return this.isSpecialAudio;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,4 +49,14 @@ public class AudioStream extends AbstractStream implements StreamObject {
|
||||
return 'a';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this audio stream is a special audio stream
|
||||
*
|
||||
* @return <p>True if this is a special audio stream</p>
|
||||
*/
|
||||
private boolean checkIfIsSpecialAudio() {
|
||||
String titleLowercase = getTitle().toLowerCase().trim();
|
||||
return titleLowercase.matches(".*audio description.*");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
|
||||
final private boolean isFullSubtitle;
|
||||
final private boolean isImageSubtitle;
|
||||
private final boolean isFullSubtitle;
|
||||
private final boolean isImageSubtitle;
|
||||
|
||||
/**
|
||||
* Instantiates a new subtitle stream
|
||||
@ -21,7 +21,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
*/
|
||||
public SubtitleStream(@NotNull Map<StreamTag, String> streamInfo, int inputIndex, int relativeIndex) {
|
||||
super(streamInfo, inputIndex, relativeIndex);
|
||||
this.isFullSubtitle = isFullSubtitle();
|
||||
this.isFullSubtitle = checkIfIsFullSubtitle();
|
||||
this.isImageSubtitle = codecName != null &&
|
||||
(getCodecName().equals("hdmv_pgs_subtitle") || getCodecName().equals("dvd_subtitle"));
|
||||
}
|
||||
@ -31,7 +31,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
*
|
||||
* @return <p>Whether the subtitles is an image subtitle.</p>
|
||||
*/
|
||||
public boolean getIsImageSubtitle() {
|
||||
public boolean isImageSubtitle() {
|
||||
return this.isImageSubtitle;
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
*
|
||||
* @return <p>Whether the subtitle is a full subtitle.</p>
|
||||
*/
|
||||
public boolean getIsFullSubtitle() {
|
||||
public boolean isFullSubtitle() {
|
||||
return this.isFullSubtitle;
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
*
|
||||
* @return <p>True if the subtitle translates everything.</p>
|
||||
*/
|
||||
private boolean isFullSubtitle() {
|
||||
private boolean checkIfIsFullSubtitle() {
|
||||
String titleLowercase = getTitle().toLowerCase().trim();
|
||||
return !titleLowercase.matches(".*si(ng|gn)s?[ &/a-z]+songs?.*") &&
|
||||
!titleLowercase.matches(".*songs?[ &/a-z]+si(gn|ng)s?.*") &&
|
||||
@ -59,7 +59,8 @@ public class SubtitleStream extends AbstractStream implements StreamObject {
|
||||
!titleLowercase.matches("songs?") &&
|
||||
!titleLowercase.matches(".*signs only.*") &&
|
||||
!titleLowercase.matches(".* signs .*") &&
|
||||
!titleLowercase.matches("signs@.*");
|
||||
!titleLowercase.matches("signs@.*") &&
|
||||
!titleLowercase.matches("signs -.*");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user