SSブログ

フォルダアクションで、iTunes にファイルを登録 [Mac]

ffmpeg で変換したファイルを自動で iTunes へ直接追加してみようと思ったのだが、
フォルダ監視をどうやればいいのかわからなかった。
いつもどおりググってみたところ、
この記事のコメントに書かれていたスクリプトが簡単だったので使わせてもらう事に。

busy status とかでは、ファイルの書き込み中のステータスが検出できず、
ffmpeg がファイルを開いたと同時に登録を中身なしファイルに対して始めてしまって
どうにも具合が悪いので、perl スクリプト側ではいったんテンポラリファイル名で作成し、
完成したところで正式名(の拡張子付き)にリネームし、iTunes への登録トリガとすることにした。
ファイルのドラッグ&ドロップでは動くのを確認したが、はたして本番でうまく動作するだろうか。

property extension_list : {"mp3", "m4a", "m4v", "mp4", "m4b"}

on adding folder items to my_folder after receiving the_files
	repeat with i from 1 to number of items in the_files
		set this_item to (item i of the_files)
		set the item_info to info for this_item
		if the name extension of the item_info is in the extension_list then
			--display dialog "Adding " & the name of item_info & " to iTunes"
			tell application "iTunes"
				try
					set this_track to add this_item to playlist "ライブラリ" of source "ライブラリ"
					duplicate this_track to user playlist " New"
				end try
			end tell
		end if
	end repeat
end adding folder items to

AppleScript Programming for Mac OS X ―Mac OS X v10.2対応

AppleScript Programming for Mac OS X ―Mac OS X v10.2対応

  • 作者: 掌田 津耶乃
  • 出版社/メーカー: ソシム
  • 発売日: 2002/10
  • メディア: 単行本


Parallels build 3186 [Mac]

Parallels をタイトルのビルドへ更新。

ブートキャンプパーティションの Windows XP を使っているが、
特に問題なく更新できた。

更新後、どうも全体に重く感じられたので、XP へのメモリ割当を減らした。
XP では今の所たいした事はさせてないので、512MB->256MBへメモリを割当を変更。
普通に使えるようになった。

はやく2GB へメモリを増設しないと。

Parallels Desktop for Mac

Parallels Desktop for Mac

  • 出版社/メーカー: プロトン
  • 発売日: 2006/11/11
  • メディア: ソフトウェア


OSX で CCDirectory みたいな事がしたい (3) [Mac]

続いて、CyberLink for Perl への差分。
これで、iTunes のライブラリ/TV番組にファイルが入ってくれる事を期待してるが、
まだ podcast としてはライブラリ登録させてないので、どうなるか不明。

--- ../Documents/download/Net-UPnP-1.1.3/lib/Net/UPnP/AV/Content.pm     2005-12-09 02:56:32.000000000 +0900
+++ /Library/Perl/5.8.6/Net/UPnP/AV/Content.pm  2007-02-27 02:20:27.000000000 +0900
@@ -7,11 +7,13 @@
 use strict;
 use warnings;
 
-use vars qw($_ID $_TITLE $_DATE);
+use vars qw($_ID $_TITLE $_DATE $_DATETIME $_CHANNELNAME);
 
 $_ID = '_id';
 $_TITLE = '_title';
 $_DATE = '_date';
+$_DATETIME = '_datetime';
+$_CHANNELNAME = '_channelname';
 
 #------------------------------
 # new
@@ -23,6 +25,8 @@
                $Net::UPnP::AV::Content::_ID => '',
                $Net::UPnP::AV::Content::_TITLE => '',
                $Net::UPnP::AV::Content::_DATE => '',
+               $Net::UPnP::AV::Content::_DATETIME => '',
+               $Net::UPnP::AV::Content::_CHANNELNAME => '',
        };
        bless $this, $class;
 }
@@ -75,6 +79,30 @@
        $this->{$Net::UPnP::AV::Content::_DATE};
 }
 
+sub setchannelName() {
+        my($this) = shift;
+        if (@_) {
+                $this->{$Net::UPnP::AV::Content::_CHANNELNAME} = $_[0];
+        }
+}
+
+sub getchannelName() {
+        my($this) = shift;
+        $this->{$Net::UPnP::AV::Content::_CHANNELNAME};
+}
+
+sub setdateTime() {
+        my($this) = shift;
+        if (@_) {
+                $this->{$Net::UPnP::AV::Content::_DATETIME} = $_[0];
+        }
+}
+
+sub getdateTime() {
+        my($this) = shift;
+        $this->{$Net::UPnP::AV::Content::_DATETIME};
+}
+
 #------------------------------
 # is*
 #------------------------------
