import saccubus.conv.ConvertToVideoHook;
import saccubus.worker.profile.ConvertProfile;
import saccubus.worker.profile.FfmpegProfile;
-import saccubus.worker.profile.GeneralProfile;
import yukihane.mediainfowrapper.Info;
import yukihane.mediainfowrapper.MediaInfo;
import yukihane.mediainfowrapper.Size;
import saccubus.worker.profile.ConvertProfile.HideCondition;
-import saccubus.worker.profile.Profile;
import yukihane.swf.Cws2Fws;
/**
- *
+ * 動画を(コメント付きに)変換するワーカクラス.
* @author yuki
*/
public class Convert extends SwingWorker<ConvertResult, ConvertProgress> {
private static final Logger logger = Logger.getLogger(Convert.class.getName());
- private final File commentMiddleFile;
- private final File tcommMiddleFile;
- private final File TMP_CWS;
- private final File commentFile;
+ private final ConvertProfile profile;
private final File videoFile;
- private final File convertedVideoFile;
- private final ConvertProfile ffmpeg;
-
- Convert(ConvertProfile ffmpeg, File commentFile, File videoFile, File convertedVideoFile) throws IOException {
- this.commentFile = commentFile;
- this.videoFile = videoFile;
- this.convertedVideoFile = convertedVideoFile;
- this.ffmpeg = ffmpeg;
-
- File tmpDir = ffmpeg.getTempDir();
- commentMiddleFile = File.createTempFile("vhk", ".tmp", tmpDir);
- tcommMiddleFile = File.createTempFile("tcom", ".tmp", tmpDir);
- TMP_CWS = File.createTempFile("cws", ".swf", tmpDir);
+ private final File commentFile;
+ private final File outputFile;
+ private File transformedComment;
+
+ /**
+ * 変換ワーカコンストラクタ.
+ * @param profile 変換用プロファイル.
+ * @param video 変換元動画.
+ * @param comment 変換元コメント. コメントを付与しない場合はnull.
+ * @param output 変換後出力動画.
+ * @throws IOException 変換失敗.
+ */
+ public Convert(ConvertProfile profile, File video, File comment, File output) throws IOException {
+ this.profile = profile;
+ this.videoFile = video;
+ this.commentFile = comment;
+ this.outputFile = output;
}
@Override
protected ConvertResult doInBackground() throws Exception {
try {
- return exec();
- } finally {
- if (commentMiddleFile.exists()) {
- commentMiddleFile.delete();
- }
- if (tcommMiddleFile.exists()) {
- tcommMiddleFile.delete();
- }
- if (TMP_CWS.exists()) {
- TMP_CWS.delete();
+ transformedComment = File.createTempFile("vhk", ".tmp", profile.getTempDir());
+
+ final HideCondition hide = profile.getNgSetting();
+ if (commentFile != null) {
+ publish(new ConvertProgress("コメントの中間ファイルへの変換中"));
+ final boolean conv = ConvertToVideoHook.convert(commentFile, transformedComment, hide.getId(), hide.
+ getWord());
+ if (!conv) {
+ throw new IOException("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?");
+ }
}
- }
- }
- private ConvertResult exec() throws InterruptedException, IOException {
- final HideCondition ngSetting = getFfmpeg().getNgSetting();
- if (commentFile != null) {
- publish(new ConvertProgress("コメントの中間ファイルへの変換中"));
- boolean conv = ConvertToVideoHook.convert(commentFile, commentMiddleFile, ngSetting.getId(), ngSetting.
- getWord());
- if (!conv) {
- publish(new ConvertProgress("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?"));
+ checkStop();
+ publish(new ConvertProgress("動画の変換を開始"));
+
+ final int code = convert();
+ if (code != 0) {
+ publish(new ConvertProgress("変換エラー:" + outputFile.getPath()));
return new ConvertResult(false);
}
- }
- checkStop();
-// if (tcommFile != null) {
-// sendText("投稿者コメントの中間ファイルへの変換中");
-// boolean conv = ConvertToVideoHook.convert(tcommFile, tcommMiddleFile, ngSetting.getId(), ngSetting.getWord());
-// if (!conv) {
-// sendText("コメント変換に失敗。ファイル名に使用できない文字が含まれているか正規表現の間違い?");
-// return false;
-// }
-// }
-// stopFlagReturn();
- publish(new ConvertProgress("動画の変換を開始"));
- int code;
- if ((code = converting_video(videoFile, convertedVideoFile, (commentFile != null), commentMiddleFile.getPath(),
- false, tcommMiddleFile.getPath(), getFfmpeg().getFfmpegOption())) == 0) {
publish(new ConvertProgress("変換が正常に終了しました。"));
return new ConvertResult(true);
- } else {
- publish(new ConvertProgress("変換エラー:" + convertedVideoFile.getPath()));
+ } finally {
+ if (transformedComment != null && transformedComment.exists()) {
+ transformedComment.delete();
+ }
}
- return new ConvertResult(false);
}
- 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);
+ private int convert() throws InterruptedException, IOException {
+ File tmpCws = null;
+ File fwsFile = null;
+ try {
+ tmpCws = File.createTempFile("cws", ".swf", profile.getTempDir());
+ fwsFile = Cws2Fws.createFws(videoFile, tmpCws);
+ final File target = (fwsFile != null) ? fwsFile : videoFile;
- List<String> cmdList = new ArrayList<String>();
- cmdList.add(getFfmpeg().getFfmpeg().getPath());
+ final List<String> arguments = createArguments(profile.getFfmpegOption(), target);
+ return executeFfmpeg(arguments);
+ } finally {
+ if (tmpCws != null && tmpCws.exists()) {
+ tmpCws.delete();
+ }
+ if (fwsFile != null && fwsFile.exists()) {
+ fwsFile.delete();
+ }
+ }
+ }
+
+ // TODO static にできた方が良い
+ private List<String> createArguments(final FfmpegProfile ffop, final File targetVideoFile)
+ throws IOException,
+ UnsupportedEncodingException {
+ final List<String> cmdList = new ArrayList<String>();
+ cmdList.add(profile.getFfmpeg().getPath());
cmdList.add("-y");
- String[] mainOptions = ov.getMainOption().split(" +");
+ final String[] mainOptions = ffop.getMainOption().split(" +");
for (String opt : mainOptions) {
if (StringUtils.isNotBlank(opt)) {
cmdList.add(opt);
}
}
- String[] inOptions = ov.getInOption().split(" +");
+ final String[] inOptions = ffop.getInOption().split(" +");
for (String opt : inOptions) {
if (StringUtils.isNotBlank(opt)) {
cmdList.add(opt);
}
}
cmdList.add("-i");
-
- if (fwsFile == null) {
- cmdList.add(videoFile.getPath());
- } else {
- cmdList.add(fwsFile.getPath());
- }
- String[] outOptions = ov.getOutOption().split(" +");
+ cmdList.add(targetVideoFile.getPath());
+ final String[] outOptions = ffop.getOutOption().split(" +");
for (String opt : outOptions) {
if (StringUtils.isNotBlank(opt)) {
cmdList.add(opt);
}
}
-
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.
+ final boolean isHD = ((double) info.getWidth() / (double) info.getHeight() > 1.5);
+ if (ffop.isResize()) {
+ final Size scaled = (ffop.isAdjustRatio()) ? MediaInfo.adjustSize(info, ffop.getResizeWidth(), ffop.
getResizeHeight()) : new Size(info.getWidth(), info.getHeight());
cmdList.add("-s");
cmdList.add(scaled.getWidth() + "x" + scaled.getHeight());
}
-
- List<String> avfilterArgs = getAvfilterOptions(ov.getAvfilterOption());
- if (!getFfmpeg().isVhookDisabled()) {
- String vhookArg = getVhookArg(addComment, commPath, addTcomment, tcommPath, isHD);
+ final List<String> avfilterArgs = createAvfilterOptions(ffop.getAvfilterOption());
+ if (!profile.isVhookDisabled()) {
+ final boolean addComment = (commentFile != null);
+ final String vhookArg = getVhookArg(profile, addComment, transformedComment.getPath(), isHD);
if (StringUtils.isNotBlank(vhookArg)) {
avfilterArgs.add(vhookArg);
}
}
-
if (!avfilterArgs.isEmpty()) {
cmdList.add("-vfilters");
final String args = "\"" + StringUtils.join(avfilterArgs, ", ") + "\"";
cmdList.add(args);
}
-
- cmdList.add(convertedVideoFile.getPath());
-
+ cmdList.add(outputFile.getPath());
final StringBuilder argMsg = new StringBuilder();
argMsg.append("arg:");
for (String s : cmdList) {
argMsg.append(" ").append(s);
}
logger.log(Level.INFO, argMsg.toString());
+ return cmdList;
+ }
+ private int executeFfmpeg(final List<String> cmdList) throws InterruptedException, IOException {
Process process = null;
try {
- logger.log(Level.INFO, "\n\n----\nProcessing FFmpeg...\n----\n\n");
+ logger.log(Level.INFO, "Processing FFmpeg...");
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=")) {
- publish(new ConvertProgress(state));
- } else if (!state.endsWith("No accelerated colorspace conversion found")) {
- logger.log(Level.INFO, e);
- }
-
- try {
- checkStop();
- } catch (InterruptedException ex) {
- throw ex;
+ String msg;
+ while ((msg = ebr.readLine()) != null) {
+ if (msg.startsWith("frame=")) {
+ publish(new ConvertProgress(msg));
+ } else if (!msg.endsWith("No accelerated colorspace conversion found")) {
+ logger.log(Level.INFO, msg);
}
+ checkStop();
}
+
process.waitFor();
return process.exitValue();
} finally {
if (process != null) {
process.destroy();
}
- if (fwsFile != null) {
- fwsFile.delete();
- }
}
}
- private List<String> getAvfilterOptions(String avfilterOption) {
+ private static List<String> createAvfilterOptions(String avfilterOption) {
final List<String> avfilterArgs = new ArrayList<String>();
if (StringUtils.isNotBlank(avfilterOption)) {
avfilterArgs.add(avfilterOption);
return avfilterArgs;
}
- private String getVhookArg(boolean addComment, String commPath, boolean addTcomment,
- String tcommPath, boolean isHD) throws UnsupportedEncodingException {
+ private static String getVhookArg(ConvertProfile prof, boolean addComment, String commPath, boolean isHD) throws
+ UnsupportedEncodingException {
StringBuilder sb = new StringBuilder();
sb.append("vhext=");
- sb.append(getFfmpeg().getVhook().getPath().replace("\\", "/"));
+ sb.append(prof.getVhook().getPath().replace("\\", "/"));
if (addComment) {
sb.append("|");
sb.append("--data-user:");
sb.append(URLEncoder.encode(commPath.replace("\\", "/"), "Shift_JIS"));
}
- if (addTcomment) {
- sb.append("|");
- 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"));
+ prof.getFont().getPath().replace("\\", "/"), "Shift_JIS"));
sb.append("|");
sb.append("--font-index:");
- sb.append(getFfmpeg().getFontIndex());
+ sb.append(prof.getFontIndex());
sb.append("|");
sb.append("--show-user:");
- sb.append(getFfmpeg().getMaxNumOfComment());
+ sb.append(prof.getMaxNumOfComment());
sb.append("|");
sb.append("--shadow:");
- sb.append(getFfmpeg().getShadowIndex());
+ sb.append(prof.getShadowIndex());
sb.append("|");
- if (getFfmpeg().isShowConverting()) {
+ if (prof.isShowConverting()) {
sb.append("--enable-show-video");
sb.append("|");
}
- if (!getFfmpeg().isDisableFontSizeArrange()) {
+ if (!prof.isDisableFontSizeArrange()) {
sb.append("--enable-fix-font-size");
sb.append("|");
}
- if (getFfmpeg().isCommentOpaque()) {
+ if (prof.isCommentOpaque()) {
sb.append("--enable-opaque-comment");
sb.append("|");
}
return sb.toString();
}
- private ConvertProfile getFfmpeg() {
- return ffmpeg;
- }
-
protected void checkStop() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException("中止要求を受け付けました");