ナゾの挙動

少し前から、AppleScriptの原因不明のトラブルに見舞われておりましたが、今日、ようやく「シッポ」を掴む事ができました。あくまで、シッポだけ、ですが。

トラブルとは、ドラッグ&ドロップのアプリケーションが正常に動作しない‥‥というもので、何が正常に動作しないかというと、ドロップした項目のうち数項目が無視される‥‥という内容のものです。

「またまた。単なるコード上のミスでしょ」とか思われるでしょうし、私も何度もコードを読み返しましたが、原因が掴めません。しょうがないので、「ドロップした項目数を確認する」ルーチンを組み込んでみたら、かろうじてナゾの挙動の「シッポ」を掴む事ができました。

シッポをもっとギュギュッと掴むために、ネズミ捕りのスクリプトを作ってみました。以下のコードでドロップレットを作って動作させてみたら、唖然とする結果が得られました。

on open theItems
    display dialog (length of theItems) as text
end open

変数theItemsには、ドロップした項目が代入されています。theItemsはリスト(一般的には配列と呼ばれるもの)なので、lengthで項目数を数える事ができます。

10個の項目(ファイルやフォルダ)をドロップすれば、当然、表示されるダイアログには「10」と出るはずです。しかし、トラブルが発生している環境で動作させると「7」とか「8」「9」などと数が減って表示されます。‥‥つまり、Finder操作でドロップした項目数が、on openで受け取っている項目数と食い違っているわけです。

ショック! 基盤を揺るがす大問題!

プログラムをやっている人なら、その重大さがお解りかと思います。ドロップした項目のうち、ランダムで受け渡されない項目が発生する‥‥なんて、ドロップレット作りの根幹に関わるトラブルです。

悩ましいのは、同じ動作を繰り返すと、やがて正常な数が表示される事です。10個ドロップして「8」と出た数秒後に、同じ動作でドロップすると今度は「10」と出る。ふえええ‥‥。

他でもMountain Lionは使ってるけど、こんな事、初めてだなあ‥‥と思い、自宅のMoutain Lion環境で試したら、何度やっても全く問題の無い正常な動作です。

自宅環境とトラブルが出る環境との違いは、思い当たるところ、マシンがiMac Late2012である事と、ドロップした項目がUSB3.0外付HDDの中にあるファイルだ‥‥という事くらいです。‥‥そんな事で、こげなトラブルが発生するか?

ファイルシステム上の何かがトラブっている? しかし、同じ場所に並んで同じ環境(iMac&USB3.0HDD)が2つありますが、2つとも同じトラブル見舞われているので、個体差ではないように思います。同じ構成のiMac環境で同じトラブルが出る。他のMac環境では発生しない。うーむ。具体的なような、そうでないような。

でもまあ、シッポを捕まえたので、逃がさないように手繰っていけば、トラブルの姿が見えてくるはずです。なんで、もうちょっとネバってみようと思います。

FinderのAppleScript

FinderをAppleScriptで操作する時は、そこそこ、注意というか、挙動を鑑みた扱い方が必要です。

例えば、ファイルのリネーム関連などは、「お手本通り」にやると、映像制作に必要な何千ファイルものリネームでは、全く使い物にならなかったりします。あまりにも動作が遅過ぎるのです。

Finderはファイルオブジェクトなど、いわゆる「item」にアクセスするとそのリターンまで、かなりの時間を要します。これは扱うファイルが多ければ多いほど顕著で、AppleScriptサイドが「タイムアップ」(応答が無いので、時間切れになる)するほどです。

tell app "Finder"
 set fileName to name of file "ファイルパス"
 set name of file "ファイルパス" to "_old_" & fileName
end


‥‥上記のような「お手本」的な段取りを、4,000ファイルも繰りかえしていたら、1時間以上かかる事すらあります。これを聞いて、「マシンの処理速度、遅えェ」とか言う人は、FinderやAppleScriptを知らない人。単にFinderの手続きがボトルネックになっているので、これはマシンがどんなに速くても解消される事はありません。

つまりは、Finderを通すと言う事は、「スーパーのレジ」を通す事に等しいので、4,000個の買い物をするのに、4,000回レジに並んでいたら、そりゃあ、遅くなるわ。‥‥という事ですネ。

