All checks were successful
KnarCraft/FFmpegConvert/master This commit looks good
133 lines
5.3 KiB
Java
133 lines
5.3 KiB
Java
package net.knarcraft.ffmpegconverter.converter;
|
|
|
|
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 java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
public class AnimeConverter extends Converter {
|
|
private String[] audioLang;
|
|
private String[] subtitleLang;
|
|
private boolean toStereo;
|
|
private boolean preventSignsAndSongs;
|
|
private boolean debug = false;
|
|
|
|
/**
|
|
* @param ffprobePath Path/command to ffprobe
|
|
* @param ffmpegPath Path/command to ffmpeg
|
|
* @param audioLang List of wanted audio languages in descending order
|
|
* @param subtitleLang List of wanted subtitle languages in descending order
|
|
* @param toStereo Convert video with several audio channels to stereo
|
|
* @param preventSignsAndSongs Prevent subtitles only converting signs and songs (not speech)
|
|
*/
|
|
public AnimeConverter(String ffprobePath, String ffmpegPath, String[] audioLang, String[] subtitleLang, boolean toStereo, boolean preventSignsAndSongs) {
|
|
this.ffprobePath = ffprobePath;
|
|
this.ffmpegPath = ffmpegPath;
|
|
this.audioLang = audioLang;
|
|
this.subtitleLang = subtitleLang;
|
|
this.toStereo = toStereo;
|
|
this.preventSignsAndSongs = preventSignsAndSongs;
|
|
}
|
|
|
|
public void convert(File file) throws IOException {
|
|
processFile(file.getParentFile(), file);
|
|
}
|
|
|
|
/**
|
|
* Reads streams from a file, and converts it to an mp4.
|
|
*
|
|
* @param folder The folder of the file to process
|
|
* @param file The file to process
|
|
* @throws IOException If the BufferedReader fails
|
|
*/
|
|
private void processFile(File folder, File file) throws IOException {
|
|
List<StreamObject> streams = probeFile(ffprobePath, file);
|
|
if (streams.isEmpty()) {
|
|
throw new IllegalArgumentException("The file has no valid streams. Please make sure the file exists and is not corrupt.");
|
|
}
|
|
String newPath = fileCollisionPrevention(folder.getAbsolutePath() + File.separator + stripExtension(file) + ".mp4", "mp4");
|
|
printl("Preparing to start process...");
|
|
String[] command = builderCommand(ffmpegPath, file.getName(), streams, newPath);
|
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
|
convertProcess(processBuilder, folder);
|
|
}
|
|
|
|
/**
|
|
* Generates a command for a ProcessBuilder.
|
|
*
|
|
* @param executable The executable file for ffmpeg
|
|
* @param fileName The input file
|
|
* @param streams A list of ffprobe streams
|
|
* @param outFile The output file
|
|
* @return A list of commands
|
|
*/
|
|
private String[] builderCommand(String executable, String fileName, List<StreamObject> streams, String outFile) {
|
|
List<String> command = ffmpegWebVideo(executable, fileName);
|
|
|
|
if (this.debug) {
|
|
addDebug(command, 50, 120);
|
|
}
|
|
|
|
List<AudioStream> audioStreams = filterStreamsByType(streams, "audio");
|
|
List<VideoStream> videoStreams = filterStreamsByType(streams, "video");
|
|
List<SubtitleStream> subtitleStreams = filterStreamsByType(streams, "subtitle");
|
|
|
|
audioStreams = filterAudioStreams(audioStreams, audioLang);
|
|
subtitleStreams = filterSubtitleStreams(subtitleStreams, subtitleLang, preventSignsAndSongs);
|
|
|
|
VideoStream videoStream = null;
|
|
AudioStream audioStream = null;
|
|
SubtitleStream subtitleStream = null;
|
|
if (videoStreams.size() > 0) {
|
|
videoStream = videoStreams.get(0);
|
|
}
|
|
if (audioStreams.size() > 0) {
|
|
audioStream = audioStreams.get(0);
|
|
}
|
|
if (subtitleStreams.size() > 0) {
|
|
subtitleStream = subtitleStreams.get(0);
|
|
}
|
|
|
|
if (videoStream == null) {
|
|
throw new IllegalArgumentException("The file does not have any valid video streams.");
|
|
}
|
|
|
|
if (audioStream != null) {
|
|
command.add("-map");
|
|
command.add("0:" + audioStream.getAbsoluteIndex());
|
|
if (toStereo && audioStream.getChannels() > 2) {
|
|
command.add("-af");
|
|
command.add("pan=stereo|FL=FC+0.30*FL+0.30*BL|FR=FC+0.30*FR+0.30*BR");
|
|
}
|
|
}
|
|
|
|
if (subtitleStream != null && subtitleStream.getIsImageSubtitle()) {
|
|
command.add("-filter_complex");
|
|
command.add("[0:v:" + videoStream.getAbsoluteIndex() + "][0:" + subtitleStream.getAbsoluteIndex() + "]overlay");
|
|
} else if (subtitleStream != null) {
|
|
command.add("-map");
|
|
command.add("0:" + videoStream.getAbsoluteIndex());
|
|
command.add("-vf");
|
|
String safeFileName = escapeSpecialCharactersInFileName(fileName);
|
|
String subtitleCommand = String.format("subtitles=\"%s\"", safeFileName);
|
|
command.add(subtitleCommand);
|
|
} else {
|
|
command.add("-map");
|
|
command.add("0:" + videoStream.getAbsoluteIndex());
|
|
}
|
|
|
|
command.add(outFile);
|
|
return command.toArray(new String[0]);
|
|
}
|
|
|
|
@Override
|
|
public String[] getValidFormats() {
|
|
return VIDEO_FORMATS;
|
|
}
|
|
}
|