1 package saccubus.converter;
3 import yukihane.saccubus.converter.profile.Profile;
4 import saccubus.converter.filegetter.FileInstanciator;
6 import java.io.IOException;
7 import java.util.concurrent.Callable;
8 import saccubus.ConvertStopFlag;
9 import yukihane.saccubus.converter.profile.FfmpegOption;
10 import saccubus.net.TextProgressListener;
15 * <p>説明: ニコニコ動画の動画をコメントつきで保存</p>
17 * <p>著作権: Copyright (c) 2007 PSI</p>
24 public class Converter extends AbstractCommand implements Runnable, Callable<Boolean> {
26 private static final String VIDEO_URL_PARSER = "http://www.nicovideo.jp/watch/";
27 private final Profile profile;
28 private final String movieId;
29 private final String time;
33 * @param url 対象となる動画のURL.
39 public Converter(String url, String time, Profile profile,
40 TextProgressListener listener, ConvertStopFlag flag) {
41 super(listener, flag);
43 if (url.startsWith(VIDEO_URL_PARSER)) {
44 int index = url.indexOf('?', VIDEO_URL_PARSER.length());
46 movieId = url.substring(VIDEO_URL_PARSER.length(), index);
48 movieId = url.substring(VIDEO_URL_PARSER.length());
54 this.profile = profile;
57 public Boolean call() throws Exception {
58 boolean result = false;
60 result = runConvert();
62 getStopFlag().finished();
64 return Boolean.valueOf(result);
70 } catch (Exception ex) {
71 String text = (ex.getMessage() != null) ? ex.getMessage() : "予期しないエラー発生のため中断しました。";
77 private boolean runConvert() throws IOException, InterruptedException {
78 if (!shouldRun(profile)) {
79 sendText("何もすることがありません");
84 final FfmpegOption ov = profile.getFfmpeg().getFfmpegOption();
88 final FileInstanciator fi = createInstanciator();
92 final File videoFile = fi.getVideoFile(getListener());
96 File commentFile = fi.getCommentFile(getListener());
100 File tcommFile = fi.getTcommFile(getListener());
102 if (!profile.needsConvert()) {
103 sendText("動画・コメントを保存し、変換は行いませんでした。");
107 if (!videoFile.isFile()) {
108 throw new IOException("入力動画ファイルが存在しません:" + videoFile.getPath());
111 if (profile.getOutputFileSetting().isAddComment()) {
112 if (!commentFile.isFile()) {
113 throw new IOException("入力コメントファイルが存在しません:" + commentFile.getPath());
119 if (profile.getOutputFileSetting().isAddTcomment()) {
120 if (!tcommFile.isFile()) {
121 throw new IOException("入力投稿者コメントファイルが存在しません" + tcommFile.getPath());
128 File convertedVideoFile;
129 if (!profile.getOutputFileSetting().getFile().isFile()) {
130 String conv_name = fi.getVideoTitle();
131 if (profile.getOutputFileSetting().isAppendPrefixVideoId()) {
132 conv_name = getVideoIDWithBracket() + conv_name;
134 convertedVideoFile = new File(profile.getOutputFileSetting().getFile().getFile(),
135 conv_name + ov.getExtOption());
137 String filename = profile.getOutputFileSetting().getFile().getFile().getPath();
138 if (!filename.endsWith(ov.getExtOption())) {
139 filename = filename.substring(0, filename.lastIndexOf('.')) + ov.getExtOption();
140 convertedVideoFile = new File(filename);
142 convertedVideoFile = profile.getOutputFileSetting().getFile().getFile();
146 boolean res = new FfmpegCommand(getListener(), getStopFlag(), commentFile, tcommFile, videoFile,
147 convertedVideoFile, profile.getFfmpeg(), profile.getGeneralSetting()).execute();
149 if (profile.getCommentSetting().isDelete()) {
150 commentFile.delete();
152 if (profile.getVideoSetting().isDelete()) {
155 if (profile.getTcommentSetting().isDelete()) {
162 private FileInstanciator createInstanciator() throws IOException {
165 FileInstanciator.InstanciationType videoType = new FileInstanciator.InstanciationType(profile.getVideoSetting());
167 FileInstanciator.CommentInstanciationType commentType = new FileInstanciator.CommentInstanciationType(profile.
168 getCommentSetting(), profile.getCommentGetInfo().isselfAdjustCommentNum(), profile.getCommentGetInfo().
171 FileInstanciator.InstanciationType tcommType = new FileInstanciator.InstanciationType(
172 profile.getTcommentSetting());
174 fi = FileInstanciator.create(getStopFlag(), videoType, commentType, tcommType, profile.getLoginInfo(), movieId,
180 * (ネットワーク設定以外の)設定を検証する.
181 * @throws IllegalArgumentException 設定に不備がある場合.
183 private void validSetting() {
184 if (profile.needsConvert()) {
185 File a = profile.getFfmpeg().getFfmpeg();
187 throw new IllegalArgumentException("FFmpegが見つかりません。");
189 if (profile.getFfmpeg().getVhook().getPath().indexOf(' ') >= 0) {
190 throw new IllegalArgumentException("すいません。現在vhookライブラリには半角空白は使えません。");
192 a = profile.getFfmpeg().getVhook();
194 throw new IllegalArgumentException("Vhookライブラリが見つかりません。");
196 a = profile.getFfmpeg().getFont();
198 throw new IllegalArgumentException("フォントが見つかりません。");
201 if (profile.getVideoSetting().isDelete()) {
202 throw new IllegalArgumentException("変換しないのに、動画削除しちゃって良いんですか?");
204 if (profile.getCommentSetting().isDelete()) {
205 throw new IllegalArgumentException("変換しないのに、コメント削除しちゃって良いんですか?");
207 if (profile.getTcommentSetting().isDelete()) {
208 throw new IllegalArgumentException("変換しないのに、投稿者コメント削除しちゃって良いんですか?");
213 private String getVideoIDWithBracket() {
214 return "[" + movieId + "]";
217 public boolean isConverted() {
218 return getStopFlag().isFinished();
222 public ConvertStopFlag getStopFlag() {
223 return super.getStopFlag();
226 /** @return 何か実行すべき処理があればtrue. */
227 private static boolean shouldRun(Profile profile) {
228 return profile.getOutputFileSetting().isConvert() || needsDownload(profile);
231 /** @return 何かダウンロードするものがあればtrue. */
232 private static boolean needsDownload(Profile profile) {
233 return (profile.getVideoSetting().isDownload() || profile.getCommentSetting().isDownload() || profile.
234 getTcommentSetting().isDownload());