1 package saccubus.converter;
4 import java.io.IOException;
5 import java.util.concurrent.Callable;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8 import saccubus.ConvertStopFlag;
9 import saccubus.converter.filegetter.FileInstanciator;
10 import saccubus.net.TextProgressListener;
11 import yukihane.saccubus.converter.profile.FfmpegOption;
12 import yukihane.saccubus.converter.profile.Profile;
17 * <p>説明: ニコニコ動画の動画をコメントつきで保存</p>
19 * <p>著作権: Copyright (c) 2007 PSI</p>
26 public class Converter extends AbstractCommand implements Callable<Boolean> {
28 private final Profile profile;
29 private final String movieId;
30 private final String time;
34 * @param url 対象となる動画のURL.
40 public Converter(String url, String time, Profile profile,
41 TextProgressListener listener, ConvertStopFlag flag) {
42 super(listener, flag);
44 // TODO 入力欄の値から動画IDの切り出しはGUI側でやるべきだろう
45 final int startIdIdx = url.lastIndexOf("/") + 1;
46 final String altId = url.substring(startIdIdx);
47 final Pattern idPattern = Pattern.compile("([a-z]*\\d+)");
48 final Matcher idMatcher = idPattern.matcher(altId);
49 if (idMatcher.find()) {
50 this.movieId = idMatcher.group(1);
52 throw new IllegalArgumentException("URL/IDの指定が不正です: " + url);
56 this.profile = profile;
60 public Boolean call() throws Exception {
61 boolean result = false;
63 result = runConvert();
65 getStopFlag().finished();
67 return Boolean.valueOf(result);
70 // TODO Runnableを実装しなくなったので削除する
74 } catch (Exception ex) {
75 String text = (ex.getMessage() != null) ? ex.getMessage() : "予期しないエラー発生のため中断しました。";
81 private boolean runConvert() throws IOException, InterruptedException {
82 if (!shouldRun(profile)) {
83 sendText("何もすることがありません");
88 final FfmpegOption ov = profile.getFfmpeg().getFfmpegOption();
92 final FileInstanciator fi = createInstanciator();
96 final File videoFile = fi.getVideoFile(getListener());
100 File commentFile = fi.getCommentFile(getListener());
104 File tcommFile = fi.getTcommFile(getListener());
106 if (!profile.needsConvert()) {
107 sendText("動画・コメントを保存し、変換は行いませんでした。");
111 if (!videoFile.isFile()) {
112 throw new IOException("入力動画ファイルが存在しません:" + videoFile.getPath());
115 if (profile.getOutputFileSetting().isAddComment()) {
116 if (!commentFile.isFile()) {
117 throw new IOException("入力コメントファイルが存在しません:" + commentFile.getPath());
123 if (profile.getOutputFileSetting().isAddTcomment()) {
124 if (!tcommFile.isFile()) {
125 throw new IOException("入力投稿者コメントファイルが存在しません" + tcommFile.getPath());
132 File convertedVideoFile;
133 if (!profile.getOutputFileSetting().getFile().isFile()) {
134 String conv_name = fi.getVideoTitle();
135 if (profile.getOutputFileSetting().isAppendPrefixVideoId()) {
136 conv_name = getVideoIDWithBracket() + conv_name;
138 convertedVideoFile = new File(profile.getOutputFileSetting().getFile().getFile(),
139 conv_name + ov.getExtOption());
141 String filename = profile.getOutputFileSetting().getFile().getFile().getPath();
142 if (!filename.endsWith(ov.getExtOption())) {
143 filename = filename.substring(0, filename.lastIndexOf('.')) + ov.getExtOption();
144 convertedVideoFile = new File(filename);
146 convertedVideoFile = profile.getOutputFileSetting().getFile().getFile();
150 boolean res = new FfmpegCommand(getListener(), getStopFlag(), commentFile, tcommFile, videoFile,
151 convertedVideoFile, profile.getFfmpeg(), profile.getGeneralSetting()).execute();
155 private FileInstanciator createInstanciator() throws IOException {
158 FileInstanciator.InstanciationType videoType = new FileInstanciator.InstanciationType(profile.getVideoSetting());
160 FileInstanciator.CommentInstanciationType commentType = new FileInstanciator.CommentInstanciationType(profile.
161 getCommentSetting(), profile.getCommentSetting().isSelfAdjustCommentNum(), profile.getCommentSetting().
162 getBackComment(), profile.getCommentSetting().isReduceComment());
164 FileInstanciator.InstanciationType tcommType = new FileInstanciator.InstanciationType(
165 profile.getCommentSetting());
167 fi = FileInstanciator.create(getStopFlag(), videoType, commentType, tcommType, profile.getLoginInfo(), profile.
168 getProxySetting(), movieId, time);
173 * (ネットワーク設定以外の)設定を検証する.
174 * @throws IllegalArgumentException 設定に不備がある場合.
176 private void validSetting() {
177 if (profile.needsConvert()) {
178 File a = profile.getFfmpeg().getFfmpeg();
180 throw new IllegalArgumentException("FFmpegが見つかりません。");
182 if (profile.getFfmpeg().getVhook().getPath().indexOf(' ') >= 0) {
183 throw new IllegalArgumentException("すいません。現在vhookライブラリには半角空白は使えません。");
185 a = profile.getFfmpeg().getVhook();
187 throw new IllegalArgumentException("Vhookライブラリが見つかりません。");
189 a = profile.getFfmpeg().getFont();
191 throw new IllegalArgumentException("フォントが見つかりません。");
196 private String getVideoIDWithBracket() {
197 return "[" + movieId + "]";
200 public boolean isConverted() {
201 return getStopFlag().isFinished();
205 public ConvertStopFlag getStopFlag() {
206 return super.getStopFlag();
209 /** @return 何か実行すべき処理があればtrue. */
210 private static boolean shouldRun(Profile profile) {
211 return profile.getOutputFileSetting().isConvert() || needsDownload(profile);
214 /** @return 何かダウンロードするものがあればtrue. */
215 private static boolean needsDownload(Profile profile) {
216 return (profile.getVideoSetting().isDownload() || profile.getCommentSetting().isDownload());