Finderに通すのは、ゼロ回、もしくは数回に抑えて、ファイルのリネームに関しては「他で処理」するのが、お得なAppleScriptとFinderの使い方です。

例えば、4,000ファイルを収納したフォルダがあったとして、その中身を1つずつ、Finderで処理するのはNG中のNG。もしFinderを使うとしても、以下のような使い方で、「できるだけFinderにはアクセスしないように」工夫します。

set folderPath to "MacHD:TestFolder:"--フォルダのパス

tell app "Finder" to set nameList to name of files of folder folderPath--Finderへのアクセスはこの行のみ

repeat with currentName in nameList
 set newName to "_old_"&currentName
 do shell script "mv "&(quoted form of posix path of (folderPath&currentName)) & " " & (quoted form of posix path of (folderPath&newName))
end


こうするだけで、3600倍くらいの速さ(おおよそ)になります。

Finderへのアクセスは1度きり、名前のリストを取得する時だけです。後は、リピート文で、地道にシェル上でリネームしてます。やりかたはヒネりがなく、地道な内容ですが、Finderでのリネームよりは数千倍速いです。

ちなみに、文中の「posix path of」は、ファイルオブジェクトやエイリアスでなく単に文字列でも、Posix pathに変換してくれるので、重宝します。「quoted form of」は日本語や空白文字などを扱う時には必須です。

AppleScriptを使って、ファイルの操作を自動化しようと思った時、意外にFinderでの使い勝手が悪くて、もしかしたらAppleScript自体を諦めている人もいるかも知れません。たしかに、Finder経由でリネームなどしようものなら、「こんなの使えねえ」と思われても仕方なのですが、ちゃんと方法はあるのです。‥‥ご参考程度に、紹介しておきます。

QTのデュレーション取得スクリプト

色々弄っているうちに、「せっかくだからルーチンとして完成させてしまえ」と思い、前々回書いた、QuickTimeムービーのデュレーションを得るスクリプトをサブルーチンにしました。

以下。

tell application "QuickTime Player 7"
    my getQTDurationInfo(document 1, 8) 
end tell

--以下からサブルーチン

to getQTDurationInfo(_document, _offset)
   
    set _frameDuration to false
    try
        tell application "QuickTime Player 7"
            set _duration to duration of _document
            set _timeScale to time scale of _document
           
            repeat with t in tracks of _document
                if (type of t) as Unicode text is "vide" as Unicode text then
                    set _frameDuration to duration of frame 1 of t
                    exit repeat
                end if
            end repeat
        end tell
        if _frameDuration is false then return false
    on error msg
        display dialog msg--エラー時、いちいちdialogが出るのがイヤな場合はコメントアウト
        return false
    end try
   
    set _fps to (round (_timeScale / _frameDuration * 1000)) / 1000
    set _rfps to round _fps
    set _sec to _duration / _frameDuration / _rfps
   
    set _frameCount to (_sec * _rfps - _offset) as integer
    set _sec to _sec - (_offset / _rfps)
   
    return {movie_frame_count:_frameCount, movie_seconds:_frameCount div _rfps, movie_frames:_frameCount mod _rfps, movie_time_info:((_frameCount div _rfps) as Unicode text) & "+" & (characters 2 thru -1 of (((_frameCount mod _rfps) + 100) as Unicode text) as Unicode text), movie_time:(round (_sec * 100)) / 100, movie_framerate:_fps}
end getQTDurationInfo

上記ルーチンで、23.976, 24.0, 29.97NDF, 29.97DF, 30.0の5種類のフレームレートを試しましたが、全て期待した結果を返す事を確認しました。

パラメータ「_offset」はボールド(スレート)のフレーム数を入れると、尺から指定フレーム数だけ差し引いて、デュレーションを計算します。

(12+20)で23.976fps、ボールド先頭8フレのQTで試すと、

{movie_frame_count:300, movie_seconds:12, movie_frames:12, movie_time_info:"12+12", movie_time:12.5, movie_framerate:23.976}

‥‥のような結果を返します。ちゃんと8フレのボールドを差し引いた"12+12"になっていますネ。

さらに、(12+25)で29.97fpsノンドロ、ボールド先頭10フレのQTで試すと、