diff -wuBr --exclude='*~' ../Documents/download/Net-UPnP-1.1.3/lib/Net/UPnP/AV/MediaServer.pm /Library/Perl/5.8.6/Net/UPnP/AV/MediaServer.pm
--- ../Documents/download/Net-UPnP-1.1.3/lib/Net/UPnP/AV/MediaServer.pm 2005-12-09 02:56:32.000000000 +0900
+++ /Library/Perl/5.8.6/Net/UPnP/AV/MediaServer.pm      2007-02-27 03:01:38.000000000 +0900
@@ -149,16 +149,27 @@
                $content,
                $container,
                $item,
+           $total_matches,
+           $number_returned,
+           $start_index,
+           $request_count,
        );
 
        @content_list = ();
+       $total_matches = 0;
+    $number_returned = 0;
+                   $request_count =$args{RequestedCount};
+                   $start_index = $args{StartingIndex};
+
+do {
        $action_res = $this->browsedirectchildren(
                        ObjectID => $args{ObjectID},
                        Filter => $args{Filter},
-                       StartingIndex => $args{StartingIndex},
-                       RequestedCount => $args{RequestedCount},
+                       StartingIndex => $start_index,
+                       RequestedCount => $request_count,
                        SortCriteria => $args{SortCriteria}
                        );
+#print $action_res;
        if ($action_res->getstatuscode() != 200) {
                return @content_list;
        }
@@ -168,6 +179,10 @@
        }
        $result = $arg_list->{'Result'};
 
+                   $number_returned = $arg_list->{'NumberReturned'};
+                   $total_matches = $arg_list->{'TotalMatches'};
+#print $result;
+
        while ($result =~ m//sgi) {
                $content = $1;
                $container = Net::UPnP::AV::Container->new();
@@ -181,7 +196,7 @@
                        $container->setdate($1);
                }
                push (@content_list, $container);
-               #print "container(" . $container->getid() . ") = " . $container->gettitle() . "\n";
+               print "container(" . $container->getid() . ") = " . $container->gettitle() . "\n";
                #print $1;
        }
 
@@ -197,6 +212,12 @@
                if ($content =~ m/(.*)<\/dc:date>/si) {
                        $item->setdate($1);
                }
+               if ($content =~ m/(.*)<\/av:dateTime>/si) {
+                       $item->setdateTime($1);
+               }
+               if ($content =~ m/(.*)<\/upnp:channelName>/si) {
+                       $item->setchannelName($1);
+               }
                if ($content =~ m/]*>(.*?)<\/res>/si) {
                        $item->seturl(Net::UPnP::HTTP::xmldecode($1));
                }
@@ -207,8 +228,14 @@
                        $item->setcontenttype($1);
                }
                push (@content_list, $item);
+               #print $item;
        }
 
+$start_index += $number_returned;
+       if ($request_count > 0) {
+       $request_count -= $number_returned;
+    }
+} while ($start_index < $total_matches);
        @content_list;
 }
 
次は、いよいよビデオポッドキャストとして登録するとどうなるかにチャレンジ。

OSX で CCDirectory みたいな事がしたい (2) [Mac]

dms2vodcast.pl を以下のように変更

・curl でテンポラリファイルを作らないで直接 ffmpeg の stdin へ入力 (先頭10秒弱切れる)
・ffmpeg で、-title をつける。(au W44S用)
・AtomicParsley で、コクーンから取得できていて埋められる情報は全部埋める

だいたい、Core Duo 2GHz で、実時間の半分弱でエンコードできる模様。

以下差分。

--- ../Documents/download/dms2vodcast-1.pl.html 2007-02-27 03:21:43.000000000 +0900
+++ ./dms2vodcast.pl    2007-02-27 03:05:07.000000000 +0900
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 
 use Net::UPnP::ControlPoint;
 use Net::UPnP::AV::MediaServer;
@@ -47,7 +47,7 @@
 ['-l', '--rss-link', '', 'Set the link tag in the output RSS file'],
 ['-r', '--requested-count', '', 'Set the max request count to the media server contents'],
 ['-t', '--rss-title', '', 'Set the title tag in the output RSS file'],
