OSDN Git Service

オプショナルコメントの中間ファイル生成とffmpeg引数での引き渡し
[coroid/inqubus.git] / frontend / src / saccubus / worker / impl / convert / Convert.java
index 5e73916..a02524e 100644 (file)
@@ -12,14 +12,17 @@ import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.ArrayList;
+import java.util.EnumMap;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import saccubus.conv.ConvertToVideoHook;
-import saccubus.conv.NicoXMLReader.ProcessType;
+import saccubus.conv.CommentType;
 import saccubus.util.FfmpegUtil;
 import saccubus.worker.Worker;
 import saccubus.worker.WorkerListener;
@@ -86,44 +89,42 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
         final File outputFile = new File(outprof.getDir(),
                 outputPattern.createFileName() + profile.getFfmpegOption().getExtOption());
 
-        File transformedComment = null;
-        File transformedOwner = null;
+        final Map<CommentType, File> tmpComments = new EnumMap<>(CommentType.class);
         try {
 
             if (profile.isCommentOverlay()) {
-                transformedComment = File.createTempFile("vhk", ".tmp", profile.getTempDir());
-                transformedOwner = File.createTempFile("vown", ".tmp", profile.getTempDir());
-                final HideCondition hide = profile.getNgSetting();
+                for (CommentType ct : CommentType.values()) {
+                    tmpComments.put(ct, File.createTempFile("vhk", ".tmp", profile.getTempDir()));
+                }
 
-                publish(new ConvertProgress(PROCESS, -1.0, "コメントの中間ファイルへの変換中"));
-                ConvertToVideoHook.convert(EnumSet.of(ProcessType.NORMAL), commentFile, transformedComment, hide.getId(),
-                        hide.getWord());
+                final HideCondition hide = profile.getNgSetting();
 
-                publish(new ConvertProgress(PROCESS, -1.0, "投稿者コメントの中間ファイルへの変換中"));
-                ConvertToVideoHook.convert(EnumSet.of(ProcessType.OWNER), commentFile, transformedOwner, hide.getId(),
-                        hide.getWord());
+                for (CommentType ct : CommentType.values()) {
+                    publish(new ConvertProgress(PROCESS, -1.0, ct.toString() + "の中間ファイルへの変換中"));
+                    ConvertToVideoHook.convert(EnumSet.of(ct), commentFile, tmpComments.get(ct),
+                            hide.getId(), hide.getWord());
+                }
             }
 
             checkStop();
             publish(new ConvertProgress(PROCESS, -1.0, "動画の変換を開始"));
 
-            final int code = convert(outputFile, transformedComment, transformedOwner);
+            final int code = convert(outputFile, new EnumMap<>(tmpComments));
             if (code != 0) {
-                throw new IOException("ffmpeg実行失敗: " + outputFile.getPath());
+                throw new IOException("ffmpeg実行失敗(code " + code + "): " + outputFile.getPath());
             }
             publish(new ConvertProgress(PROCESS, 100.0, "変換が正常に終了しました。"));
             return new ConvertResult(true, outputFile.getName());
         } finally {
-            if (transformedComment != null && transformedComment.exists()) {
-                transformedComment.delete();
-            }
-            if (transformedOwner != null && transformedOwner.exists()) {
-                transformedOwner.delete();
+            for(File f : tmpComments.values()) {
+                if(f != null && f.exists()) {
+                    f.delete();
+                }
             }
         }
     }
 
