Removes some code duplication and makes converter code utilize the StreamObject interface
	
		
			
	
		
	
	
		
	
		
			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:
		| @@ -19,11 +19,11 @@ import java.util.List; | ||||
|  */ | ||||
| public abstract class AbstractConverter implements Converter { | ||||
|     final boolean DEBUG = false; | ||||
|     private final String newExtension; | ||||
|     String ffprobePath; | ||||
|     String ffmpegPath; | ||||
|     String[] audioFormats; | ||||
|     String[] videoFormats; | ||||
|     private final String newExtension; | ||||
|  | ||||
|     /** | ||||
|      * Initializes variables used by the abstract converter | ||||
| @@ -42,18 +42,18 @@ public abstract class AbstractConverter implements Converter { | ||||
|     /** | ||||
|      * Filters parsed streams into one of the stream types | ||||
|      * | ||||
|      * @param streams   <p>A list of stream objects.</p> | ||||
|      * @param codecType <p>The codec type of the streams to select.</p> | ||||
|      * @param <G>       <p>The correct object type for the streams with the selected codec type.</p> | ||||
|      * @param streams <p>A list of stream objects.</p> | ||||
|      * @param clazz   <p>The class to filter</p> | ||||
|      * @param <G>     <p>The correct object type for the streams with the selected codec type.</p> | ||||
|      * @return <p>A potentially shorter list of streams.</p> | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     static <G extends StreamObject> List<G> filterStreamsByType(List<StreamObject> streams, String codecType) { | ||||
|     static <G extends StreamObject> List<G> filterStreamsByType(List<StreamObject> streams, Class<?> clazz) { | ||||
|         Iterator<StreamObject> i = streams.iterator(); | ||||
|         List<G> newStreams = new ArrayList<>(); | ||||
|         while (i.hasNext()) { | ||||
|             StreamObject next = i.next(); | ||||
|             if (next.getCodecType().equals(codecType)) { | ||||
|             if (next.getClass() == clazz) { | ||||
|                 newStreams.add((G) next); | ||||
|             } | ||||
|         } | ||||
| @@ -143,6 +143,7 @@ public abstract class AbstractConverter implements Converter { | ||||
|             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"); | ||||
|                 //command.add("pan=stereo|FL < 1.0*FL + 0.707*FC + 0.707*BL|FR < 1.0*FR + 0.707*FC + 0.707*BR"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -155,7 +156,7 @@ public abstract class AbstractConverter implements Converter { | ||||
|      * @param videoStream    <p>The video stream to be used.</p> | ||||
|      * @param file           <p>The file to convert.</p> | ||||
|      */ | ||||
|     void addSubtitles(List<String> command, SubtitleStream subtitleStream, VideoStream videoStream, File file) { | ||||
|     void addSubtitlesAndVideo(List<String> command, SubtitleStream subtitleStream, VideoStream videoStream, File file) { | ||||
|         //No appropriate subtitle was found. Just add the video stream. | ||||
|         if (subtitleStream == null) { | ||||
|             command.add("-map"); | ||||
| @@ -242,4 +243,52 @@ public abstract class AbstractConverter implements Converter { | ||||
|         ProcessBuilder processBuilder = new ProcessBuilder(builderCommand(ffmpegPath, file, streams, newPath)); | ||||
|         FFMpegHelper.convertProcess(processBuilder, folder); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the first audio stream from a list of streams | ||||
|      * | ||||
|      * @param streams <p>A list of all streams.</p> | ||||
|      * @return <p>The first audio stream found or null if no audio streams were found.</p> | ||||
|      */ | ||||
|     AudioStream getFirstAudioSteam(List<StreamObject> streams) { | ||||
|         List<AudioStream> audioStreams = filterStreamsByType(streams, AudioStream.class); | ||||
|         AudioStream audioStream = null; | ||||
|         if (audioStreams.size() > 0) { | ||||
|             audioStream = audioStreams.get(0); | ||||
|         } | ||||
|         return audioStream; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the first subtitle stream from a list of streams | ||||
|      * | ||||
|      * @param streams <p>A list of all streams.</p> | ||||
|      * @return <p>The first subtitle stream found or null if no subtitle streams were found.</p> | ||||
|      */ | ||||
|     SubtitleStream getFirstSubtitleStream(List<StreamObject> streams) { | ||||
|         List<SubtitleStream> subtitleStreams = filterStreamsByType(streams, SubtitleStream.class); | ||||
|         SubtitleStream subtitleStream = null; | ||||
|         if (subtitleStreams.size() > 0) { | ||||
|             subtitleStream = subtitleStreams.get(0); | ||||
|         } | ||||
|         return subtitleStream; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the first video stream from a list of streams | ||||
|      * | ||||
|      * @param streams <p>A list of all streams.</p> | ||||
|      * @return <p>The first video stream found or null if no video streams were found.</p> | ||||
|      */ | ||||
|     VideoStream getFirstVideoStream(List<StreamObject> streams) { | ||||
|         List<VideoStream> videoStreams = filterStreamsByType(streams, VideoStream.class); | ||||
|         VideoStream videoStream = null; | ||||
|         if (videoStreams.size() > 0) { | ||||
|             videoStream = videoStreams.get(0); | ||||
|         } | ||||
|         if (videoStream == null) { | ||||
|             throw new IllegalArgumentException("The file does not have any valid video streams."); | ||||
|         } | ||||
|         return videoStream; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,19 +5,18 @@ 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.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 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 String[] audioLanguages; | ||||
|     private final String[] subtitleLanguages; | ||||
|     private final boolean toStereo; | ||||
|     private final boolean preventSignsAndSongs; | ||||
|  | ||||
| @@ -26,18 +25,18 @@ public class AnimeConverter extends AbstractConverter { | ||||
|      * | ||||
|      * @param ffprobePath          <p>Path/command to ffprobe.</p> | ||||
|      * @param ffmpegPath           <p>Path/command to ffmpeg.</p> | ||||
|      * @param audioLang            <p>List of wanted audio languages in descending order.</p> | ||||
|      * @param subtitleLang         <p>List of wanted subtitle languages in descending order.</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> | ||||
|      */ | ||||
|     public AnimeConverter(String ffprobePath, String ffmpegPath, String[] audioLang, String[] subtitleLang, | ||||
|     public AnimeConverter(String ffprobePath, String ffmpegPath, String[] audioLanguages, String[] subtitleLanguages, | ||||
|                           boolean toStereo, boolean preventSignsAndSongs) { | ||||
|         super("mp4"); | ||||
|         this.ffprobePath = ffprobePath; | ||||
|         this.ffmpegPath = ffmpegPath; | ||||
|         this.audioLang = audioLang; | ||||
|         this.subtitleLang = subtitleLang; | ||||
|         this.audioLanguages = audioLanguages; | ||||
|         this.subtitleLanguages = subtitleLanguages; | ||||
|         this.toStereo = toStereo; | ||||
|         this.preventSignsAndSongs = preventSignsAndSongs; | ||||
|     } | ||||
| @@ -50,34 +49,25 @@ public class AnimeConverter extends AbstractConverter { | ||||
|     @Override | ||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||
|         List<String> command = FFMpegHelper.getFFMpegWebVideoCommand(executable, file.getName()); | ||||
|  | ||||
|         if (this.DEBUG) { | ||||
|             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||
|         } | ||||
|  | ||||
|         List<AudioStream> audioStreams = filterAudioStreams(filterStreamsByType(streams, "audio"), audioLang); | ||||
|         List<VideoStream> videoStreams = filterStreamsByType(streams, "video"); | ||||
|         //Get the first audio stream in accordance with chosen languages | ||||
|         List<AudioStream> audioStreams = filterAudioStreams(filterStreamsByType(streams, AudioStream.class), audioLanguages); | ||||
|         AudioStream audioStream = getFirstAudioSteam(new ArrayList<>(audioStreams)); | ||||
|  | ||||
|         //Get the first subtitle stream in accordance with chosen languages and signs and songs prevention | ||||
|         List<SubtitleStream> subtitleStreams = filterSubtitleStreams(filterStreamsByType(streams, | ||||
|                 "subtitle"), subtitleLang, preventSignsAndSongs); | ||||
|                 SubtitleStream.class), subtitleLanguages, preventSignsAndSongs); | ||||
|         SubtitleStream subtitleStream = getFirstSubtitleStream(new ArrayList<>(subtitleStreams)); | ||||
|  | ||||
|         VideoStream videoStream = null; | ||||
|         AudioStream audioStream = null; | ||||
|         SubtitleStream subtitleStream = null; | ||||
|         if (videoStreams.size() > 0) { | ||||
|             videoStream = videoStreams.get(0); | ||||
|         } | ||||
|         if (videoStream == null) { | ||||
|             throw new IllegalArgumentException("The file does not have any valid video streams."); | ||||
|         } | ||||
|         if (audioStreams.size() > 0) { | ||||
|             audioStream = audioStreams.get(0); | ||||
|         } | ||||
|         if (subtitleStreams.size() > 0) { | ||||
|             subtitleStream = subtitleStreams.get(0); | ||||
|         } | ||||
|         //Get the first video stream | ||||
|         VideoStream videoStream = getFirstVideoStream(streams); | ||||
|  | ||||
|         //Add streams to output file | ||||
|         addAudioStreams(command, audioStream, toStereo); | ||||
|         addSubtitles(command, subtitleStream, videoStream, file); | ||||
|         addSubtitlesAndVideo(command, subtitleStream, videoStream, file); | ||||
|  | ||||
|         command.add(outFile); | ||||
|         return command.toArray(new String[0]); | ||||
|   | ||||
| @@ -16,9 +16,9 @@ public class AudioConverter extends AbstractConverter { | ||||
|     /** | ||||
|      * Instantiates a new audio converter | ||||
|      * | ||||
|      * @param ffprobePath <p>Path/command to ffprobe.</p> | ||||
|      * @param ffmpegPath  <p>Path/command to ffmpeg.</p> | ||||
|      * @param newExtension      <p>The extension of the new file.</p> | ||||
|      * @param ffprobePath  <p>Path/command to ffprobe.</p> | ||||
|      * @param ffmpegPath   <p>Path/command to ffmpeg.</p> | ||||
|      * @param newExtension <p>The extension of the new file.</p> | ||||
|      */ | ||||
|     public AudioConverter(String ffprobePath, String ffmpegPath, String newExtension) { | ||||
|         super(newExtension); | ||||
| @@ -29,16 +29,14 @@ public class AudioConverter extends AbstractConverter { | ||||
|     @Override | ||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||
|         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); | ||||
|         List<AudioStream> audioStreams = filterStreamsByType(streams, "audio"); | ||||
|         AudioStream audioStream = null; | ||||
|         if (audioStreams.size() > 0) { | ||||
|             audioStream = audioStreams.get(0); | ||||
|         if (this.DEBUG) { | ||||
|             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||
|         } | ||||
|         if (audioStreams.size() > 0) { | ||||
|             command.add("-map"); | ||||
|             command.add("0:" + audioStream.getAbsoluteIndex()); | ||||
|         } | ||||
|         command.add(outFile); | ||||
|  | ||||
|         //Gets the first audio stream from the file and adds it to the output file | ||||
|         AudioStream audioStream = getFirstAudioSteam(streams); | ||||
|         addAudioStreams(command, audioStream, false); | ||||
|  | ||||
|         return command.toArray(new String[0]); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -18,9 +18,9 @@ public class VideoConverter extends AbstractConverter { | ||||
|     /** | ||||
|      * Instantiates a new video converter | ||||
|      * | ||||
|      * @param ffprobePath <p>Path/command to ffprobe.</p> | ||||
|      * @param ffmpegPath  <p>Path/command to ffmpeg.</p> | ||||
|      * @param newExtension      <p>The extension of the new file.</p> | ||||
|      * @param ffprobePath  <p>Path/command to ffprobe.</p> | ||||
|      * @param ffmpegPath   <p>Path/command to ffmpeg.</p> | ||||
|      * @param newExtension <p>The extension of the new file.</p> | ||||
|      */ | ||||
|     public VideoConverter(String ffprobePath, String ffmpegPath, String newExtension) { | ||||
|         super(newExtension); | ||||
| @@ -31,51 +31,25 @@ public class VideoConverter extends AbstractConverter { | ||||
|     @Override | ||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||
|         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); | ||||
|  | ||||
|         if (this.DEBUG) { | ||||
|             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||
|         } | ||||
|  | ||||
|         List<AudioStream> audioStreams = filterStreamsByType(streams, "audio"); | ||||
|         List<VideoStream> videoStreams = filterStreamsByType(streams, "video"); | ||||
|         List<SubtitleStream> subtitleStreams = filterStreamsByType(streams, "subtitle"); | ||||
|         //Get first streams from the file | ||||
|         SubtitleStream subtitleStream = getFirstSubtitleStream(streams); | ||||
|         VideoStream videoStream = getFirstVideoStream(streams); | ||||
|         AudioStream audioStream = getFirstAudioSteam(streams); | ||||
|  | ||||
|         VideoStream videoStream = null; | ||||
|         AudioStream audioStream = null; | ||||
|         SubtitleStream subtitleStream = null; | ||||
|         if (videoStreams.size() > 0) { | ||||
|             videoStream = videoStreams.get(0); | ||||
|         //Add streams to output | ||||
|         addSubtitlesAndVideo(command, subtitleStream, videoStream, file); | ||||
|         if (audioStream != null) { | ||||
|             addAudioStreams(command, audioStream, true); | ||||
|         } | ||||
|         if (audioStreams.size() > 0) { | ||||
|             audioStream = audioStreams.get(0); | ||||
|         } | ||||
|         if (subtitleStreams.size() > 0) { | ||||
|             subtitleStream = subtitleStreams.get(0); | ||||
|         } | ||||
|  | ||||
|         addSubtitles(command, subtitleStream, videoStream, file); | ||||
|  | ||||
|         if (audioStreams.size() > 0) { | ||||
|             command.add("-map"); | ||||
|             command.add("0:" + audioStream); | ||||
|         } | ||||
|  | ||||
|         convertToStereo(command); | ||||
|  | ||||
|         command.add(outFile); | ||||
|         return command.toArray(new String[0]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Converts the audio of a video to stereo | ||||
|      * | ||||
|      * @param command <p>The command list to add to.</p> | ||||
|      */ | ||||
|     private void convertToStereo(List<String> command) { | ||||
|         command.add("-af"); | ||||
|         command.add("pan=stereo|FL < 1.0*FL + 0.707*FC + 0.707*BL|FR < 1.0*FR + 0.707*FC + 0.707*BR"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String[] getValidFormats() { | ||||
|         return videoFormats; | ||||
|   | ||||
| @@ -17,8 +17,8 @@ public final class FileUtil { | ||||
|     /** | ||||
|      * Gets the path described by the input, but changed to account for collisions | ||||
|      * | ||||
|      * @param folder <p>The folder containing the output file.</p> | ||||
|      * @param file <p>The input file.</p> | ||||
|      * @param folder       <p>The folder containing the output file.</p> | ||||
|      * @param file         <p>The input file.</p> | ||||
|      * @param outExtension <p>The extension of the output file.</p> | ||||
|      * @return <p>A file name with the new extension and without any collisions.</p> | ||||
|      */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user