The correct object type for the streams with the selected codec type.
+ * @param The correct object type for the streams with the selected codec type.
* @return A potentially shorter list of streams.
*/
@SuppressWarnings("unchecked")
@@ -63,7 +58,8 @@ public abstract class AbstractConverter implements Converter {
/**
* Filters and sorts audio streams according to chosen languages
- * @param audioStreams A list of audio streams.
+ *
+ * @param audioStreams A list of audio streams.
* @param audioLanguages A list of languages.
* @return A list containing just audio tracks of chosen languages, sorted in order of languages.
*/
@@ -83,8 +79,9 @@ public abstract class AbstractConverter implements Converter {
/**
* Filters and sorts subtitle streams according to chosen languages
- * @param subtitleStreams A list of subtitle streams.
- * @param subtitleLanguages A list of languages.
+ *
+ * @param subtitleStreams A list of subtitle streams.
+ * @param subtitleLanguages A list of languages.
* @param preventSignsAndSongs Whether partial subtitles should be avoided.
* @return A list containing just subtitles of chosen languages, sorted in order of languages.
*/
@@ -108,6 +105,7 @@ public abstract class AbstractConverter implements Converter {
/**
* Escapes special characters which can cause trouble for ffmpeg
+ *
* @param fileName The filename to escape.
* @return A filename with known special characters escaped.
*/
@@ -120,13 +118,19 @@ public abstract class AbstractConverter implements Converter {
.replace("[", "\\[");
}
-
+ /**
+ * Gets all valid input formats for the converter
+ *
+ * @return A list of valid input formats
+ */
+ public abstract String[] getValidFormats();
/**
* Adds audio to a command
- * @param command The command to add audio to.
+ *
+ * @param command The command to add audio to.
* @param audioStream The audio stream to be added.
- * @param toStereo Whether to convert the audio stream to stereo.
+ * @param toStereo Whether to convert the audio stream to stereo.
*/
void addAudioStreams(List command, AudioStream audioStream, boolean toStereo) {
if (audioStream != null) {
@@ -141,10 +145,11 @@ public abstract class AbstractConverter implements Converter {
/**
* Adds subtitles and video mapping to a command
- * @param command The list containing the rest of the command.
+ *
+ * @param command The list containing the rest of the command.
* @param subtitleStream The subtitle stream to be used.
- * @param videoStream The video stream to be used.
- * @param file The file to convert.
+ * @param videoStream The video stream to be used.
+ * @param file The file to convert.
*/
void addSubtitles(List command, SubtitleStream subtitleStream, VideoStream videoStream, File file) {
//No appropriate subtitle was found. Just add the video stream.
@@ -165,9 +170,10 @@ public abstract class AbstractConverter implements Converter {
/**
* Adds subtitle commands to a command list
- * @param command The list containing the FFmpeg commands.
+ *
+ * @param command The list containing the FFmpeg commands.
* @param subtitleStream The subtitle stream to add.
- * @param videoStream The video stream to burn the subtitle into.
+ * @param videoStream The video stream to burn the subtitle into.
*/
private void addSubtitle(List command, SubtitleStream subtitleStream, VideoStream videoStream) {
command.add("-map");
@@ -181,9 +187,10 @@ public abstract class AbstractConverter implements Converter {
/**
* Adds image subtitle commands to a command list
- * @param command The list containing the FFmpeg commands.
+ *
+ * @param command The list containing the FFmpeg commands.
* @param subtitleStream The subtitle stream to add.
- * @param videoStream The video stream to burn the subtitle into.
+ * @param videoStream The video stream to burn the subtitle into.
*/
private void addInternalImageSubtitle(List command, SubtitleStream subtitleStream, VideoStream videoStream) {
command.add("-filter_complex");
@@ -194,9 +201,10 @@ public abstract class AbstractConverter implements Converter {
/**
* Adds external image subtitle commands to a command list
- * @param command The list containing the FFmpeg commands.
+ *
+ * @param command The list containing the FFmpeg commands.
* @param externalImageSubtitle The external image subtitle stream to add.
- * @param videoStream The video stream to burn the subtitle into.
+ * @param videoStream The video stream to burn the subtitle into.
*/
private void addExternalImageSubtitle(List command, SubtitleStream externalImageSubtitle,
VideoStream videoStream) {
diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java
index b286595..75494ad 100644
--- a/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java
+++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/AnimeConverter.java
@@ -4,24 +4,31 @@ 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 net.knarcraft.ffmpegconverter.utility.FileUtil;
+import net.knarcraft.ffmpegconverter.utility.OutputUtil;
import java.io.File;
import java.io.IOException;
import java.util.List;
-public class AnimeConverter extends Converter {
- private String[] audioLang;
- private String[] subtitleLang;
- private boolean toStereo;
- private boolean preventSignsAndSongs;
+/**
+ * A converter mainly designed for converting anime to web-playable mp4
+ */
+public class AnimeConverter extends AbstractConverter {
+ private final String[] audioLang;
+ private final String[] subtitleLang;
+ private final boolean toStereo;
+ private final boolean preventSignsAndSongs;
/**
* Instantiates a new anime converter
- * @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 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,
@@ -34,51 +41,49 @@ public class AnimeConverter extends Converter {
this.preventSignsAndSongs = preventSignsAndSongs;
}
- /**
- * Converts the given file
- * @param file The file to convert.
- * @throws IOException If the file cannot be converted.
- */
+ @Override
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.
+ * @param file The file to process.
* @throws IOException If the BufferedReader fails.
*/
private void processFile(File folder, File file) throws IOException {
- List streams = probeFile(ffprobePath, file);
+ List streams = FFMpegHelper.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();
- printl("Preparing to start process...");
- printl("Converting " + file);
+ String newPath = FileUtil.getNonCollidingFilename(folder.getAbsolutePath() + File.separator +
+ FileUtil.stripExtension(file) + ".mp4", "mp4");
+ OutputUtil.println();
+ OutputUtil.println("Preparing to start process...");
+ OutputUtil.println("Converting " + file);
String[] command = builderCommand(ffmpegPath, file.getName(), streams, newPath, file);
ProcessBuilder processBuilder = new ProcessBuilder(command);
- convertProcess(processBuilder, folder);
+ FFMpegHelper.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.
+ * @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 streams, String outFile,
File file) {
- List command = ffmpegWebVideo(executable, fileName);
+ List command = FFMpegHelper.getFFMpegWebVideoCommand(executable, fileName);
if (this.DEBUG) {
- addDebug(command, 50, 120);
+ FFMpegHelper.addDebugArguments(command, 50, 120);
}
List audioStreams = filterAudioStreams(filterStreamsByType(streams, "audio"), audioLang);
@@ -102,77 +107,15 @@ public class AnimeConverter extends Converter {
subtitleStream = subtitleStreams.get(0);
}
- addAudioStreams(command, audioStream);
- addSubtitles(command, subtitleStream, videoStream, fileName, file);
+ addAudioStreams(command, audioStream, toStereo);
+ addSubtitles(command, subtitleStream, videoStream, file);
command.add(outFile);
return command.toArray(new String[0]);
}
- /**
- * Adds audio to a command
- * @param command The command to add audio to.
- * @param audioStream The audio stream to be added.
- */
- private void addAudioStreams(List command, AudioStream audioStream) {
- 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");
- }
- }
- }
-
- /**
- * Adds subtitles and video mapping to a command
- * @param command The list containing the rest of the command.
- * @param subtitleStream The subtitle stream to be used.
- * @param videoStream The video stream to be used.
- * @param fileName The name of the file which is converted.
- * @param file The file to convert.
- */
- private void addSubtitles(List command, SubtitleStream subtitleStream, VideoStream videoStream,
- String fileName, File file) {
- File folder = file.getParentFile();
- String externalImageSubtitle = hasExternalImageSubtitle(folder.getAbsolutePath(), fileName);
- String externalSubtitle = hasExternalSubtitle(folder.getAbsolutePath(), fileName);
- if (subtitleStream != null && subtitleStream.getIsImageSubtitle()) {
- command.add("-filter_complex");
- String filter = String.format("[0:v:%d][0:%d]overlay", videoStream.getAbsoluteIndex(),
- subtitleStream.getAbsoluteIndex());
- command.add(filter);
- } else if (subtitleStream != null) {
- command.add("-map");
- command.add(String.format("0:%d", videoStream.getAbsoluteIndex()));
- command.add("-vf");
- String safeFileName = escapeSpecialCharactersInFileName(fileName);
- String subtitleCommand = String.format("subtitles='%s':si=%d", safeFileName,
- subtitleStream.getRelativeIndex());
- command.add(subtitleCommand);
- } else if (!externalSubtitle.equals("")) {
- command.add("-map");
- command.add(String.format("0:%d", videoStream.getAbsoluteIndex()));
- command.add("-vf");
- String subtitleCommand = String.format("subtitles='%s'", escapeSpecialCharactersInFileName(externalSubtitle));
- command.add(subtitleCommand);
- } else if (!externalImageSubtitle.equals("")) {
- command.add("-i");
- command.add(stripExtension(fileName) + externalImageSubtitle);
- command.add("-filter_complex");
- command.add(String.format("[1:s]scale=width=1272:height=720,crop=w=1272:h=720:x=0:y=out_h[sub];[%d:v]" +
- "[sub]overlay", videoStream.getAbsoluteIndex()));
- command.add("-profile:v");
- command.add("baseline");
- } else {
- command.add("-map");
- command.add(String.format("0:%d", videoStream.getAbsoluteIndex()));
- }
- }
-
@Override
public String[] getValidFormats() {
- return VIDEO_FORMATS;
+ return videoFormats;
}
}
diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java
index a0c8224..999a452 100644
--- a/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java
+++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/AudioConverter.java
@@ -2,19 +2,25 @@ package net.knarcraft.ffmpegconverter.converter;
import net.knarcraft.ffmpegconverter.streams.AudioStream;
import net.knarcraft.ffmpegconverter.streams.StreamObject;
+import net.knarcraft.ffmpegconverter.utility.FFMpegHelper;
+import net.knarcraft.ffmpegconverter.utility.FileUtil;
import java.io.File;
import java.io.IOException;
import java.util.List;
-public class AudioConverter extends Converter {
- private String newExt;
+/**
+ * A converter for converting audio files
+ */
+public class AudioConverter extends AbstractConverter {
+ private final String newExt;
/**
* Instantiates a new audio converter
+ *
* @param ffprobePath Path/command to ffprobe.
- * @param ffmpegPath Path/command to ffmpeg.
- * @param newExt The extension of the new file.
+ * @param ffmpegPath Path/command to ffmpeg.
+ * @param newExt The extension of the new file.
*/
public AudioConverter(String ffprobePath, String ffmpegPath, String newExt) {
this.ffprobePath = ffprobePath;
@@ -24,30 +30,32 @@ public class AudioConverter extends Converter {
/**
* Processes a file conversion
+ *
* @param folder The work folder containing the file.
- * @param file The file to convert.
+ * @param file The file to convert.
* @param newExt The extension of the new file.
* @throws IOException If the file cannot be converted.
*/
private void processFile(File folder, File file, String newExt) throws IOException {
- List streams = probeFile(ffprobePath, file);
+ List streams = FFMpegHelper.probeFile(ffprobePath, file);
if (streams.size() == 0) {
throw new IllegalArgumentException("The file has no streams");
}
- String newPath = stripExtension(file) + "." + newExt;
- convertProcess(new ProcessBuilder(builderCommand(ffmpegPath, file.getName(), streams, newPath)), folder);
+ String newPath = FileUtil.stripExtension(file) + "." + newExt;
+ FFMpegHelper.convertProcess(new ProcessBuilder(builderCommand(ffmpegPath, file.getName(), streams, newPath)), 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.
+ * @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 streams, String outFile) {
- List command = generalFile(executable, fileName);
+ List command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, fileName);
List audioStreams = filterStreamsByType(streams, "audio");
AudioStream audioStream = null;
if (audioStreams.size() > 0) {
@@ -63,7 +71,7 @@ public class AudioConverter extends Converter {
@Override
public String[] getValidFormats() {
- return AUDIO_FORMATS;
+ return audioFormats;
}
@Override
diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/Converter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/Converter.java
index 8fab2dd..17acb80 100644
--- a/src/main/java/net/knarcraft/ffmpegconverter/converter/Converter.java
+++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/Converter.java
@@ -10,6 +10,7 @@ public interface Converter {
/**
* Converts the given file
+ *
* @param file The file to convert.
* @throws IOException If the file cannot be converted.
*/
diff --git a/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java b/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java
index 4f8168c..d7f2cce 100644
--- a/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java
+++ b/src/main/java/net/knarcraft/ffmpegconverter/converter/VideoConverter.java
@@ -2,20 +2,27 @@ 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 net.knarcraft.ffmpegconverter.utility.FFMpegHelper;
+import net.knarcraft.ffmpegconverter.utility.FileUtil;
import java.io.File;
import java.io.IOException;
import java.util.List;
-public class VideoConverter extends Converter {
- private String newExt;
+/**
+ * A converter for converting video files
+ */
+public class VideoConverter extends AbstractConverter {
+ private final String newExt;
/**
* Instantiates a new video converter
+ *
* @param ffprobePath Path/command to ffprobe.
- * @param ffmpegPath Path/command to ffmpeg.
- * @param newExt The extension of the new file.
+ * @param ffmpegPath Path/command to ffmpeg.
+ * @param newExt The extension of the new file.
*/
public VideoConverter(String ffprobePath, String ffmpegPath, String newExt) {
this.ffprobePath = ffprobePath;
@@ -25,52 +32,56 @@ public class VideoConverter extends Converter {
/**
* 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.
+ * @param file The file to process.
* @throws IOException If the BufferedReader fails.
*/
private void processFile(File folder, File file, String newExt) throws IOException {
- List streams = probeFile(ffprobePath, file);
+ List streams = FFMpegHelper.probeFile(ffprobePath, file);
if (streams.size() == 0) {
throw new IllegalArgumentException("The file has no streams");
}
- String newPath = fileCollisionPrevention(folder.getAbsolutePath() + File.separator + stripExtension(file) + "." + newExt, newExt);
- convertProcess(new ProcessBuilder(builderCommand(ffmpegPath, file.getName(), streams, newPath, folder)), folder);
+ String newPath = FileUtil.getNonCollidingFilename(folder.getAbsolutePath() + File.separator +
+ FileUtil.stripExtension(file) + "." + newExt, newExt);
+ FFMpegHelper.convertProcess(new ProcessBuilder(builderCommand(ffmpegPath, file, streams, newPath)), 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.
+ * @param file 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 streams, String outFile, File folder) {
- List command = generalFile(executable, fileName);
+ private String[] builderCommand(String executable, File file, List streams, String outFile) {
+ List command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName());
if (this.DEBUG) {
- addDebug(command, 50, 120);
+ FFMpegHelper.addDebugArguments(command, 50, 120);
}
List audioStreams = filterStreamsByType(streams, "audio");
List videoStreams = filterStreamsByType(streams, "video");
+ List subtitleStreams = filterStreamsByType(streams, "subtitle");
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);
}
-
- boolean videoAdded = addSubtitles(command, folder, fileName, videoStream);
-
- if (!videoAdded && videoStreams.size() > 0) {
- command.add("-map");
- command.add("0:" + videoStream);
+ if (subtitleStreams.size() > 0) {
+ subtitleStream = subtitleStreams.get(0);
}
+
+ addSubtitles(command, subtitleStream, videoStream, file);
+
if (audioStreams.size() > 0) {
command.add("-map");
command.add("0:" + audioStream);
@@ -82,39 +93,9 @@ public class VideoConverter extends Converter {
return command.toArray(new String[0]);
}
- /**
- * Adds subtitles to a command
- * @param command The command to add to.
- * @param folder The folder containing the file to be converted.
- * @param fileName The name of the file to be converted.
- * @param videoStream The video stream to be added.
- * @return True if a video stream was added.
- */
- private boolean addSubtitles(List command, File folder, String fileName, VideoStream videoStream) {
- String externalSubtitle = hasExternalSubtitle(folder.getAbsolutePath(), fileName);
- String externalImageSubtitle = hasExternalImageSubtitle(folder.getAbsolutePath(), fileName);
- if (!externalSubtitle.equals("")) {
- command.add("-vf");
- command.add("subtitles=" + externalSubtitle);
- } else if (!externalImageSubtitle.equals("")) {
- command.add("-i");
- command.add(externalImageSubtitle);
- if (this.DEBUG) {
- addDebug(command, 50, 120);
- }
- //TODO: Scale subtitles to video
- command.add("-filter_complex");
- command.add("[1:s]scale=width=1920:height=800,crop=w=1920:h=800:x=0:y=out_h[sub];[" + videoStream +
- ":v][sub]overlay");
- command.add("-profile:v");
- command.add("baseline");
- return true;
- }
- return false;
- }
-
/**
* Converts the audio of a video to stereo
+ *
* @param command The command list to add to.
*/
private void convertToStereo(List command) {
@@ -124,7 +105,7 @@ public class VideoConverter extends Converter {
@Override
public String[] getValidFormats() {
- return VIDEO_FORMATS;
+ return videoFormats;
}
@Override