{movie_frame_count:375, movie_seconds:12, movie_frames:15, movie_time_info:"12+15", movie_time:12.5, movie_framerate:29.97}

‥‥のような結果を返します。これも合ってますネ。

60秒の29.97fpsノンドロは、

{movie_frame_count:1800, movie_seconds:60, movie_frames:0, movie_time_info:"60+00", movie_time:60.0, movie_framerate:29.97}

となり、期待した結果になります。QuickTime Playerの情報ウィンドウだと「0:00:01:00.06」とか表示されて混乱しますが、上記ルーチンはちゃんと60秒ジャストの尺を返します。

ちなみに、尺が(59+28)のドロップフレームのQTをルーチンで処理しても、ちゃんと59+28を返します。

日々、こうしたルーチンをストックし、スクリプトコンポーネントに書き込んでおくと、とても楽に、面倒な処理のスクリプトがスッと作れるようになります。

スクリプトコンポーネントは単にサブルーチンを記載したスクリプト書類です。load scriptでスクリプト書類を読み込み変数に入れて、中身のサブルーチンを呼び出すだけです。

set myComponent to load script [任意のファイルオブジェクト]
set theResult to myComponent's getQTDurationInfo(document 1, 8)

最近は、本業を絵作り中心に戻そうと思っていますが、やはり、スクリプトで環境を武装しておかないと、不毛な時間的ロスが発生し、巡り巡って、絵作りの時間が奪われる事になります。あまり夢中になりすぎないように、自制しながら、スクリプトやプログラムと付き合い続けていこうと思っています。

ちなみに‥‥AppleScriptをいじった事がなく、他の言語でプログラムをやる人は、

 if _frameDuration is false then return false

‥‥なんて記述を見ると、不思議に思う事でしょう。AppleScriptは、値が存在すればtrueになるわけでは無いのれす。undefinedとかをfalse扱いにしたりも出来ません。いわゆるundefined的なものは、AppleScriptにおいては、スクリプト文の構造上の欠陥と見なされます。「存在しないならfalseだよ」とは行かず、「存在しないのはスクリプト文のエラーだ」となります。‥‥めんどくさいっすネ。結構、「型にウルサイ」やつなのです。


追記:ルーチンにちょっとミスがありました。ビデオトラックを検索する部分です。

誤記「set _frameDuration to duration of frame 1 of track 1 of _document」
訂正「set _frameDuration to duration of frame 1 of t」

誤記のほうは、何のためにループ文でトラックを検査しているのか、意味の無い書き方になっちゃってますネ。見直してたら気付きました。
‥‥まあ、いわゆる「撮影上がり」はビデオトラック1つだけの事が多いので、エラーもなく完了する事も多いのですが‥‥。


Numbersのスクリプト制御

NumbersはそこそこにAppleScriptで自動制御が可能なので、使う気になれば、色々な場面で役立ちます。Numbersの関数と、AppleScriptの各種コマンド、AppleScript上で作った自作の関数などを組み合わせると、日々の作業や日常生活で特に不満を感じる事なく、便利に使えます。

表計算ソフトウェアとしてのExcelの優位性は疑う余地の無いものですが、前に書いたエディットシート程度の内容や、バーコードなどのラベル作成、当座の集計表くらいならば、Numbersで充分こなせますし、レイアウトの自由度が高く、フォントが(お金をかけずに)奇麗なのは、Numbersならでは特徴です。おそらく、Numbersの開発意図も、Excelと「ビジネス分野で競合するつもりはない」のでしょう、Excelのビジネス寄りの盲点を突いた設計思想になっていますネ。

Numbersをスクリプト制御する際のコツは、「ある程度、Numbers内で作っておく」事です。要は、Numbersの関数と協同してスクリプトを実行するわけです。例えば、行番号はNumbersで「row()-1」(1行目が見出しの場合)で自動表記するようにしておいて、コンテンツはAppleScriptで流し込む‥‥みたいな。そうしておくと、後で「この行は不要だ」と削除した時に、いちいち行番号を書き変えなくてすみます。行番号までAppleScriptで流し込むと、任意の行を削除した時に面倒な修正が必要になります。

