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.
96 lines
4.5 KiB
Java
96 lines
4.5 KiB
Java
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.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* A converter mainly designed for converting anime to web-playable mp4
|
|
*/
|
|
public class AnimeConverter extends AbstractConverter {
|
|
|
|
private final String[] audioLanguages;
|
|
private final String[] subtitleLanguages;
|
|
private final boolean toStereo;
|
|
private final boolean preventSignsAndSongs;
|
|
private final int forcedAudioIndex;
|
|
private final int forcedSubtitleIndex;
|
|
private final String subtitleNameFilter;
|
|
|
|
/**
|
|
* Instantiates a new anime converter
|
|
*
|
|
* @param ffprobePath <p>Path/command to ffprobe.</p>
|
|
* @param ffmpegPath <p>Path/command to ffmpeg.</p>
|
|
* @param audioLanguages <p>List of wanted audio languages in descending order.</p>
|
|
* @param subtitleLanguages <p>List of wanted subtitle languages in descending order.</p>
|
|
* @param toStereo <p>Convert video with several audio channels to stereo.</p>
|
|
* @param preventSignsAndSongs <p>Prevent subtitles only converting signs and songs (not speech).</p>
|
|
* @param forcedAudioIndex <p>A specific audio stream to force. 0-indexed from the first audio stream found</p>
|
|
* @param forcedSubtitleIndex <p>A specific subtitle stream to force. 0-indexed for the first subtitle stream found</p>
|
|
*/
|
|
public AnimeConverter(String ffprobePath, String ffmpegPath, String[] audioLanguages, String[] subtitleLanguages,
|
|
boolean toStereo, boolean preventSignsAndSongs, int forcedAudioIndex, int forcedSubtitleIndex,
|
|
String subtitleNameFilter) {
|
|
super("mp4");
|
|
this.ffprobePath = ffprobePath;
|
|
this.ffmpegPath = ffmpegPath;
|
|
this.audioLanguages = audioLanguages;
|
|
this.subtitleLanguages = subtitleLanguages;
|
|
this.toStereo = toStereo;
|
|
this.preventSignsAndSongs = preventSignsAndSongs;
|
|
this.forcedAudioIndex = forcedAudioIndex;
|
|
this.forcedSubtitleIndex = forcedSubtitleIndex;
|
|
this.subtitleNameFilter = subtitleNameFilter;
|
|
}
|
|
|
|
@Override
|
|
public String[] generateConversionCommand(@NotNull String executable, @NotNull StreamProbeResult probeResult,
|
|
@NotNull String outFile) {
|
|
FFMpegCommand command = FFMpegHelper.getFFMpegWebVideoCommand(executable, probeResult.parsedFiles());
|
|
List<StreamObject> streams = probeResult.parsedStreams();
|
|
if (this.debug) {
|
|
FFMpegHelper.addDebugArguments(command, 50, 120);
|
|
}
|
|
|
|
//Get the first audio stream in accordance with chosen languages
|
|
List<AudioStream> audioStreams = filterAudioStreams(filterStreamsByType(streams, AudioStream.class),
|
|
this.audioLanguages);
|
|
AudioStream audioStream = getNthAudioSteam(new ArrayList<>(audioStreams), Math.max(this.forcedAudioIndex, 0));
|
|
|
|
//Get the first subtitle stream in accordance with chosen languages and signs and songs prevention
|
|
List<SubtitleStream> allSubtitleStreams = filterStreamsByType(streams, SubtitleStream.class);
|
|
List<SubtitleStream> subtitleStreams = filterSubtitleStreams(allSubtitleStreams, this.subtitleLanguages,
|
|
this.preventSignsAndSongs, this.subtitleNameFilter);
|
|
SubtitleStream subtitleStream = getNthSubtitleStream(new ArrayList<>(subtitleStreams),
|
|
Math.max(this.forcedSubtitleIndex, 0));
|
|
|
|
//Get the first video stream
|
|
VideoStream videoStream = getNthVideoStream(streams, 0);
|
|
if (videoStream == null) {
|
|
throw new IllegalArgumentException("The selected video stream does not exist");
|
|
}
|
|
|
|
//Add streams to output file
|
|
FFMpegHelper.addAudioStream(command, audioStream, this.toStereo);
|
|
FFMpegHelper.addSubtitleAndVideoStream(command, subtitleStream, videoStream);
|
|
|
|
command.setOutputFile(outFile);
|
|
return command.getResult();
|
|
}
|
|
|
|
@Override
|
|
public String[] getValidFormats() {
|
|
return this.videoFormats;
|
|
}
|
|
|
|
}
|