-['-f', '--mp4-format', '', 'Set the MPEG4 format'],
+['-f', '--mp4-format', '', 'Set the MPEG4 format'],
 ['-s', '--search-title', '', 'Set the regular expression of the content titles by UTF-8'],
 );
 
@@ -114,7 +114,7 @@
                $rss_title = $ARGV[++$i];
        } elsif ($opt_short_name eq '-f') {
                $mp4_format = $ARGV[++$i];
-               if ($mp4_format ne 'ipod' && $mp4_format ne 'psp') {
+               if ($mp4_format ne 'ipod' && $mp4_format ne 'psp' && $mp4_format ne 'w44s') {
                        print "Unkown MPEG4 format : $mp4_format !!\n";
                        exit 1;
                }
@@ -248,6 +248,7 @@
                                }
                        }
                }
+               print $title; print "\n"
        }
 
        unless ($content->iscontainer()) {
@@ -257,6 +258,7 @@
        my @child_content_list = $mediaServer->getcontentlist(ObjectID => $objid );
 
        if (@child_content_list <= 0) {
+       print "return @@@\n";
                return;
        }
 
@@ -273,9 +275,12 @@
        ($mediaServer, $content) = @_;
        my $objid = $content->getid();
        my $title = $content->gettitle();
+       my $date = $content->getdate();
+       my $dateTime = $content->getdateTime();
+       my $channelName = $content->getchannelName();
        my $url = $content->geturl();
 
-       print "[$objid] $title ($url)\n";
+       print "[$objid] $title ($url), $date\n";
 
        my $dev = $mediaServer->getdevice();
        my $dev_friendlyname = $dev->getfriendlyname();
@@ -287,25 +292,40 @@
        $filename_body =~ s/\//-/g;
 
        my $mpeg2_file_name = $filename_body . ".mpeg";
-       my $mpeg4_file_name = $filename_body . "_" . $mp4_format . ".m4v";
+       my $mpeg4_file_name = $filename_body . "_" . $date . "_" . $mp4_format . ".m4v";
        my $output_mpeg4_file_name = $base_directory . $mpeg4_file_name;
 
        if (!(-e $output_mpeg4_file_name)) {
-               $curl_opt = "\"$url\" -o \"$mpeg2_file_name\"";
-               print "curl $curl_opt\n";
-               curl($curl_opt);
+               $curl_opt = "\"$url\" -s";
 
-               if ($mp4_format eq 'psp') {
-                       $ffmpeg_opt = "-y -i \"$mpeg2_file_name\" -bitexact -fixaspect -s 320x240 -r 29.97 -b 768 -ar 24000 -ab 32 -f psp \"$output_mpeg4_file_name\"";
-               }
-               else {
-                       $ffmpeg_opt = "-y -i \"$mpeg2_file_name\" -bitexact -fixaspect -s 320x240 -r 29.97 -b 850 -acodec aac -ac 2 -ar 44100 -ab 64 -f mp4 \"$output_mpeg4_file_name\"";
-               }
+#              $curl_opt = "\"$url\" -o \"$mpeg2_file_name\"";
+#              my $mpeg2_file_size = -s $mpeg2_file_name;
+#              if (($mpeg2_file_size <= 0) ||
+#                  !(-e $mpeg2_file_name)) {
+#                  print "curl $curl_opt\n";
+#                  curl($curl_opt);
+#              }
 
-               print "ffmpeg $ffmpeg_opt\n";
-               ffmpeg($ffmpeg_opt);
-
-               unlink($mpeg2_file_name);
+               if ($mp4_format eq 'psp') {
+#                      $ffmpeg_opt = "-y -i \"$mpeg2_file_name\" -bitexact -fixaspect -s 320x240 -r 29.97 -b 768 -ar 24000 -ab 32 -f psp \"$output_mpeg4_file_name\"";
+                   $ffmpeg_opt = "-y -vcodec h264 -coder 1 -bufsize 4096Kib -maxrate 320kb -g 250 -r ntsc-film -qmin 24 -qmax 28 -mb rd -me full -cmp 2 -subcmp 2 -subq 7 -refs 2 -flags loop -deblockalpha -1 -flags2 wpred+mixed_refs+brdo+8x8dct -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -nr 1 -i \"$mpeg2_file_name\" -bitexact -fixaspect -s 320x240 -r 29.97 -b 768 -ar 48000 -ab 48 -f psp \"$output_mpeg4_file_name\"";
+                   } elsif ($mp4_format eq 'ipod') {
+#                      $ffmpeg_opt = "-y -i \"$mpeg2_file_name\" -bitexact -fixaspect -s 320x240 -r 29.97 -b 850 -acodec aac -ac 2 -ar 44100 -ab 64 -f mp4 \"$output_mpeg4_file_name\"";
+                       $ffmpeg_opt = "-i - -y -threads 2 -vcodec xvid -bitexact -fixaspect -s 320x240 -r 29.97 -qscale 3 -maxrate 850 -acodec aac -ac 2 -ar 48000 -ab 128 -f mp4 \"$output_mpeg4_file_name\"";
+                   } elsif ($mp4_format eq 'w44s') {
+                       # fast conversion
+                       $ffmpeg_opt = "-i - -y -threads 2 -vcodec xvid -bitexact -fixaspect -s 320x240 -r 29.97 -qscale 3 -maxrate 768 -acodec aac -ac 2 -ar 48000 -ab 128 -f psp -title \"\[$date\]$title\" \"$output_mpeg4_file_name\"";
+
+                       # high quality
+                       # $ffmpeg_opt = "-i - -itsoffset -00:00:00 -t 03:00:00 -threads 2 -y -async 1000 -vcodec xvid -qns -qpel -mbd 2 -trell -aic -me full -bitexact -fixaspect -s 320x240 -r 29.97 -g 60 -qscale 3 -maxrate 768 -deinterlace -acodec aac -ac 2 -ar 48000 -ab 128 -f psp -title \"\[$date\]$title\" \"$output_mpeg4_file_name\"";
+                   }
+
+               print "curl $curl_opt | ffmpeg $ffmpeg_opt";
+               system "curl $curl_opt | ffmpeg $ffmpeg_opt";
+
+               # print "ffmpeg $ffmpeg_opt\n";
+               # ffmpeg($ffmpeg_opt);
+               # unlink($mpeg2_file_name);
        }
 
        if (!(-e $output_mpeg4_file_name)) {
@@ -318,6 +338,10 @@
                return undef;
        }
 
+       my $atomic_opt = "$output_mpeg4_file_name -W -M --title \"\[$date\]$title\" -y \"$dateTime\" -n \"$channelName\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"\[$date\]$title\" lang=jp";
+       print "AtomicParsley $atomic_opt" . "\n";
+       system "AtomicParsley $atomic_opt";
+
        my %info = (
                'objid' => $objid,
                'title' => $title,
次は CyberLink for Perl 側の差分。 続く。

OSX で CCDirectory みたいな事がしたい [Mac]

携帯動画変換君とセットで利用すると便利なソフトに、同じ作者の方が作ってくれた
CCDirectory というソフトがある。

これは、コクーンというDVRからUPnP AVでコンテンツリストをダウンロードして表示し、
このリストからアイテムを選んで変換君へドラッグ&ドロップするとURLが渡って、
変換君(中のffmpeg?)がDVRからMPEG2-TS をダウンロードして所望のフォーマットへ変換してくれる、
というものである。

このソフトは激しく便利なのだが、OSX ではそのままでは使えない。
あと、手動で動かすのが基本なので、デイリーでWBSを変換してiTunesに登録とかいう
用途には向かない気がする。(実はオプションがあったりして)

で、ちょっと探してみると、

このようにしている方や、
こんな風にしている先達がいらっしゃることがわかった。

この、CyberGarage の Satoshi Konno さんのやられてるのがやりたいことそのものだったので、
やってみた。

レシピ:
perl もとから入ってるので不要
curl もとから入ってるので不要
ffmpeg iSquint のパッケージから取り出し(intel Mac なので)
CyberLink for Perl http://search.cpan.org/~skonno/Net-UPnP-1.1.3/
# 1.1.3 を使った
dms2vodcast.pl CyberGarage さんの該当アーティクルから取得

まず、CyberLink for Perl をインストールする。
MediaServer.pm を、コンテンツリスト全件取得できるよう修正。
# 1.2.1 だと修正されてるのかも。
次に、
ffmpeg をパスの通っているところに置く。
最後に、
dms2vodcast.pl の ffmpeg のオプションに、-threads 2 とか追加する。

これで、あとは使い方説明のとおりに実行すれば、変換されて .xml ファイルと
一緒に準備されてめでたしめでたしとなる。

...
これは、ビデオ iPod に買い替えないとだけど、新型はいつ出るんだろう。

Apple iPod 30GB ホワイト MA444J/A

Apple iPod 30GB ホワイト MA444J/A

  • 出版社/メーカー: アップルコンピュータ
  • 発売日: 2006/09/13
  • メディア: エレクトロニクス

追記:
-threads オプションをつけると、音がおかしくなるようで、このオプションは使用不可。

追記2:
こちらのffmpeg では、-threads オプションが使用可能。


Mac OS X Internals [Mac]

最近リスニングばかりで本を読んでないので買ってみた。
ほんとに厚くて重くてびっくりしたけど、読んでて楽しいですなこれ。

箸休めに Binary Hacks も購入。

MAC OS X Internals: A Systems Approach

MAC OS X Internals: A Systems Approach

  • 作者: Amit Singh
  • 出版社/メーカー: Addison-Wesley (C)
  • 発売日: 2006/06/22
  • メディア: ハードカバー


Binary Hacks ―ハッカー秘伝のテクニック100選

Binary Hacks ―ハッカー秘伝のテクニック100選

  • 作者: 高林 哲, 鵜飼 文敏, 佐藤 祐介, 浜地 慎一郎, 首藤 一幸
  • 出版社/メーカー: オライリー・ジャパン
  • 発売日: 2006/11/14
  • メディア: 単行本(ソフトカバー)


XP on Parallels build 3106 でエディにチャージ [Mac]

メモ:

Parallels build 3106
XP は SP2、Boot Camp でインストール
パソリのソフトは、Boot Camp でインストール
初回認識は Boot Camp 側、ただし読み取りのみ実施

Parallels でもパソリを認識して、ドライバがインストールされた。
その後、サービス登録済みのカードにチャージをおこなったところ、
問題なくチャージされた。
前に、Win2K でチャージに失敗して引き落としだけされてた分も、
リカバリーされた。

Parallels、えらい。

Parallels Desktop for Mac

Parallels Desktop for Mac

  • 出版社/メーカー: プロトン
  • 発売日: 2006/11/11
  • メディア: ソフトウェア


Parallels build 3106 [Mac]

Windows XP SP2 がぼちぼち買えなくなるかなと思い、OEM版を購入。
とりあえず Boot Camp でインストール。特に問題なく動作。

その後、Parallels build 3094 から Boot Camp パーティションを使って VM を
起動。普通に使えたが、なぜかコヒーレンスモードが disable されてしまっていた。

ググってたら build 3106 が出ていたので、上書きインストール。
ひととおり更新して起動したら、コヒーレンスモードも使用可能に。

この、XP のタスクバーがメニューバーの下にくるの、かなり変な見た目だなあ。
やっぱり表示しないほうがいいかな。

Microsoft Windows XP Home Edition Service Pack 2 通常版

Microsoft Windows XP Home Edition Service Pack 2 通常版

  • 出版社/メーカー: マイクロソフト
  • 発売日: 2004/10/22
  • メディア: ソフトウェア


Parallels build 3094 とパソリと Win2k [Mac]

前のエントリに気を良くして会社に置いていた パソリを
持ち帰って、チャージできるか試してみた。
アプリは Edy Viewer。

結果:
・読み取り OK
・チャージ、ギフト 「エディにアクセスできないため、この取引は中断されました」

やっぱりだめ。結構 Edy が使えたと書いてあるブログがあるので、何かすれば
チャージできるのかなと思うのだけど、残念。

いまどき Win2k というのもマイナーなのかもしれず、
これはつまり Win2k だからできないということなのだろうか。


Parallels build 3094 [Mac]

あちこちで、Parallels Desktop for Mac Build 3094 が楽しそうということなので、試してみた。

MacBook 2.0GHz, 1GB Memory.
GuestOS は、昔使ってた Win2K。
アップデート前は最後のステーブル版を利用 > Parallels

・コヒーレンスモードは普通に便利。
・オーディオ CD 普通にリッピングできるようになってる!
・昔使ってたシリコンの Network Walkman にチェックアウトできる (via SS4.0)
・感覚的には、動作中でも以前より OS X 側が軽い?気がする。

会社にパソリを置いてきてしまったので、これは試さねば。
前は読み取りのみでチャージできなかったので。

相当に進化してるなこれ。

Parallels Desktop for Mac

Parallels Desktop for Mac

  • 出版社/メーカー: プロトン
  • 発売日: 2006/11/11
  • メディア: ソフトウェア


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。