X-Git-Url: http://git.sourceforge.jp/view?p=coroid%2Finqubus.git;a=blobdiff_plain;f=frontend%2Fsrc%2Fsaccubus%2Fconverter%2FFfmpegCommand.java;h=57e16f6ce6adc19051a365d6cbf62773db4b70a0;hp=e2071fb32f504e54a2f16017f4c40d8015d9061d;hb=3d2cd2b8f260c14575c7886bf4dbd4ed22f2fe05;hpb=4e7e9eef76b343f220f5d7a23ae8a8ba6660eb89 diff --git a/frontend/src/saccubus/converter/FfmpegCommand.java b/frontend/src/saccubus/converter/FfmpegCommand.java index e2071fb..57e16f6 100644 --- a/frontend/src/saccubus/converter/FfmpegCommand.java +++ b/frontend/src/saccubus/converter/FfmpegCommand.java @@ -7,45 +7,52 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import saccubus.ConvertStopFlag; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.SwingWorker; +import org.apache.commons.lang.StringUtils; import saccubus.conv.ConvertToVideoHook; -import saccubus.converter.profile.Ffmpeg; -import saccubus.converter.profile.FfmpegOption; -import saccubus.converter.profile.NgSetting; -import saccubus.net.TextProgressListener; +import saccubus.converter.profile.ConvertProfile; +import saccubus.converter.profile.FfmpegProfile; +import saccubus.converter.profile.GeneralProfile; +import yukihane.mediainfowrapper.Info; +import yukihane.mediainfowrapper.MediaInfo; +import yukihane.mediainfowrapper.Size; +import saccubus.converter.profile.ConvertProfile.HideCondition; import yukihane.swf.Cws2Fws; /** * * @author yuki */ -public class FfmpegCommand extends AbstractCommand { +public class FfmpegCommand extends SwingWorker { + private static final Logger logger = Logger.getLogger(FfmpegCommand.class.getName()); private final File commentMiddleFile; private final File tcommMiddleFile; private final File TMP_CWS; private final File commentFile; - private final File tcommFile; private final File videoFile; private final File convertedVideoFile; - private final Ffmpeg ffmpeg; + private final ConvertProfile ffmpeg; - FfmpegCommand(TextProgressListener listener, ConvertStopFlag flag, File commentFile, File tcommFile, - File videoFile, File convertedVideoFile, Ffmpeg ffmpeg) throws IOException { - super(listener, flag); + FfmpegCommand(File commentFile, File videoFile, File convertedVideoFile, ConvertProfile ffmpeg, + GeneralProfile general) throws IOException { this.commentFile = commentFile; - this.tcommFile = tcommFile; this.videoFile = videoFile; this.convertedVideoFile = convertedVideoFile; this.ffmpeg = ffmpeg; - File tmpDir = new File("tmp"); + File tmpDir = general.getTempDir(); commentMiddleFile = File.createTempFile("vhk", ".tmp", tmpDir); tcommMiddleFile = File.createTempFile("tcom", ".tmp", tmpDir); TMP_CWS = File.createTempFile("cws", ".swf", tmpDir); } - public boolean execute() throws InterruptedException, IOException { + @Override + protected FfmpegCommandResult doInBackground() throws Exception { try { return exec(); } finally { @@ -61,89 +68,123 @@ public class FfmpegCommand extends AbstractCommand { } } - private boolean exec() throws InterruptedException, IOException { - final NgSetting ngSetting = getFfmpeg().getNgSetting(); + private FfmpegCommandResult exec() throws InterruptedException, IOException { + final HideCondition ngSetting = getFfmpeg().getNgSetting(); if (commentFile != null) { - sendText("ƒRƒƒ“ƒg‚Ì’†ŠÔƒtƒ@ƒCƒ‹‚Ö‚Ì•ÏŠ·’†"); + publish(new FfmpegCommandProgress("コメントの中間ファイルへの変換中")); boolean conv = ConvertToVideoHook.convert(commentFile, commentMiddleFile, ngSetting.getId(), ngSetting. getWord()); if (!conv) { - sendText("ƒRƒƒ“ƒg•ÏŠ·‚ÉŽ¸”sBƒtƒ@ƒCƒ‹–¼‚ÉŽg—p‚Å‚«‚È‚¢•¶Žš‚ªŠÜ‚Ü‚ê‚Ä‚¢‚é‚©³‹K•\Œ»‚̊ԈႢH"); - return false; + publish(new FfmpegCommandProgress("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?")); + return new FfmpegCommandResult(false); } } - stopFlagReturn(); - if (tcommFile != null) { - sendText("“ŠeŽÒƒRƒƒ“ƒg‚Ì’†ŠÔƒtƒ@ƒCƒ‹‚Ö‚Ì•ÏŠ·’†"); - boolean conv = ConvertToVideoHook.convert(tcommFile, tcommMiddleFile, ngSetting.getId(), ngSetting.getWord()); - if (!conv) { - sendText("ƒRƒƒ“ƒg•ÏŠ·‚ÉŽ¸”sBƒtƒ@ƒCƒ‹–¼‚ÉŽg—p‚Å‚«‚È‚¢•¶Žš‚ªŠÜ‚Ü‚ê‚Ä‚¢‚é‚©³‹K•\Œ»‚̊ԈႢH"); - return false; - } - } - stopFlagReturn(); - sendText("“®‰æ‚Ì•ÏŠ·‚ðŠJŽn"); + checkStop(); +// if (tcommFile != null) { +// sendText("投稿者コメントの中間ファイルへの変換中"); +// boolean conv = ConvertToVideoHook.convert(tcommFile, tcommMiddleFile, ngSetting.getId(), ngSetting.getWord()); +// if (!conv) { +// sendText("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?"); +// return false; +// } +// } +// stopFlagReturn(); + publish(new FfmpegCommandProgress("動画の変換を開始")); int code; - if ((code = converting_video(videoFile, convertedVideoFile, (commentFile != null), commentMiddleFile.getPath(), (tcommFile - != null), tcommMiddleFile.getPath(), getFfmpeg().getFfmpegOption())) == 0) { - sendText("•ÏŠ·‚ª³í‚ɏI—¹‚µ‚Ü‚µ‚½B"); - return true; + if ((code = converting_video(videoFile, convertedVideoFile, (commentFile != null), commentMiddleFile.getPath(), + false, tcommMiddleFile.getPath(), getFfmpeg().getFfmpegOption())) == 0) { + publish(new FfmpegCommandProgress("変換が正常に終了しました。")); + return new FfmpegCommandResult(true); } else { - sendText("•ÏŠ·ƒGƒ‰[:" + convertedVideoFile.getPath()); + publish(new FfmpegCommandProgress("変換エラー:" + convertedVideoFile.getPath())); } - return false; + return new FfmpegCommandResult(false); } - private int converting_video(File videoFile, File convertedVideoFile, boolean addComment, String vhook_path, - boolean addTcomment, String tcommPath, FfmpegOption ov) throws InterruptedException, IOException { + private int converting_video(File videoFile, File convertedVideoFile, boolean addComment, String commPath, + boolean addTcomment, String tcommPath, FfmpegProfile ov) throws InterruptedException, IOException { File fwsFile = Cws2Fws.createFws(videoFile, TMP_CWS); - StringBuffer sb = new StringBuffer(); - sb.append("\""); - sb.append(getFfmpeg().getFfmpeg().getPath().replace("\\", "\\\\")); - sb.append("\""); - sb.append(" -y "); - sb.append(ov.getMainOption()); - sb.append(" "); - sb.append(ov.getInOption()); - sb.append(" -i "); + List cmdList = new ArrayList(); + cmdList.add(getFfmpeg().getFfmpeg().getPath()); + cmdList.add("-y"); + String[] mainOptions = ov.getMainOption().split(" +"); + for (String opt : mainOptions) { + if (StringUtils.isNotBlank(opt)) { + cmdList.add(opt); + } + } + String[] inOptions = ov.getInOption().split(" +"); + for (String opt : inOptions) { + if (StringUtils.isNotBlank(opt)) { + cmdList.add(opt); + } + } + cmdList.add("-i"); + if (fwsFile == null) { - sb.append("\""); - sb.append(videoFile.getPath().replace("\\", "\\\\")); - sb.append("\""); + cmdList.add(videoFile.getPath()); } else { - sb.append(fwsFile.getPath().replace("\\", "\\\\")); + cmdList.add(fwsFile.getPath()); + } + String[] outOptions = ov.getOutOption().split(" +"); + for (String opt : outOptions) { + if (StringUtils.isNotBlank(opt)) { + cmdList.add(opt); + } } - sb.append(" "); - sb.append(ov.getOutOption()); - sb.append(" \""); - sb.append(convertedVideoFile.getPath().replace("\\", "\\\\")); - sb.append("\""); + + final Info info = MediaInfo.getInfo(new File("bin", "MediaInfo"), videoFile); + // 4:3 なら1.33, 16:9 なら1.76 + boolean isHD = ((double) info.getWidth() / (double) info.getHeight() > 1.5); + if (ov.isResize()) { + final Size scaled = (ov.isAdjustRatio()) ? MediaInfo.adjustSize(info, ov.getResizeWidth(), ov. + getResizeHeight()) : new Size(info.getWidth(), info.getHeight()); + cmdList.add("-s"); + cmdList.add(scaled.getWidth() + "x" + scaled.getHeight()); + } + + List avfilterArgs = getAvfilterOptions(ov.getAvfilterOption()); if (!getFfmpeg().isVhookDisabled()) { - if (!addVhookSetting(sb, addComment, vhook_path, addTcomment, tcommPath)) { - return -1; + String vhookArg = getVhookArg(addComment, commPath, addTcomment, tcommPath, isHD); + if (StringUtils.isNotBlank(vhookArg)) { + avfilterArgs.add(vhookArg); } } - String cmd = sb.substring(0); - System.out.println("arg:" + cmd); + + if (!avfilterArgs.isEmpty()) { + cmdList.add("-vfilters"); + final String args = "\"" + StringUtils.join(avfilterArgs, ", ") + "\""; + cmdList.add(args); + } + + cmdList.add(convertedVideoFile.getPath()); + + final StringBuilder argMsg = new StringBuilder(); + argMsg.append("arg:"); + for (String s : cmdList) { + argMsg.append(" ").append(s); + } + logger.log(Level.INFO, argMsg.toString()); + + Process process = null; try { - System.out.println("\n\n----\nProcessing FFmpeg...\n----\n\n"); - Process process = Runtime.getRuntime().exec(cmd); + logger.log(Level.INFO, "\n\n----\nProcessing FFmpeg...\n----\n\n"); + process = Runtime.getRuntime().exec(cmdList.toArray(new String[0])); BufferedReader ebr = new BufferedReader(new InputStreamReader( process.getErrorStream())); String e; while ((e = ebr.readLine()) != null) { String state = e; if (state.startsWith("frame=")) { - sendText(state); + publish(new FfmpegCommandProgress(state)); } else if (!state.endsWith("No accelerated colorspace conversion found")) { - System.out.println(e); + logger.log(Level.INFO, e); } try { - stopFlagReturn(); + checkStop(); } catch (InterruptedException ex) { - process.destroy(); throw ex; } @@ -151,61 +192,79 @@ public class FfmpegCommand extends AbstractCommand { process.waitFor(); return process.exitValue(); } finally { + // TODO 正常終了した場合もdestroyしていいのか? + if (process != null) { + process.destroy(); + } if (fwsFile != null) { fwsFile.delete(); } } } - private boolean addVhookSetting(StringBuffer sb, boolean addComment, String vhook_path, boolean addTcomment, - String tcommPath) { - try { - sb.append(" -vfilters \"vhext="); - sb.append(getFfmpeg().getVhook().getPath().replace("\\", "/")); - if (addComment) { - sb.append("|"); - sb.append("--data-user:"); - sb.append(URLEncoder.encode(vhook_path.replace("\\", "/"), "Shift_JIS")); - } - if (addTcomment) { - sb.append("|"); - sb.append("--data-owner:"); - sb.append(URLEncoder.encode(tcommPath.replace("\\", "/"), "Shift_JIS")); - } + private List getAvfilterOptions(String avfilterOption) { + final List avfilterArgs = new ArrayList(); + if (StringUtils.isNotBlank(avfilterOption)) { + avfilterArgs.add(avfilterOption); + } + return avfilterArgs; + } + + private String getVhookArg(boolean addComment, String commPath, boolean addTcomment, + String tcommPath, boolean isHD) throws UnsupportedEncodingException { + StringBuilder sb = new StringBuilder(); + sb.append("vhext="); + sb.append(getFfmpeg().getVhook().getPath().replace("\\", "/")); + if (addComment) { sb.append("|"); - sb.append("--font:"); - sb.append(URLEncoder.encode( - getFfmpeg().getFont().getPath().replace("\\", "/"), "Shift_JIS")); + sb.append("--data-user:"); + sb.append(URLEncoder.encode(commPath.replace("\\", "/"), "Shift_JIS")); + } + if (addTcomment) { sb.append("|"); - sb.append("--font-index:"); - sb.append(getFfmpeg().getFontIndex()); + sb.append("--data-owner:"); + sb.append(URLEncoder.encode(tcommPath.replace("\\", "/"), "Shift_JIS")); + } + sb.append("|"); + sb.append("--font:"); + sb.append(URLEncoder.encode( + getFfmpeg().getFont().getPath().replace("\\", "/"), "Shift_JIS")); + sb.append("|"); + sb.append("--font-index:"); + sb.append(getFfmpeg().getFontIndex()); + sb.append("|"); + sb.append("--show-user:"); + sb.append(getFfmpeg().getMaxNumOfComment()); + sb.append("|"); + sb.append("--shadow:"); + sb.append(getFfmpeg().getShadowIndex()); + sb.append("|"); + if (getFfmpeg().isShowConverting()) { + sb.append("--enable-show-video"); sb.append("|"); - sb.append("--show-user:"); - sb.append(getFfmpeg().getMaxNumOfComment()); + } + if (!getFfmpeg().isDisableFontSizeArrange()) { + sb.append("--enable-fix-font-size"); sb.append("|"); - sb.append("--shadow:"); - sb.append(getFfmpeg().getShadowIndex()); + } + if (getFfmpeg().isCommentOpaque()) { + sb.append("--enable-opaque-comment"); sb.append("|"); - if (getFfmpeg().isShowConverting()) { - sb.append("--enable-show-video"); - sb.append("|"); - } - if (getFfmpeg().isSelfAdjustFontSize()) { - sb.append("--enable-fix-font-size"); - sb.append("|"); - } - if (getFfmpeg().isCommentOpaque()) { - sb.append("--enable-opaque-comment"); - } - sb.append("\""); - return true; - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - return false; } + if (isHD) { + sb.append("--aspect-mode:1"); + sb.append("|"); + } + return sb.toString(); } - private Ffmpeg getFfmpeg() { + private ConvertProfile getFfmpeg() { return ffmpeg; } + + protected void checkStop() throws InterruptedException { + if (Thread.interrupted()) { + throw new InterruptedException("中止要求を受け付けました"); + } + } }