レイアウトもスタイル(フォントや文字サイズ、字体や装飾)も、Numbersであらかじめ作っておきます。スタイルや行揃えまでAppleScriptで制御しようとすると、無駄にスクリプト作成に時間がかかります。行を追加した時などは、Numbersはスタイルを前の行の状態を継承しますので、スタイルもひな形で事前に作っておけば、AppleScriptでの手間を省けます。

ただ、スタイルは「セルに1種類」と考えて、ひな形を作る必要があります。Numbers上では、セル内で内容文を改行し、行ごと(文字ごとでも)にスタイルを使い分ける事は可能ですが、AppleScriptで単純に値を流し込むと、行頭のスタイルで全て統一されます。スクリプトに対応するひな形のデザインをおこなう事で、最小限の手間でNumbersを思いのままに自動制御できるようになります。

私は、NumbersとAppleScriptを用いて、倉庫収容物のデータベースからバーコード付きラベルを印刷したり、QTファイルのレンダリング速度のアベレージを一覧表にしたり、「手でやると面倒な」作業を自動化しています。

アニメ制作においても、制作さんからCSVファイルを提供してもらい、自分の作業内容と照合して、結果をNumbersの表に出力するような事もできます。

人間の時間は限られたもの、24時間から睡眠時間を除いた時間しか与えられていなので、コンピュータでもできるような仕事は、どんどん自動化して、人間でしか出来ない事柄に時間を費やすべき‥‥と考えているのです。

このあたりの記事は、「片手間スクリプト」的なコラムにまとめて、もっと詳しくコードとかも書いて、リファインすべきかな‥‥とは思っております。Macを使ってるんなら、AppleScriptやiWork、XcodeやObjective-Cを使わないのは、もったいないもんネ。

QuickTime Player 7 と Numbers でエディットシート

今更ながらの話題ですが、QuickTime Players 7とNumbers、そしてAppleScriptがあれば、QuickTimeムービークリップの基本事項を記した一覧表、いわゆるエディットシートを自動で作る事ができます。最近、必要に迫られて昔のスクリプトをブラッシュアップした事もあり、忘れないうちに書き留めておきます。

NumbersはMacOSXの定番表計算ソフトウェアですが、システム標準装備の奇麗なヒラギノフォントなどを用いて作表できるので、見栄えの良いドキュメントを作成できます。AppleScriptを用いて、セル内の値の書き換え、行や列の追加などが自動処理できるので、ひな形ファイルでスタイルを作っておけば、最小限の手間で、スタイル付きの読みやすくて奇麗な表を作る事が可能です。

一方、QuickTime Player 7 は、AppleScriptを用いて様々な操作を自動で処理する事ができます。フルコマ〜数コマ毎の連番書き出し、映像の変換、字幕やインデックスの挿入、映像のカット&ペースト、サイズの変更など、自動処理できる内容は盛りだくさんです。もちろん、ムービーファイルの情報取得も可能です。

Numbersはひな形ファイルをまず作ります。タイトルのテーブルを作り、一覧表のテーブルも作ります。表に名前をつけておけば、「table "お好みの名前" of sheet 1 of front document」で任意の表へとアクセスできます。セルの指定はとても単純で、1行目左からカウントしていくだけです。例えば、8列2行の最終セル〜つまり一番右下のセルは「cell 16」となります。

行を下に追加したい場合は、add row below cell [セル番号] で簡単に追加できます。例えば、先ほどの8列2行の表に行を1行追加したい場合は、add row below cell 9、または、add row below cell 16などで下に追加されます。命令自体はとても簡単。

セルの内容を書き換えたい場合は、set value of cell [セル番号] to "ほにゃらら"で書き換えられます。空欄にしたい場合はvalueを""にすれば良いですネ。

ひな形ファイルはFinder上で複製して日付でリネームするのが楽です。日付けは、do shell script "date +%y%m%d"で、容易に省略した年月日が取得できます。"130510"のような書式は、下手にdateクラスを使うより、shellのdateコマンドを使ったほうが断然楽ですネ。

表の操作が可能になれば、あとはQuickTime Player 7で取得した情報を各セルに流し込むだけです。

QuickTimeはDuration(いわゆる尺ですネ)をタイムスケールの単位で表します。タイムスケールが480だった場合は、10秒は4800という値になります。タイムスケールは大きな数値の事もあれば、24という素直な数字の事もあるので、実際のファイルから取得して計算するのが安全です。duration / time scale で秒数は取得できますが、24コマ表記にする場合は、ちょっと頭をヒネって、変換式を作ります。

