2 package saccubus.converter;
4 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.UnsupportedEncodingException;
9 import java.net.URLEncoder;
10 import java.util.ArrayList;
11 import java.util.List;
12 import org.apache.commons.lang.StringUtils;
13 import saccubus.ConvertStopFlag;
14 import saccubus.conv.ConvertToVideoHook;
15 import saccubus.converter.profile.Ffmpeg;
16 import saccubus.converter.profile.FfmpegOption;
17 import saccubus.converter.profile.GeneralSetting;
18 import saccubus.converter.profile.NgSetting;
19 import saccubus.net.TextProgressListener;
20 import yukihane.mediainfowrapper.Info;
21 import yukihane.mediainfowrapper.MediaInfo;
22 import yukihane.mediainfowrapper.Size;
23 import yukihane.swf.Cws2Fws;
29 public class FfmpegCommand extends AbstractCommand {
31 private final File commentMiddleFile;
32 private final File tcommMiddleFile;
33 private final File TMP_CWS;
34 private final File commentFile;
35 private final File tcommFile;
36 private final File videoFile;
37 private final File convertedVideoFile;
38 private final Ffmpeg ffmpeg;
40 FfmpegCommand(TextProgressListener listener, ConvertStopFlag flag, File commentFile, File tcommFile,
41 File videoFile, File convertedVideoFile, Ffmpeg ffmpeg, GeneralSetting general) throws IOException {
42 super(listener, flag);
43 this.commentFile = commentFile;
44 this.tcommFile = tcommFile;
45 this.videoFile = videoFile;
46 this.convertedVideoFile = convertedVideoFile;
49 File tmpDir = general.getTempDir();
50 commentMiddleFile = File.createTempFile("vhk", ".tmp", tmpDir);
51 tcommMiddleFile = File.createTempFile("tcom", ".tmp", tmpDir);
52 TMP_CWS = File.createTempFile("cws", ".swf", tmpDir);
55 public boolean execute() throws InterruptedException, IOException {
59 if (commentMiddleFile.exists()) {
60 commentMiddleFile.delete();
62 if (tcommMiddleFile.exists()) {
63 tcommMiddleFile.delete();
65 if (TMP_CWS.exists()) {
71 private boolean exec() throws InterruptedException, IOException {
72 final NgSetting ngSetting = getFfmpeg().getNgSetting();
73 if (commentFile != null) {
74 sendText("コメントの中間ファイルへの変換中");
75 boolean conv = ConvertToVideoHook.convert(commentFile, commentMiddleFile, ngSetting.getId(), ngSetting.
78 sendText("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?");
83 if (tcommFile != null) {
84 sendText("投稿者コメントの中間ファイルへの変換中");
85 boolean conv = ConvertToVideoHook.convert(tcommFile, tcommMiddleFile, ngSetting.getId(), ngSetting.getWord());
87 sendText("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?");
94 if ((code = converting_video(videoFile, convertedVideoFile, (commentFile != null), commentMiddleFile.getPath(),
96 != null), tcommMiddleFile.getPath(), getFfmpeg().getFfmpegOption())) == 0) {
97 sendText("変換が正常に終了しました。");
100 sendText("変換エラー:" + convertedVideoFile.getPath());
105 private int converting_video(File videoFile, File convertedVideoFile, boolean addComment, String commPath,
106 boolean addTcomment, String tcommPath, FfmpegOption ov) throws InterruptedException, IOException {
107 File fwsFile = Cws2Fws.createFws(videoFile, TMP_CWS);
109 List<String> cmdList = new ArrayList<String>();
110 cmdList.add(getFfmpeg().getFfmpeg().getPath());
112 String[] mainOptions = ov.getMainOption().split(" +");
113 for (String opt : mainOptions) {
114 if (StringUtils.isNotBlank(opt)) {
118 String[] inOptions = ov.getInOption().split(" +");
119 for (String opt : inOptions) {
120 if (StringUtils.isNotBlank(opt)) {
126 if (fwsFile == null) {
127 cmdList.add(videoFile.getPath());
129 cmdList.add(fwsFile.getPath());
131 String[] outOptions = ov.getOutOption().split(" +");
132 for (String opt : outOptions) {
133 if (StringUtils.isNotBlank(opt)) {
138 final Info info = MediaInfo.getInfo(new File("bin", "MediaInfo"), videoFile);
139 // 4:3 なら1.33, 16:9 なら1.76
140 boolean isHD = ((double)info.getWidth()/(double)info.getHeight() > 1.5);
142 final Size scaled = (ov.isAdjustRatio()) ? MediaInfo.adjustSize(info, ov.getResizeWidth(), ov.
143 getResizeHeight()) : new Size(info.getWidth(), info.getHeight());
145 cmdList.add(scaled.getWidth() + "x" + scaled.getHeight());
148 List<String> avfilterArgs = getAvfilterOptions(ov, addComment, commPath, addTcomment, tcommPath, isHD);
150 if (!avfilterArgs.isEmpty()) {
151 cmdList.add("-vfilters");
152 final String args = "\"" + StringUtils.join(avfilterArgs, ", ") + "\"";
156 cmdList.add(convertedVideoFile.getPath());
158 System.out.print("arg:");
159 for (String s : cmdList) {
160 System.out.print(" " + s);
162 System.out.println();
165 System.out.println("\n\n----\nProcessing FFmpeg...\n----\n\n");
166 Process process = Runtime.getRuntime().exec(cmdList.toArray(new String[0]));
167 BufferedReader ebr = new BufferedReader(new InputStreamReader(
168 process.getErrorStream()));
170 while ((e = ebr.readLine()) != null) {
172 if (state.startsWith("frame=")) {
174 } else if (!state.endsWith("No accelerated colorspace conversion found")) {
175 System.out.println(e);
180 } catch (InterruptedException ex) {
187 return process.exitValue();
189 if (fwsFile != null) {
195 private List<String> getAvfilterOptions(FfmpegOption ov, boolean addComment, String commPath, boolean addTcomment,
196 String tcommPath, boolean isHD) throws UnsupportedEncodingException {
197 final List<String> avfilterArgs = new ArrayList<String>();
198 final String avfilterOption = ov.getAvfilterOption();
199 if (StringUtils.isNotBlank(avfilterOption)) {
200 avfilterArgs.add(avfilterOption);
202 final String vhookArg = (getFfmpeg().isVhookDisabled())
203 ? null : getVhookArg(addComment, commPath, addTcomment, tcommPath, isHD);
204 if (vhookArg != null) {
205 avfilterArgs.add(vhookArg);
210 private String getVhookArg(boolean addComment, String commPath, boolean addTcomment,
211 String tcommPath, boolean isHD) throws UnsupportedEncodingException {
212 StringBuilder sb = new StringBuilder();
214 sb.append(getFfmpeg().getVhook().getPath().replace("\\", "/"));
217 sb.append("--data-user:");
218 sb.append(URLEncoder.encode(commPath.replace("\\", "/"), "Shift_JIS"));
222 sb.append("--data-owner:");
223 sb.append(URLEncoder.encode(tcommPath.replace("\\", "/"), "Shift_JIS"));
226 sb.append("--font:");
227 sb.append(URLEncoder.encode(
228 getFfmpeg().getFont().getPath().replace("\\", "/"), "Shift_JIS"));
230 sb.append("--font-index:");
231 sb.append(getFfmpeg().getFontIndex());
233 sb.append("--show-user:");
234 sb.append(getFfmpeg().getMaxNumOfComment());
236 sb.append("--shadow:");
237 sb.append(getFfmpeg().getShadowIndex());
239 if (getFfmpeg().isShowConverting()) {
240 sb.append("--enable-show-video");
243 if (getFfmpeg().isSelfAdjustFontSize()) {
244 sb.append("--enable-fix-font-size");
247 if (getFfmpeg().isCommentOpaque()) {
248 sb.append("--enable-opaque-comment");
252 sb.append("--aspect-mode:1");
255 return sb.toString();
258 private Ffmpeg getFfmpeg() {