-    private int convert(File outputFile, File commentNormal, File commentOwner) throws InterruptedException, IOException {
+    private int convert(File outputFile, Map<CommentType,File> tmpComments) throws InterruptedException, IOException {
         File fwsFile = null;
         try {
             final File tmpCws = File.createTempFile("cws", ".swf", profile.getTempDir());
@@ -131,7 +132,7 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
             tmpCws.delete();
             final File target = (fwsFile != null) ? fwsFile : videoFile;
 
-            final List<String> arguments = createArguments(target, outputFile, commentNormal, commentOwner);
+            final List<String> arguments = createArguments(target, outputFile, tmpComments);
             final FfmpegUtil util = new FfmpegUtil(profile.getFfmpeg(), target);
             int duration;
             try {
@@ -148,7 +149,7 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
         }
     }
 
-    private List<String> createArguments(final File targetVideoFile, File output, File comment, File commentOwner)
+    private List<String> createArguments(final File targetVideoFile, File output, Map<CommentType,File> comments)
             throws IOException, UnsupportedEncodingException {
         final ConvertProfile prof = profile;
         final FfmpegProfile ffop = prof.getFfmpegOption();
@@ -176,7 +177,7 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
                 cmdList.add(opt);
             }
         }
-        final Info info = MediaInfo.getInfo(new File("bin", "MediaInfo"), targetVideoFile);
+        final Info info = MediaInfo.getInfo(profile.getMediaInfo(), targetVideoFile);
         // 4:3 なら1.33, 16:9 なら1.76
         final boolean isHD = ((double) info.getWidth() / (double) info.getHeight() > 1.5);
         if (ffop.isResize()) {
@@ -187,26 +188,22 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
         }
         final List<String> avfilterArgs = createAvfilterOptions(ffop.getAvfilterOption());
         if (!prof.isVhookDisabled()) {
-            final String vhookArg = getVhookArg(prof, comment.getPath(), commentOwner.getPath(), isHD);
+            final String vhookArg = getVhookArg(prof, comments, isHD);
             if (isNotBlank(vhookArg)) {
                 avfilterArgs.add(vhookArg);
             }
         }
         if (!avfilterArgs.isEmpty()) {
             cmdList.add("-vfilters");
-            final String args =  join(avfilterArgs, ", ");
+            final String args = join(avfilterArgs, ", ");
             cmdList.add(args);
         }
         cmdList.add(output.getPath());
-        final StringBuilder argMsg = new StringBuilder();
-        argMsg.append("arg:");
-        for (String s : cmdList) {
-            argMsg.append(" ").append(s);
-        }
-        logger.info(argMsg.toString());
+
+        logger.info("arg: {}", cmdList);
         return cmdList;
     }
-    private static final Pattern PATTERN_TIME = Pattern.compile("time=(\\d+)");
+    private static final Pattern PATTERN_TIME = Pattern.compile("time=(\\d+):(\\d+):(\\d+)");
 
     private int executeFfmpeg(final List<String> cmdList, int duration) throws InterruptedException, IOException {
         Process process = null;
@@ -221,14 +218,21 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
                     final Matcher m = PATTERN_TIME.matcher(msg);
                     double per = -1.0;
                     if (m.find()) {
-                        final String strTime = m.group(1);
-                        final double time = Double.parseDouble(strTime);
+                        final double hour = Integer.parseInt(m.group(1));
+                        final double min = Integer.parseInt(m.group(2));
+                        final double sec = Integer.parseInt(m.group(3));
+                        final double time = ((hour * 60) + min) * 60 + sec;
                         per = 100.0 * time / duration;
-                        logger.trace("time:{}, duration:{}", time, duration);
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("time:{}, duration:{}", time, duration);
+                            logger.trace(msg);
+                        }
                     }
                     publish(new ConvertProgress(PROCESS, per, msg));
                 } else if (!msg.endsWith("No accelerated colorspace conversion found")) {
                     logger.warn(msg);
+                } else {
+                    logger.info(msg);
                 }
 
                 checkStop();
@@ -251,18 +255,17 @@ public class Convert extends Worker<ConvertResult, ConvertProgress> {
         return avfilterArgs;
     }
 
-    private static String getVhookArg(ConvertProfile prof, String commPath, String commOwnerPath, boolean isHD) throws
+    private static String getVhookArg(ConvertProfile prof, Map<CommentType, File> comments, boolean isHD) throws
             UnsupportedEncodingException {
         StringBuilder sb = new StringBuilder();
         sb.append("vhext=");
         sb.append(prof.getVhook().getPath().replace("\\", "/"));
         if (prof.isCommentOverlay()) {
-            sb.append("|");
-            sb.append("--data-user:");
-            sb.append(URLEncoder.encode(commPath.replace("\\", "/"), "Shift_JIS"));
-            sb.append("|");
-            sb.append("--data-owner:");
-            sb.append(URLEncoder.encode(commOwnerPath.replace("\\", "/"), "Shift_JIS"));
+            for(Entry<CommentType, File> e : comments.entrySet()) {
+                sb.append("|");
+                sb.append(e.getKey().getVhookOptionPrefix());
+                sb.append(URLEncoder.encode(e.getValue().getPath().replace("\\", "/"), "Shift_JIS"));
+            }
         }
         sb.append("|");
         sb.append("--font:");