ビデオそのものの情報については、「ビデオトラック」の情報へアクセスします。コーデックを知りたければ、「data format of track 1 of document 1」です。
*これはPlayer上で一番手前のドキュメントで、かつトラックがビデオトラック1つだけの時に有効なスクリプト文です。トラックが複数ある場合は、track 1 でビデオトラックを指定できるとは限りませんので、trackの種別を調べてから情報を得る必要があります。でもまあ大概、After Effectsでレンダリングした「撮影上がり」QT は、トラックは1つだけです。

ビデオトラックよりもさらに細密なframeにアクセスすると、フレームレートなどが計算できます。ただし、23.976fpsはちょっと厄介です。「例の誤差」はご多分に漏れず、QTでも発生しますので、めんどくさがらずにサックリ対応します。

QuickTimeの場合、1分につき0.06の誤差が発生し、情報ウィンドウにも本来「60秒」であるはずが、堂々と「60.06秒」として表示されます。しかし、これではNG。しかと本来の尺になるよう工夫します。例えば、以下みたいな。

tell application "QuickTime Player 7"
    set dur to duration of document 1
    set ts to time scale of document 1
    set f to duration of frame 1 of track 1 of document 1
   
    set fps to (round (ts / f * 1000)) / 1000
    set sec to dur / f / (round fps)
end tell

duration of frame 1 of‥‥の下りは、After Effectsで言う「frameDuration」ですネ。fpsはそのまま計算すると「23.976023976024」なんて数値が返るので、野暮ったいやり方ですが、下3桁に丸めています。

上記スクリプトで処理すると、60秒のムービーはちゃんと60の値を返します。60.06(60+1)とかにはなりません。

fpsは23.976ですが、実際は24(四捨五入で)で計算をし、60秒ジャストの尺が返るようにします。せめて未来の120fpsは120.0であって欲しいですが、59.94なんてレートが存在するから、やっぱりダメだろうなあ。

そんなこんなで得た情報を、Numbersの表に流し込むと、整然とした書式の一覧表が出来上がります。

ブログなので、細部の説明はかなり端折っていますが、いつか本家サイトで詳しく紹介できたらと思います。



MacのAppleScript

私がAfter Effectsを駆動するアプリを作る際の「常套手段」は、AppleScriptと組み合わせるやり方です。GUIをAppleScriptに担当させて、After Effects上のスクリプトは処理に徹します。

Xcodeを用いて本格的なGUIを装備する方法もあるのですが、何だかんだと時間がかかるので、AppleScriptオンリーでGUIを調達します。AppleScriptはalert()的なものはもちろん、リスト表示、ファイル選択、フォルダ選択、新規ファイル指定、カラーピック、テキスト入力など、とりあえずひと揃えがあるので、開発上は特に困らないのです。一般的な開発環境と違って、自作のウィンドウ(インターフェイスビルダーで作るような)は作れませんが、対話式のアプリならストレスを感じずスイスイ作れます。

例えば、AppleScriptは、Finderで扱うファイルやフォルダをas unicode textで簡単にファイルパスに変換できますから、FinderでChooseしてファイルパス文字列に変換し、Adobeのスクリプトに組み込めば良いのです。ちなみに、HFSのパス文字列がイヤな場合は、POSIX Path of...でスラ区切りのパスを取得できます。quoted form of...を使うと意図せぬコマンドと文字列の衝突を防げます。

MacOSXでAfter EffectsをAppleScript経由で制御し、さらにWindowsに処理を渡す場合は、ちょっと工夫が必要ですが、出来ない事はありません。Windowsで「After Effectsサーバ」的なスクリプトを走らせておいて、MacOSXから投げこむ‥‥のような事も可能です。独自のキューファイル(ジョブファイル‥‥呼び方はどうとでも)を規定して、Mac/Win共通規格の書類とする事で、MacからでもWinからでもAfter Effects処理サーバに処理を投げ込む事ができるのです。After Effects処理サーバは、特別な事をしているわけでなく、単にスケジュールタスクを定間隔で走らせて指定フォルダ内をCrawlして、新規キューファイルを見つけたら指示通りに処理をするだけ‥‥です。

