Added lossless flac audio support
[meviz.git] / src / main / java / eu / svjatoslav / meviz / encoder / converters / FFMpegVideo.java
1 /*
2  * Meviz - Various tools collection to work with multimedia.
3  * Copyright (C) 2012 -- 2019, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 3 of the GNU Lesser General Public License
7  * or later as published by the Free Software Foundation.
8 */
9
10 package eu.svjatoslav.meviz.encoder.converters;
11
12 import eu.svjatoslav.meviz.encoder.BitrateParameter.Bitrate;
13 import eu.svjatoslav.meviz.encoder.EncodingOptions;
14
15 import java.io.File;
16 import java.util.List;
17
18 public class FFMpegVideo extends AbstractConverter {
19
20     private String constructCodecParamsString(final EncodingOptions options,
21                                               final int videoBitrate, final int audioBitrate,
22                                               final String videoCodec, final String audioCodec) {
23
24         final StringBuilder codecParams = new StringBuilder();
25
26         if (audioCodec == null)
27             codecParams.append("-an ");
28         else
29             codecParams.append("-acodec " + audioCodec + " ");
30
31         codecParams.append("-vcodec " + videoCodec + " ");
32
33         if (videoBitrate != -1)
34             codecParams.append("-b " + videoBitrate + "k ");
35
36         if (audioBitrate != -1)
37             codecParams.append("-b:a " + audioBitrate + "k ");
38
39         if (options.isDeinterlace())
40             codecParams.append("-filter:v yadif ");
41
42         if (options.getTargetFps() != null)
43             codecParams.append("-r " + options.getTargetFps() + " ");
44
45         return codecParams.toString();
46     }
47
48     private int getAudioBitrateValue(final Bitrate bitRate) {
49         switch (bitRate) {
50             case LOW:
51                 return 128;
52
53             case MEDIUM:
54                 return 160;
55
56             case HIGH:
57                 return 320;
58
59             case COPY:
60                 return -1;
61
62             case NONE:
63                 return -1;
64
65             case LOSSLESS:
66                 return -1;
67
68             default:
69                 throw new RuntimeException("Audio bitrate: " + bitRate
70                         + " is not supported.");
71         }
72     }
73
74     @Override
75     public String getCommand(final File inputFile, final File targetFile,
76                              final EncodingOptions options, final String targetFormat) {
77
78         int videoBitrate = getVideoBitrateValue(options.getVideoBitrate());
79         int audioBitrate = getAudioBitrateValue(options.getAudioBitrate());
80
81         // convert
82         final StringBuilder codecParams = new StringBuilder();
83
84         String videoCodec = "libx264";
85         String audioCodec = "libmp3lame";
86
87         if (targetFormat.equals("webm")) {
88             videoCodec = "vp8";
89             audioCodec = "opus";
90             codecParams.append("-s 800x450 ");
91         }
92
93         if (options.getVideoBitrate() == Bitrate.COPY)
94             videoCodec = "copy";
95
96         if (options.getAudioBitrate() == Bitrate.COPY)
97             audioCodec = "copy";
98
99         if (options.getAudioBitrate() == Bitrate.LOSSLESS){
100             audioCodec = "flac";
101             codecParams.append("-strict -2 ");
102         }
103
104         if (options.getAudioBitrate() == Bitrate.NONE)
105             audioCodec = null;
106
107         if (options.isForPortablePlayer()) {
108             videoBitrate = 1000;
109             audioBitrate = 128;
110             videoCodec = "libxvid";
111
112             // reduce resolution
113             codecParams.append("-s 640x480 ");
114
115             // enforce maximum keyframe interval
116             codecParams.append("-g 150 ");
117         }
118
119         codecParams.append(constructCodecParamsString(options, videoBitrate,
120                 audioBitrate, videoCodec, audioCodec));
121
122         return "ffmpeg -i \"" + inputFile.getAbsolutePath() + "\" "
123                 + codecParams.toString() + "\"" + targetFile.getAbsolutePath()
124                 + "\"";
125     }
126
127     @Override
128     public List<String> getSourceFileExtensions() {
129         return getSupportedExtensions();
130     }
131
132     private List<String> getSupportedExtensions() {
133         return toList("mkv", "mts", "mp4", "avi", "mpg", "mpeg", "vob", "m4v",
134                 "webm", "mov", "asf", "3gp");
135     }
136
137     @Override
138     public List<String> getTargetFileExtensions() {
139         return getSupportedExtensions();
140     }
141
142     private int getVideoBitrateValue(final Bitrate bitRate) {
143         switch (bitRate) {
144             case LOW:
145                 return 1000;
146
147             case MEDIUM:
148                 return 4000;
149
150             case HIGH:
151                 return 16000;
152
153             case COPY:
154                 return -1;
155
156             default:
157                 throw new RuntimeException("Video bitrate: " + bitRate
158                         + " is not supported.");
159         }
160     }
161
162     @Override
163     public boolean isTerminalMandatory() {
164         return true;
165     }
166
167 }