X-Git-Url: http://git.sourceforge.jp/view?p=coroid%2Finqubus.git;a=blobdiff_plain;f=frontend%2Fsrc%2Fsaccubus%2Fworker%2Fimpl%2Fconvert%2FConvert.java;h=0fa991699adf7c4e8371b31ece73834c222a7168;hp=bcc40f28340c4bc68faaaf151103e1dbc3c1fe12;hb=bc4340e9f1ca17ad2970f58ab19603c5d90b52ef;hpb=7e792afc4f120e799a37e4eb9a2dfa655afbf002 diff --git a/frontend/src/saccubus/worker/impl/convert/Convert.java b/frontend/src/saccubus/worker/impl/convert/Convert.java index bcc40f2..0fa9916 100644 --- a/frontend/src/saccubus/worker/impl/convert/Convert.java +++ b/frontend/src/saccubus/worker/impl/convert/Convert.java @@ -12,10 +12,15 @@ import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; +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.util.FfmpegUtil; import saccubus.worker.Worker; import saccubus.worker.WorkerListener; import saccubus.worker.profile.ConvertProfile; @@ -35,7 +40,7 @@ import yukihane.swf.Cws2Fws; */ public class Convert extends Worker { - private static final Logger logger = Logger.getLogger(Convert.class.getName()); + private static final Logger logger = LoggerFactory.getLogger(Convert.class); private final ConvertProfile profile; private final File videoFile; private final File commentFile; @@ -58,7 +63,7 @@ public class Convert extends Worker { this.profile = profile; this.videoFile = video; this.commentFile = comment; - logger.log(Level.INFO, "convert video:{0}, comment:{1}", new Object[]{videoFile, commentFile}); + logger.info("convert video:{}, comment:{}", videoFile, commentFile); } @Override @@ -69,31 +74,40 @@ public class Convert extends Worker { final GeneralProfile gene = profile.getGeneralProfile(); final OutputProfile outprof = profile.getOutputProfile(); - final OutputNamePattern pattern = new OutputNamePattern(outprof.getFileName()); + final OutputNamePattern outputPattern = new OutputNamePattern(outprof.getFileName()); final String id = outprof.getVideoId(); - pattern.setId(isNotEmpty(id) ? id : ""); + outputPattern.setId(isNotEmpty(id) ? id : ""); final String title = outprof.getTitile(); - pattern.setTitle(isNotEmpty(title) ? title : ""); + outputPattern.setTitle(isNotEmpty(title) ? title : ""); final String fileName = getBaseName(videoFile.getPath()); - pattern.setFileName(fileName); - pattern.setReplaceFrom(gene.getReplaceFrom()); - pattern.setReplaceFrom(gene.getReplaceTo()); - final File outputFile = new File(outprof.getDir(), pattern.createFileName()); + outputPattern.setFileName(fileName); + outputPattern.setReplaceFrom(gene.getReplaceFrom()); + outputPattern.setReplaceFrom(gene.getReplaceTo()); + final File outputFile = new File(outprof.getDir(), + outputPattern.createFileName() + profile.getFfmpegOption().getExtOption()); File transformedComment = null; + File transformedOwner = null; try { if (profile.isCommentOverlay()) { transformedComment = File.createTempFile("vhk", ".tmp", profile.getTempDir()); + transformedOwner = File.createTempFile("vown", ".tmp", profile.getTempDir()); final HideCondition hide = profile.getNgSetting(); + publish(new ConvertProgress(PROCESS, -1.0, "コメントの中間ファイルへの変換中")); - ConvertToVideoHook.convert(commentFile, transformedComment, hide.getId(), hide.getWord()); + ConvertToVideoHook.convert(EnumSet.of(ProcessType.NORMAL), commentFile, transformedComment, hide.getId(), + hide.getWord()); + + publish(new ConvertProgress(PROCESS, -1.0, "投稿者コメントの中間ファイルへの変換中")); + ConvertToVideoHook.convert(EnumSet.of(ProcessType.OWNER), commentFile, transformedOwner, hide.getId(), + hide.getWord()); } checkStop(); publish(new ConvertProgress(PROCESS, -1.0, "動画の変換を開始")); - final int code = convert(transformedComment, outputFile); + final int code = convert(outputFile, transformedComment, transformedOwner); if (code != 0) { throw new IOException("ffmpeg実行失敗: " + outputFile.getPath()); } @@ -103,10 +117,13 @@ public class Convert extends Worker { if (transformedComment != null && transformedComment.exists()) { transformedComment.delete(); } + if (transformedOwner != null && transformedOwner.exists()) { + transformedOwner.delete(); + } } } - private int convert(File transformedComment, File outputFile) throws InterruptedException, IOException { + private int convert(File outputFile, File commentNormal, File commentOwner) throws InterruptedException, IOException { File fwsFile = null; try { final File tmpCws = File.createTempFile("cws", ".swf", profile.getTempDir()); @@ -114,8 +131,16 @@ public class Convert extends Worker { tmpCws.delete(); final File target = (fwsFile != null) ? fwsFile : videoFile; - final List arguments = createArguments(target, transformedComment, outputFile); - return executeFfmpeg(arguments); + final List arguments = createArguments(target, outputFile, commentNormal, commentOwner); + final FfmpegUtil util = new FfmpegUtil(profile.getFfmpeg(), target); + int duration; + try { + duration = util.getDuration(); + } catch (IOException ex) { + logger.info("動画再生時間を取得できませんでした: {}", target); + duration = Integer.MAX_VALUE; + } + return executeFfmpeg(arguments, duration); } finally { if (fwsFile != null && fwsFile.exists()) { fwsFile.delete(); @@ -123,12 +148,12 @@ public class Convert extends Worker { } } - private List createArguments(final File targetVideoFile, File transformedComment, File output) + private List createArguments(final File targetVideoFile, File output, File comment, File commentOwner) throws IOException, UnsupportedEncodingException { final ConvertProfile prof = profile; final FfmpegProfile ffop = prof.getFfmpegOption(); - final List cmdList = new ArrayList(); + final List cmdList = new ArrayList<>(); cmdList.add(prof.getFfmpeg().getPath()); cmdList.add("-y"); final String[] mainOptions = ffop.getMainOption().split(" +"); @@ -162,41 +187,48 @@ public class Convert extends Worker { } final List avfilterArgs = createAvfilterOptions(ffop.getAvfilterOption()); if (!prof.isVhookDisabled()) { - // TODO 引数冗長 - final String vhookArg = getVhookArg(prof, prof.isCommentOverlay(), transformedComment.getPath(), isHD); + final String vhookArg = getVhookArg(prof, comment.getPath(), commentOwner.getPath(), 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.log(Level.INFO, argMsg.toString()); + + logger.info("arg: {}", cmdList); return cmdList; } + private static final Pattern PATTERN_TIME = Pattern.compile("time=(\\d+):(\\d+):(\\d+)"); - private int executeFfmpeg(final List cmdList) throws InterruptedException, IOException { + private int executeFfmpeg(final List cmdList, int duration) throws InterruptedException, IOException { Process process = null; try { - logger.log(Level.INFO, "Processing FFmpeg..."); + logger.info("Processing FFmpeg..."); process = Runtime.getRuntime().exec(cmdList.toArray(new String[0])); BufferedReader ebr = new BufferedReader(new InputStreamReader( process.getErrorStream())); String msg; while ((msg = ebr.readLine()) != null) { if (msg.startsWith("frame=")) { - // TODO パーセンテージ計算、出力 - publish(new ConvertProgress(PROCESS, 0.0, msg)); + final Matcher m = PATTERN_TIME.matcher(msg); + double per = -1.0; + if (m.find()) { + 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; + if (logger.isTraceEnabled()) { + logger.trace("time:{}, duration:{}", time, duration); + } + } + publish(new ConvertProgress(PROCESS, per, msg)); } else if (!msg.endsWith("No accelerated colorspace conversion found")) { - logger.log(Level.INFO, msg); + logger.warn(msg); } checkStop(); @@ -205,7 +237,6 @@ public class Convert extends Worker { process.waitFor(); return process.exitValue(); } finally { - // TODO 正常終了した場合もdestroyしていいのか? if (process != null) { process.destroy(); } @@ -213,22 +244,25 @@ public class Convert extends Worker { } private static List createAvfilterOptions(String avfilterOption) { - final List avfilterArgs = new ArrayList(); + final List avfilterArgs = new ArrayList<>(); if (isNotBlank(avfilterOption)) { avfilterArgs.add(avfilterOption); } return avfilterArgs; } - private static String getVhookArg(ConvertProfile prof, boolean addComment, String commPath, boolean isHD) throws + private static String getVhookArg(ConvertProfile prof, String commPath, String commOwnerPath, boolean isHD) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); sb.append("vhext="); sb.append(prof.getVhook().getPath().replace("\\", "/")); - if (addComment) { + 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")); } sb.append("|"); sb.append("--font:");