ぶっちゃけ、今の私は、ソフトウェアの開発にそんなに時間をかけられなくなっているので、AppleScriptくらいのレベルがちょうど良いのです。まあ、他の言語に馴れちゃうと、AppleScriptは冗長なコードになりやすく、タイプがめんどくさくて、たまに心が折れる事もあるんですがネ‥‥。theArray[0]で済むところを、item 1 of theArrayですからネ‥‥。

また、Windows作業環境グループでQuickTimeのProRes出力する場合などは、規模にもよりますが、Mac miniとCompressor、AppleScriptを使えば変換サーバを仕立てられます。AppleScriptのon idleを使って自動巡回変換ソフトを作っちゃえば良いのです。仮にAfter Effectsのライセンスがあれば、さらに高度な変換(スレートを自動生成するとか)もできます。AppleScriptベースなので、開発時間が最小で済むのです。

Macを使ってるんなら、今さら何ですが、AppleScriptを使わないのは、もったいないですヨ。

‥‥ちなみに、無理すれば、AppleScriptから直にビットマップデータを書き出す事が可能です。SGIなどの簡単な書式であれば、ですが。スクリプト文中にヘッダ部とビットマップを文字列で記述し、open for accessで書き出し、ファイル名に拡張子をシレッと付ければ、ちゃんと画像ファイルになります。

スクリプトを書くとソフトを覚える

何か逆説的な言い方ですが、私がコンピュータに詳しくなっていったのは、スクリプトを書いたからかも知れません。「スクリプトって、コンピュータに詳しい人が書けるものなんじゃないの?」とか思われるかも知れません。‥‥が、みんなが超能力者や諜報機関の人間じゃないので、他人が作った仕様を何もなしに理解などできません。誰もが、開発者サイドの用意した文献なりヘルプなりを読みながら、スクリプトやプログラムを書きます。

つまり、スクリプトを書く過程で、否が応でも、ソフトウェアの仕組みを覚えてしまうのです。スクリプトの書き始めは基礎的な知識しか無くても、書き進むうちに、ソフトウェアやコンピュータの事を覚え、さらには、ソフトウェアの内部構造を知ると、スクリプトの書き方が改良され、「上昇気流」にのるようにどんどん総合スキルが上がっていきます。

スクリプトがわからない‥‥と言っているうちは、実は、コンピュータもわからず仕舞い‥‥なのかも知れません。極論めいた響きではありますが。 「スタートアップガイド」を丸暗記しても、コンピュータを使えるようになったとは言い難いですもんネ。
*‥‥ただ、昔からコンピュータをいじっている人は、時代的に、プログラムやスクリプト、マクロといったものと無縁ではいられなかったでしょうから、コンピュータとはどんなものかは、嫌でも知っている事とは思います。

例えば、Finderのウィンドウ。ただ漠然と接しているだけだと、「ただのウィンドウ」としか言いようのないものです。しかし、ウィンドウ絡みのスクリプトを書くと、ウィンドウに関する色々な事柄に触れる事になります。

target, position, bounds, current view, statusbar visible, sidebar width

これらは、ウィンドウの見た目を制御するプロパティです。これらの値を変えると、ウィンドウも呼応して変化します。ウィンドウの姿がどのように制御されているかを知る事になります。

class:icon view options, arrangement:arranged by name, icon size:64, shows item info:false, shows icon preview:true, text size:12, label position:bottom, background picture:missing value, color:{65535, 65535, 65535}

これは、アイコン表示時のウィンドウのプロパティです。icon size を64から128にすると、アイコンの表示サイズが倍になります。

こうして、スクリプトを書くうちに、Finderや、PhotoshopやAfter Effectsなどの内部構造を、「知ってしまう」わけです。

After Effectsでは色々な要素を扱いますが、各要素はどのような関係性をもっているのか? フッテージとは? レイヤーとは? ‥‥AVレイヤー、ソリッドレイヤー、テキストレイヤー‥‥みな同じレイヤーですが、After Effectsの内部的には、扱いは大きく異なります。

実は私は、スクリプトを書くまで、そんなにAfter Effectsの内部を知っていたわけでなく、単に経験則で「こんな構造なんだろうな」と考えていただけです。しかし、スクリプトを書く事で、After Effectsの「融通の良さ・悪さ」に対して「合点が行った」わけです。

