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 { | public abstract class AbstractConverter implements Converter { | ||||||
|     final boolean DEBUG = false; |     final boolean DEBUG = false; | ||||||
|  |     private final String newExtension; | ||||||
|     String ffprobePath; |     String ffprobePath; | ||||||
|     String ffmpegPath; |     String ffmpegPath; | ||||||
|     String[] audioFormats; |     String[] audioFormats; | ||||||
|     String[] videoFormats; |     String[] videoFormats; | ||||||
|     private final String newExtension; |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Initializes variables used by the abstract converter |      * Initializes variables used by the abstract converter | ||||||
| @@ -43,17 +43,17 @@ public abstract class AbstractConverter implements Converter { | |||||||
|      * Filters parsed streams into one of the stream types |      * Filters parsed streams into one of the stream types | ||||||
|      * |      * | ||||||
|      * @param streams <p>A list of stream objects.</p> |      * @param streams <p>A list of stream objects.</p> | ||||||
|      * @param codecType <p>The codec type of the streams to select.</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> |      * @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> |      * @return <p>A potentially shorter list of streams.</p> | ||||||
|      */ |      */ | ||||||
|     @SuppressWarnings("unchecked") |     @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(); |         Iterator<StreamObject> i = streams.iterator(); | ||||||
|         List<G> newStreams = new ArrayList<>(); |         List<G> newStreams = new ArrayList<>(); | ||||||
|         while (i.hasNext()) { |         while (i.hasNext()) { | ||||||
|             StreamObject next = i.next(); |             StreamObject next = i.next(); | ||||||
|             if (next.getCodecType().equals(codecType)) { |             if (next.getClass() == clazz) { | ||||||
|                 newStreams.add((G) next); |                 newStreams.add((G) next); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -143,6 +143,7 @@ public abstract class AbstractConverter implements Converter { | |||||||
|             if (toStereo && audioStream.getChannels() > 2) { |             if (toStereo && audioStream.getChannels() > 2) { | ||||||
|                 command.add("-af"); |                 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=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 videoStream    <p>The video stream to be used.</p> | ||||||
|      * @param file           <p>The file to convert.</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. |         //No appropriate subtitle was found. Just add the video stream. | ||||||
|         if (subtitleStream == null) { |         if (subtitleStream == null) { | ||||||
|             command.add("-map"); |             command.add("-map"); | ||||||
| @@ -242,4 +243,52 @@ public abstract class AbstractConverter implements Converter { | |||||||
|         ProcessBuilder processBuilder = new ProcessBuilder(builderCommand(ffmpegPath, file, streams, newPath)); |         ProcessBuilder processBuilder = new ProcessBuilder(builderCommand(ffmpegPath, file, streams, newPath)); | ||||||
|         FFMpegHelper.convertProcess(processBuilder, folder); |         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.SubtitleStream; | ||||||
| import net.knarcraft.ffmpegconverter.streams.VideoStream; | import net.knarcraft.ffmpegconverter.streams.VideoStream; | ||||||
| import net.knarcraft.ffmpegconverter.utility.FFMpegHelper; | 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.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * A converter mainly designed for converting anime to web-playable mp4 |  * A converter mainly designed for converting anime to web-playable mp4 | ||||||
|  */ |  */ | ||||||
| public class AnimeConverter extends AbstractConverter { | public class AnimeConverter extends AbstractConverter { | ||||||
|     private final String[] audioLang; |     private final String[] audioLanguages; | ||||||
|     private final String[] subtitleLang; |     private final String[] subtitleLanguages; | ||||||
|     private final boolean toStereo; |     private final boolean toStereo; | ||||||
|     private final boolean preventSignsAndSongs; |     private final boolean preventSignsAndSongs; | ||||||
|  |  | ||||||
| @@ -26,18 +25,18 @@ public class AnimeConverter extends AbstractConverter { | |||||||
|      * |      * | ||||||
|      * @param ffprobePath          <p>Path/command to ffprobe.</p> |      * @param ffprobePath          <p>Path/command to ffprobe.</p> | ||||||
|      * @param ffmpegPath           <p>Path/command to ffmpeg.</p> |      * @param ffmpegPath           <p>Path/command to ffmpeg.</p> | ||||||
|      * @param audioLang            <p>List of wanted audio languages in descending order.</p> |      * @param audioLanguages       <p>List of wanted audio languages in descending order.</p> | ||||||
|      * @param subtitleLang         <p>List of wanted subtitle 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 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 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) { |                           boolean toStereo, boolean preventSignsAndSongs) { | ||||||
|         super("mp4"); |         super("mp4"); | ||||||
|         this.ffprobePath = ffprobePath; |         this.ffprobePath = ffprobePath; | ||||||
|         this.ffmpegPath = ffmpegPath; |         this.ffmpegPath = ffmpegPath; | ||||||
|         this.audioLang = audioLang; |         this.audioLanguages = audioLanguages; | ||||||
|         this.subtitleLang = subtitleLang; |         this.subtitleLanguages = subtitleLanguages; | ||||||
|         this.toStereo = toStereo; |         this.toStereo = toStereo; | ||||||
|         this.preventSignsAndSongs = preventSignsAndSongs; |         this.preventSignsAndSongs = preventSignsAndSongs; | ||||||
|     } |     } | ||||||
| @@ -50,34 +49,25 @@ public class AnimeConverter extends AbstractConverter { | |||||||
|     @Override |     @Override | ||||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { |     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||||
|         List<String> command = FFMpegHelper.getFFMpegWebVideoCommand(executable, file.getName()); |         List<String> command = FFMpegHelper.getFFMpegWebVideoCommand(executable, file.getName()); | ||||||
|  |  | ||||||
|         if (this.DEBUG) { |         if (this.DEBUG) { | ||||||
|             FFMpegHelper.addDebugArguments(command, 50, 120); |             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         List<AudioStream> audioStreams = filterAudioStreams(filterStreamsByType(streams, "audio"), audioLang); |         //Get the first audio stream in accordance with chosen languages | ||||||
|         List<VideoStream> videoStreams = filterStreamsByType(streams, "video"); |         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, |         List<SubtitleStream> subtitleStreams = filterSubtitleStreams(filterStreamsByType(streams, | ||||||
|                 "subtitle"), subtitleLang, preventSignsAndSongs); |                 SubtitleStream.class), subtitleLanguages, preventSignsAndSongs); | ||||||
|  |         SubtitleStream subtitleStream = getFirstSubtitleStream(new ArrayList<>(subtitleStreams)); | ||||||
|  |  | ||||||
|         VideoStream videoStream = null; |         //Get the first video stream | ||||||
|         AudioStream audioStream = null; |         VideoStream videoStream = getFirstVideoStream(streams); | ||||||
|         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); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |         //Add streams to output file | ||||||
|         addAudioStreams(command, audioStream, toStereo); |         addAudioStreams(command, audioStream, toStereo); | ||||||
|         addSubtitles(command, subtitleStream, videoStream, file); |         addSubtitlesAndVideo(command, subtitleStream, videoStream, file); | ||||||
|  |  | ||||||
|         command.add(outFile); |         command.add(outFile); | ||||||
|         return command.toArray(new String[0]); |         return command.toArray(new String[0]); | ||||||
|   | |||||||
| @@ -29,16 +29,14 @@ public class AudioConverter extends AbstractConverter { | |||||||
|     @Override |     @Override | ||||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { |     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||||
|         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); |         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); | ||||||
|         List<AudioStream> audioStreams = filterStreamsByType(streams, "audio"); |         if (this.DEBUG) { | ||||||
|         AudioStream audioStream = null; |             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||||
|         if (audioStreams.size() > 0) { |  | ||||||
|             audioStream = audioStreams.get(0); |  | ||||||
|         } |         } | ||||||
|         if (audioStreams.size() > 0) { |  | ||||||
|             command.add("-map"); |         //Gets the first audio stream from the file and adds it to the output file | ||||||
|             command.add("0:" + audioStream.getAbsoluteIndex()); |         AudioStream audioStream = getFirstAudioSteam(streams); | ||||||
|         } |         addAudioStreams(command, audioStream, false); | ||||||
|         command.add(outFile); |  | ||||||
|         return command.toArray(new String[0]); |         return command.toArray(new String[0]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,51 +31,25 @@ public class VideoConverter extends AbstractConverter { | |||||||
|     @Override |     @Override | ||||||
|     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { |     public String[] builderCommand(String executable, File file, List<StreamObject> streams, String outFile) { | ||||||
|         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); |         List<String> command = FFMpegHelper.getFFMpegGeneralFileCommand(executable, file.getName()); | ||||||
|  |  | ||||||
|         if (this.DEBUG) { |         if (this.DEBUG) { | ||||||
|             FFMpegHelper.addDebugArguments(command, 50, 120); |             FFMpegHelper.addDebugArguments(command, 50, 120); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         List<AudioStream> audioStreams = filterStreamsByType(streams, "audio"); |         //Get first streams from the file | ||||||
|         List<VideoStream> videoStreams = filterStreamsByType(streams, "video"); |         SubtitleStream subtitleStream = getFirstSubtitleStream(streams); | ||||||
|         List<SubtitleStream> subtitleStreams = filterStreamsByType(streams, "subtitle"); |         VideoStream videoStream = getFirstVideoStream(streams); | ||||||
|  |         AudioStream audioStream = getFirstAudioSteam(streams); | ||||||
|  |  | ||||||
|         VideoStream videoStream = null; |         //Add streams to output | ||||||
|         AudioStream audioStream = null; |         addSubtitlesAndVideo(command, subtitleStream, videoStream, file); | ||||||
|         SubtitleStream subtitleStream = null; |         if (audioStream != null) { | ||||||
|         if (videoStreams.size() > 0) { |             addAudioStreams(command, audioStream, true); | ||||||
|             videoStream = videoStreams.get(0); |  | ||||||
|         } |         } | ||||||
|         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); |         command.add(outFile); | ||||||
|         return command.toArray(new String[0]); |         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 |     @Override | ||||||
|     public String[] getValidFormats() { |     public String[] getValidFormats() { | ||||||
|         return videoFormats; |         return videoFormats; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user