他人が書いたエクスプレッションをコピペしてるだけじゃ、After Effectsは深く理解できんです。自分で書いてみないと。 ‥‥同じように、コンピュータのスペックだけ詳しくても、単に「コンピュータが好きな人」なだけで、駆使する能力は身につきません。

スクリプトとコンピュータの知識って、右足と左足のようなもんで、片方ずつ繰り出して進んでいくもんですネ。

作業環境マネージャ

小刻みな仕事を多くこなしていると、フォルダやファイルの管理というか、作業環境がルーズになってきます。‥‥とは言え、そうじゃない人もいるでしょうから、私は特に‥‥と言っておきましょう。

アニメの撮影だけやってた頃は、あまり乱れなかったんですが、多種多様な作業をおこなうようになって、自分でも嫌になるほどフォルダ構成がルーズになってしまいました。「このファイルはどんな名前のフォルダに入れて整理しておけばいいんだ?」とか、「そもそもこのファイルのカテゴリは何だ?」とか、迷ううちにテキトーな名前を付けてテキトーな名前のフォルダに入れて、そして後で探しまわる事になる‥‥と。

「検索すればいいじゃん」とか思うのですが、テキトーな名前ゆえ、検索文字列すら思い起こせないので、検索が解決案とはならないのです。例えば「.psd」で検索してたら、色んなファイルが引っかかりますしネ。

ここ数ヶ月、こまめな仕事をしていて、とりあえずプロジェクトごとのフォルダには収まっているものの、中身は混沌としてしまって、昨夜、「まだ記憶が残っているうちに」整理しました。

‥‥で、整理をしてて、「これって、コンピュータでヘルプ可能だよな」と、ふと感じました。

まあ、もともと私がコンピュータに期待して、プログラムを習得したのは、こうした自分自身の欠点〜整理が苦手〜を、「作業に足枷にならない程度に改善したい」という目的があったからでした。

その昔、OSのウィンドウが散らかるのがイヤで、「どのフォルダのウィンドウを、どのような表示形式で、どの位置とサイズで開くか」を記憶するアプリケーションを作った事がありました。自分で使い易いように各ウィンドウを整頓して並べて、その状態をテキストファイルに記録し、適宜呼び出す‥‥というものです。ウィンドウの整頓は、Finderのスクリプトで誰もが一度はやる内容かも知れませんが、その自作アプリは各ウィンドウの状態を独自のテキスト書式で読み書きするのがミソでした。「ウィンドウマネージャー」とでも言いましょうか。

それに似た事を、フォルダのツリー構造でやれば良いんですネ。テキストファイルの書式やごく簡単なマクロ言語を決めちゃえば、そんなに難しい事ではないです。MacOSXは素でShellが使えるので、正規表現も流用可能ですし。

作業環境マネージメントのソフトウェアを作り、そのひな形を何種類か用意しておいて、通常はそのひな形を使って整理し、ちょっと変わった仕様の作品には、ひな形を適宜書き換えて用いる‥‥という具合です。ひな形はテキストファイルで、汎用テキストエディタで編集可能とします。わざわざバイナリデータにする必要ないですネ。

アプリ作成は、やっぱりAppleScriptかなぁ。手軽なJavaScriptよりも、さらに手軽ですからネ。Shellも巻き込んじゃえば、ひと通りの事はできちゃいますしネ。


timeToFrames()の困惑


After Effectsの尺など、時間やフレームをテキストレイヤーで表記する事はよくありますが、使い方によっては、意図しない結果になる事があります。

使う人はよく使う「timeToFrames()」は結構なくせ者で、ちゃんと3つの引数全てを入力しないと、何かのきっかけによって、返値が1、ズレる事があります。

例えば、12+12を表示しようとして、12+13になる事があります。これは、引数isDurationをtrueにすれば防げる事ですが、After Effects上での挙動が曖昧なので、「この引数は特に指定しなくても大丈夫だ」と処理しがちです。

同じスクリプト文でも、隣の人の環境ではちゃんと意図通りの結果、自分の環境だと1ズレる。じゃあ、自分の環境が何か違うのかと思っていると、隣の人の環境でも、やがて1ズレる。‥‥実は昨日体験した事例なのですが、挙動が曖昧で「再現性をつかめていない」ので根本の解決には至っておりません。対処法はありますが。

以下の例文。

timeToFrames(8/24,24,false)+" : "+timeToFrames(8/24,24,true);

人によっては「8 : 8」、違う人では「9 : 8」と表示されます。厄介なのは、「8 : 8」と表示されていた人の環境でも、何かのきっかけで「9 : 8」になる事です。なぜ最初から「9 : 8」と表示されないのでしょうネ?

要は「0,1,2,3,4」か「1,2,3,4」かの事だとは思うのですが、引数「isDuration」の挙動がおかしいんだよなあ‥‥。

作業用のテンプレートとして配布されるAfter Effectsプロジェクトで、上記のような障害が発生し、ボールドの尺表記が1フレーム分ズレる事があります。テンプレートを作った本人はその障害に気付いてないですし、受け取った人によっても挙動が違うので、「結果オーライ」とそうでない場合がマチマチなのです。

エラーの再現性を確立できなくても、対処法は簡単です。isDurationをtrueにして扱えば良いのです。isDurationをfalseにするのは、返値が曖昧なので、NGですかネ。‥‥まあ、ネジが外れた部分にガムテープで処置するような対処法ですが。

サンプルの尺表示のエクスプレッションです。

var offset=8;
var fps=1/thisComp.frameDuration;
var dur=timeToFrames(thisComp.duration,fps,true)-offset;
"("+String(Math.floor(dur/fps)) + "+" + String(100+Math.round(dur%fps)).slice(1)+")";

昨日はレンダリングしたQTをチェックしてビックリ。ボールド表記に、12+01とか、20+13とか、妙なコマ数が表記されてて、実際に尺をミスったかと思いました。困ったのは、環境によって障害が出ない事も多かった事です。草木も眠る深夜にAfter Effectsの珍妙な挙動に悩まされるとは‥‥。一律で全部1コマ多かったら、明快なんですけどネ。

尺、桁揃え

After Effectsで尺〜デュレーションを自動表記する際、私が昔から好んで使うのは、以下のようなエクスプレッションです。

var offset=8;
//ボールドなどの尺を引く場合は、適宜
var t=thisComp.duration-framesToTime(offset);
String(100+Math.floor(t)).slice(1)+ "+" + String(100+Math.round(t%1/thisComp.frameDuration)).slice(1);
//2桁で表記を統一する場合です


*ブログのデザイン上、改行されている箇所がありますが、行末はあくまで「 ; 」です。

私は、昔からの習慣で、小数点の端数で痛い目にあっているので、thisComp.durationをframeDurationで割る‥‥というような事はせずに、1秒で割った余りだけをframeDurationで割るようにしています。誤差を極力出さないルーチンにしておけば、どんな環境でも表記上の誤差は発生しない‥‥という事です。
*誤差の累積を、故意に発生させる場合は別ですヨ。

また、floorとroundは上手く使いわけてこそ‥‥です。floorばかり使っていると、思わぬ結果が出る事がありますネ。


また、数字の表記を2桁で揃えたい、4桁で揃えたい‥‥という時には、

var ketaNumber=Math.pow(10,桁数);

で、必要な桁数の位が繰り上がった数を用意しておき、

String(ketaNumber+任意の数).slice(1));

‥‥にすれば簡単にゼロで埋めた文字列を生成できます。つまり、0025が欲しい場合は、

String(10000+25).slice(1);

‥‥で済みます。わざわざIF文を使わずとも、1行でおさまります。

if num<10 {"0"+num} みたいなのは、2桁だとさほど苦ではないですが、例えば4桁の場合は、IF分岐がめんどくさい事になりますネ。for構文でゼロを追加するのも、なんだか大袈裟過ぎます。

私は今まで散々、桁数を揃えた番号と付き合ってきたのですが、何だかんだ言って、上記のプリミティブなやり方(10のべき算を一時的に足す)が一番シンプルで使い易く感じています。項目の数に応じて、動的に桁数を変える事だって、簡単にできますしネ。


*「var」も「;」も、エクスプレッションでは無くても見逃してくれるんですが、何かね、不安で。 ‥‥妙な省略癖がつくのもイヤだし。


calendar

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< July 2017 >>

selected entries

categories

archives

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM