ESTKのスクリプトをAppleScriptに埋め込む

前々回のブログで、せっかく、それなりに高速処理のリネームスクリプトができたので、ESTKエディタからの実行だけでなく、AppleScriptでGUIをくっつけて、気軽にドラッグ&ドロップでも処理できるようにしました。

 

アプレットでもドロップレットでも動作するように、「on open」と「on run」を併用しています。

 

macOSのアプリケーションフォルダにある「スクリプトエディタ」を起動して、おもむろにAppleScriptとESTKの合体コードを作ります。

 

 

property defaultItem : false

 

on open theItems

    my main(theItems)

end open

 

on run

    tell application "Finder" to if defaultItem is false or not (defaultItem exists) then set defaultItem to home as alias

    set res to choose folder with prompt "処理するフォルダを選択してください." default location defaultItem with multiple selections allowed

    tell application "Finder" to set defaultItem to (parent of (item 1 of res)) as alias

    my main(res)

end run

 

to main(_folders)

    set errorText to {"フォルダ指定が不正です", "フォルダが空です"}

    set errorLog to ""

    repeat with _folder in _folders

        set res to my runAdobeScript(_folder as Unicode text)

        activate

        if res as integer > 0 then

            tell application "Finder" to set folderName to name of _folder

            set errorLog to errorLog & folderName & tab & res & tab & (item (res as integer) of errorText) & return

        end if

    end repeat

    activate

    if errorLog is "" then

        display dialog "処理が正常に終了しました" with icon 1

    else

        display dialog "エラーが発生しました

下記のエラーログを確認してください" with icon caution default answer errorLog

    end if

end main

 

to runAdobeScript(folder_path)

    tell application "Adobe After Effects CC 2018"

        DoScript "app.exitCode=0;

_1801_RENAME_RE=new RegExp('[_-]*[0-9]+¥¥.[A-Za-z0-9]{2,}');

app.exitCode=main();

 

function main(){

    var theFolder=new Folder('" & folder_path & "');

    if(!theFolder){return 1;}

    var theFiles=theFolder.getFiles();

    if(theFiles.length<1){return 2;}

    for(var i=0;i<theFiles.length;i++){

        var reMatch=theFiles[i].name.match(_1801_RENAME_RE);

        if(reMatch&&theFiles[i].name.match(/^[A-Za-z0-9]/)){

            theFiles[i].rename(theFolder.name+String(reMatch));

        }

    }

    return 0;

}"

    end tell

end runAdobeScript

*前回のバックスラッシュの文字化けを防止するために、ARIELフォントにしてみました。‥‥けど、やっぱり、¥になっちゃった。

*このスクリプトのコードはサンプルです。実際に使用する際は、自己責任でお願いします。

*あ‥‥そういえば、パスに日本語(2バイト文字)が混ざっている場合の処理は盛り込まれていないです。忘れてました。なので、その辺はよしなに。

 

書いたら、アプリケーション形式で保存すれば、ドラッグ&ドロップで動作する、小さなアプリケーションみたいなのが出来上がります。

 

 

 

実際に動作している映像はこちら。毎度のGIFアニメですまんす。

 

 

 

フォルダの名前で、内包するファイルの名前をリネームしている様子が、小さくて見にくいですが、なんとか伝わると思います。

 

合計500ファイル以上あるリネームを瞬時に処理します。フォルダを複数処理すると、ウィンドウの更新に時間がかかるようですが、それでも数秒の処理です。

 

 

‥‥で。

 

ここまで作ってなんですが、「この方法はないな‥‥」と思いました。

 

ESTKのエディタからであれば、実行ボタンで処理を実行できます。しかし、ESTKエディタではなく、AppleScriptからですと、なんらかの「ホストアプリケーション」〜つまり、実行する環境が必要になります。

 

なので、上述のAppleScriptのコード文では「After Effects」を呼び出していますが‥‥

 

そりゃないでしょ。

 

After Effectsの機能は全く使わず、リネームの実行環境としてのみ使うためにAfter Effectsを起動するなんて、スーパーへ買い物に行くのにヘリコプターを飛ばすようなもんです。段取りが大袈裟すぎます。

 

 

まあ、なので、結論としては、

 

ESTKのスクリプトはjsxで保存して、After EffectsやPhotoshopを起動している時に、メニューから呼び出す

 

‥‥のが、使い方の基本ですかね。やっぱり。

 

リネームのため「だけ」に、PhotoshopやAfter Effectsを起動するのは‥‥さすがに、ないわ。

 

 

 

まあでも、せっかく作ったので、なんかあった時に使ってみるかも、です。

 

どうせ、After EffectsやPhotoshopは起動しっぱなしだし。

 

 

 


プログラムとファイル名

数行のスクリプトであっても、コンピュータプログラムを実際に作って、ファイルやフォルダのリネームを処理するようになると、明確に「それ以前と以後」で当人に変化があらわれます。それは‥‥

 

人間もプログラムも、両方で扱いやすい、ファイル&フォルダの命名規則

 

‥‥を考えるようになるのです。

 

なぜかというと、人間だけでなく、プログラム的に見ても、扱いやすいファイル名のほうが、運用が円滑で効率的になるからです。

 

例えば、

 

a0001.tga

 

‥‥というファイル名があったとします。そしてこの名前の「a」を「b」へと自動処理で変えたいとします。

 

その時、どのようにプログラム上で名前を変更するでしょうか。

 

「a」は1文字だから、2文字目から最後までを抜き出して、先頭に「b」を足せば良い。つまり‥‥

 

"b"+"a0001.tga".substr(1);

 

‥‥とスクリプト文を書けば、結果は‥‥

 

「b0001.tga」

 

‥‥で、めでたし、めでたし。

 

‥‥と考えるのは、よくあることでしょう。

 

しかし、それはハッキリ申しまして「浅知恵」と言わずばなりません。

 

もし、「A上セル」の場合にファイル名が‥‥

 

a-ue0001.tga

 

‥‥だった場合は‥‥

 

"b"+"a-un0001.tga".substr(1);

 

‥‥とスクリプト文が以前と同じままだと、結果は‥‥

 

「b-un0001.tga」

 

‥‥で、全然ダメ。

 

なので、スクリプト文を部分的に書き直して、

 

"b"+"a-un0001.tga".substr(4);

 

‥‥と書けば、「a-ue0001.tga」を「b0001.tga」に変更できる。‥‥めでたし、めでたし‥‥?

 

‥‥のようになりましょう。本当に「めでたし」でしょうか?

 

問題は明らかです。ファイル名の状況によって、毎度毎度、スクリプトのコード文を修正しなければ使えないのです。

 

「大した手間じゃないし」と考える人もいましょうが、スクリプト・プログラムを導入するのは「自動処理で効率化」する目的なのですから、「毎回毎回スクリプトを手動で書き換えていたら、それはもはや自動処理と言えない」わけです。

 

「じゃあ、後ろから数えて、連番と拡張子を抜き出せば良い」と思いますよネ。つまり‥‥

 

"b"+"a-un0001.tga".slice(-8);

 

‥‥と書けば、後ろから8文字以降を抜き出せるので、"b"と合体して‥‥

 

b0001.tga

 

‥‥となり、思った通りの結果を得られる。

 

 

「ならば、ソレでいいじゃん」と思いがちです。でも、よく考えて見れば、連番は必ず4ケタと言い切れるでしょうか? セル素材の場合は2ケタだったり、コンポジット後の連番は5ケタだってあり得ます。連番のケタ数が変われば、その時点でスクリプトは台無しです。

 

"b"+"a-un_01.tga".slice(-8);

結果:「bn_01.tga」〜余計な文字が入り込み、「b_01.tga」に変換できない

 

毎回異なる状況に合わせて、「-8」を「-7」「-9」などその都度スクリプトを書き換えなければ、正常に機能しません。つまり、「何度も使いまわせる自動処理」とはなりません。

 

前から数えようが、後ろから数えようが、文字数に合わせて「1」とか「-8」などの決まった数字を使っている限り、臨機応変に対応する自動処理にはならない‥‥ということです。

 

 

‥‥と書いてて何ですが、正規表現を使えば、かなりの柔軟度でファイル名を修正できます。以下の正規表現でアニメ制作の実質的な連番関連の文字列を抜き出せるからです。

 

new RegExp("[_-]*[0-9]+¥¥.[A-Za-z0-9]{2,}");

 

*「¥」は、実際はバックスラッシュです。このブログのフォントが日本語フォントの影響だか、「¥」に見えてしまうようです。ブログのコード直書き機能でフォントを英語フォントにすれば良いのかな‥‥。

 

上記正規表現ならば、「アンダーバーかハイフンの区切り文字(=無くても可)のあとに、連番と拡張子をもつ、ファイル名」を全て共通のコード内容で処理できます。

 

"a0001.tga"を"b0001.tga"に変えたい

"b"+"a0001.tga".match(/[_-]*[0-9]+¥.[A-Za-z0-9]{2,}/);

結果:"b0001.tga"

 

 

"a-un_001.tga"を"b_001.tga"に変えたい

"b"+"a-un_001.tga".match(/[_-]*[0-9]+¥.[A-Za-z0-9]{2,}/);

結果:"b_001.tga"

 

"a-01.tga"を"b-01.tga"に変えたい

"b"+"a-01.tga".match(/[_-]*[0-9]+¥.[A-Za-z0-9]{2,}/);

結果:"b-01.tga"

 

*注)match()を実行すると、実際は「配列」が返ります。例では「暗黙の型変換」で処理していますが、After Effectsなどで実行する際はString()で囲んで明示的に型変換=キャストしないと、エラー(ゼロによる除算)で構文チェックにひっかかる可能性もあります。

 

ファイル名がセル名と連番が直結していようが、アンダーバー(アンダースコア)やハイフンで区切られていようが、何桁だろうが、全て連番と拡張子以外を名前変更します。実際は「a0001.tga」や「b」は動的に自動入力されますから(ファイルの繰り返し処理や親フォルダ名から取得するなどして)、スクリプトを変更せずに処理できます。

 

 

でも、こうした、まるで呪文のような複雑な正規表現を、アニメ制作上で頻繁に用いるフォルダ名・ファイル名に適用しなければ、名前の変更1つすら自動化できない‥‥なんて、いかにも「運用上の命名規則の甘さ」のリカバーそのものです。

 

運用開始時点で、プログラムにも人間にも判りやすい、汎用性の高い命名規則を制定すれば良いのです。

 

最初っから、先を見越して、決めておけば良いのです。その場その場で場当たり的に対応するのではなく。

 

プログラムが、現場のルーズな運用規則をリカバーするばかりに徹するのではなく、現場のファイル運用もプログラムによる運用効率化に歩み寄るべきです。自動処理、スクリプト処理云々以前に、作業者ごとでまるでバラバラな命名規則で運用し、その都度対応して無用な手間を増やし続けて、口にするのは「手間が多くて大変だ」なんて、窮状の自作自演と言われても何も言い返せません。

 

 

ファイル名・フォルダ名は「その場の雰囲気でつける」ものではありません。たとえ、簡素な命名規則でも、実は根っこに色々な工夫が張り巡らされているものです。

 

そして、その命名規則は、人間だけでなく、プログラム・スクリプトにとっても活用性の豊富な規則であれば、効率化はどんどん加速します。制作進捗状況を記録するデータベースにおいても、円滑に処理できる基盤となるでしょう。

 

例えば、アンダーバーは「カット固有や素材ファイルの要素を区切る文字」と決め、ハイフンは「注釈や派生を付記する文字」と決めれば、人間でもコンピュータでも、ファイル名から解釈は容易です。

 

anim_05_234_mo_t1.mov

意味:作品「anim」の「05」話のカット「234」の出力種別「mo」の「テイク1」のQuickTimeファイル

 

a-ue_0004.psd

意味:「a-ue」素材の「4」つめのPhotoshopファイル

 

b_01.tga

意味:「b」素材の「1」つめのTargaファイル

 

 

こうした、シンプルだけども汎用性や拡張性の高い命名規則を規定しておけば、ファイル名を変更するスクリプトを何度もそのままで流用可能になりますし、データベースなどへの情報記録もフォルダやファイル名から一貫できます。

 

ファイル名やフォルダ名は、制作運用上のメタデータと心得るべきです。

 

そのためには何よりも、ファイル命名規則を規定する人間が、人間主観だけでなく、プログラムの観点からも鑑みることが、必要になります。

 

例えば、After Effectsでテキストレイヤーのエクスプレッションなどで形成する「カットボールド」は、作品・話数・カットの各文字列がアンダーバーでセパレートできれば、何度でも無修正で使いまわせる雛形コンポが作れます。substrで「何文字目」なんて毎回変更せずとも、配列のインデックスでどんな作品でも要素を確定できます。

 

「thisComp.name.split("_")[0];」は作品キーワード(作品略号)

「thisComp.name.split("_")[1];」は話数またはシーン

「thisComp.name.split("_")[2];」はカット番号

 

同じ「数字指定」をしても、セパレートの文字=デリミタをあらかじめ規定しておき、そのデリミタで文字列を「split()」で分解して処理すれば、作品ごとに「数字指定を変更せずとも通用する」のです。

 

 

プログラムを知れば、ファイル命名規則の考え方も変わってくる。

 

ファイル命名規則の考え方が変われば、ファイルやフォルダの運用も変わってくる。

 

ファイルやフォルダの運用が規則的になれば、制作現場のデータ運用も変わってくる。

 

データ運用の無駄を抑制できれば、金銭や時間や人的資源の運用コストも変わってくる。

 

運用コストを改善できれば、現場全体を改善へと導くきっかけとなる。

 

 

‥‥と、以前、「地道に状況をレゴブロックのように積み重ねる」と書いたことは、まさにこうした流れのことを指します。秘密兵器、必勝兵器なんて存在せず、地道で先見性のある「積み重ね」だけが現場を変えていけると、少なくとも私は考えます。

 

改善の積み重ねも無しに、業界外部の門外漢の人々に、いくら「私たちアニメ業界はお金に困っています。増額してください。」なんて訴えたところで、「まず、自分らの基礎的で地道な改善をしてから、訴えてくださいよ」とひと蹴りされておしまいです。効率改善、現場の改善なんて、どんな業種だって重要なテーマです。アニメ業界だけが野放図に状況にひきづられてダダ漏れコスト消費のなすがままで良い‥‥なんて「あるわけがない」のです。

 

構造の改善は全く着手せず、現場作業者の目先の報酬を徐々にカットしていく‥‥なんて、アホ丸出しです。ゴツ石だらけ、ゴミだらけの畑に、いくらタネと水を撒いても、まともな作物なんて育ちません。上の人間も下の人間も、制作構造の「土壌」から改善することを、2020年代の目標にすべきと思います。

 

「コンピュータを毎日使っていながら、コンピュータの基本的かつ絶大な能力を使っていない」なんてことが起こらないよう、プログラムの「ちから」を制作現場にもっと導入すべき‥‥と考えます。

 

 

 

* * * * * * * * *

 

おまけ:正規表現によるフォルダ内リネーム

 

今回のブログ記事用にせっかく「アンダーバーかハイフンで区切られた(区切られていなくても良い)、1桁以上の連番と、ドットと、拡張子」にマッチする正規表現を書いたので、以前ブログで書いた「ESTKからフォルダ内をリネームするスクリプト」を改造して、汎用度を高くしました。

 

以下。

 

_1801_RENAME_RE=new RegExp("[_-]*[0-9]+¥¥.[A-Za-z0-9]{2,}");
alert(main());

 

function main(){
    var theFolder=Folder.selectDialog("フォルダを選択してください");
    if(!theFolder){return "処理をキャンセルしました";}
    var theFiles=theFolder.getFiles();
    if(theFiles.length<1){return "フォルダが空です";}
    for(var i=0;i<theFiles.length;i++){
        var reMatch=theFiles[i].name.match(_1801_RENAME_RE);
        if(reMatch&&theFiles[i].name.match(/^[A-Za-z0-9]/)){
            theFiles[i].rename(theFolder.name+String(reMatch));
        }
    }
    return "処理が正常に終了しました";
}

 

これなら、「a-01.tga」でも、「a_1.tif」でも「a_001.tiff」でも、「a0001.psd」でも、全て「ファイル名に含まれる素材名部分を親フォルダ名に書き換えてリネーム」できます。

 

ドットで始まる「隠しファイル」がわんさか存在するOSXでの運用を鑑みて、「match(/^[A-Za-z0-9]/)」の条件は念のため入れときました。先頭に記号を付与して、事前に処理対象から意図的に外すことも可能です。

 

まあ、まだ穴はある(エラーで止まる条件は残っています。例えば、「a0001.tga」と「b0001.tga」が同じフォルダに入っていた場合、2つとも「親フォルダ名0001.tga」にしようとして失敗する‥‥など)のですが、かなり現場の作業傾向を吸収できそうです。

 

私は正規表現の使い手ではなく、必要に応じてチョコっと‥‥という程度なので、「.」を「¥.」にするまでは良かったものの、「""」で囲む時に「¥自身のエスケープ」を忘れて、期待通りの動作をせずにウンウン唸ってました。「""」で囲む=クォーティングする場合は、「¥¥.」ですよネ。正規表現に限らす、「" "」や「' '」のクォーティングの際にエスケープ文字自身をエスケープするのは、基本ですよね。

 

そんな程度の私でも、日々の制作作業において、自作スクリプトは大活躍です。‥‥というか、自作のスクリプトやヘルパーソフトウェア、エクスプレッションがなければ、「できることもできなくなる」のが未来の制作技術だと痛感しています。数百にも及ぶキーフレームを意のままに操作するなんて、手作業でいちいち操作してたら無理ですもんネ。

 

 


最初は覚えることいっぱい

前回、スクリプトの補足を書いてて、どんどん解説文が長くなるのを我ながら見て、たった3行のスクリプトでも覚えることはそれなりに多いな‥‥と実感しました。あれだけ長く書いた割に、「var」とか、「 = 」とか、for構文の「{ }」とか、行末の「 ; 」は、しれっと何も説明しないまま、スルーしてますもんネ。

 

例えば、「var theNumber = 120;」の「var」はvariable〜バリアブル〜「変数」の英単語の頭文字3文字です。しかし、変数といっても、ローカル変数=その場だけで有効な変数もあれば、グローバル変数=After Effectsが起動している間はずっと有効な変数もあります。また、値やオブジェクトを格納するのは、変数だけでなく、定数でも可能です。

 

varは、ローカル変数を明示的に生成する時に用います。そうしないと、特にAfter Effectsの場合、昼は作業、夜はレンダリング‥‥みたいにAfter Effectsが起動しっぱなしだと、偶然、複数のスクリプトで同じ変数名を使っていた際に、思わぬ事故が起こることがあります。空だと思っていた変数が、実は全く違うスクリプトで数日前に代入済みで、思わぬ動作をする‥‥みたいに。

 

ですから、After Effectsのスクリプトの場合、

 

theNumber = 120;

 

のような、グローバル変数の代入ではなく、

 

var theNumber = 120;

 

‥‥のようなローカル変数の代入が基本になります。After Effectsのグローバル変数は、After Effectsが起動している限り、たとえスクリプトが終了しても生き続けるので、注意が必要です。

 

「え? エクスプレッションだとvarなんて使わなくてもトラブルはないけどな」

 

‥‥というのは、その通りで、After Effectsのスクリプトとエクスプレッションは、グローバル変数の「スコープ=範囲」が違うのです。

 

エクスプレッションは逆に、変数の寿命‥‥というか有効範囲が「そのフレームだけ」と極端に狭いです。毎フレームごとにエクスプレッションが実行されますが、そのたびに、グローバルもローカルも関係なく変数の寿命は終了して空になります。

 

なので、エクスプレッションは、

 

theNumber = 120;

 

‥‥でも、全く問題がないのです。

 

反面、エクスプレッションは、タイムライン〜フレームにまたがって変数を持てません。ですので、裏技‥‥というか、他の方法でフレーム共通のグローバル変数もしくは定数を実現することになります。マーカーを作ってコメントを書いて参照して定数にしたり(直にエクスプレッション文をイジらなくても定数の変更が可能)、他のテキストレイヤーのテキスト内容の読み取り(連動して動作させるには、結構、構造は複雑になります〜正確には変数ではなくクリップボードのような扱い)など、「本来、変数・定数の格納場所として想定されていないものを無理矢理活用」すれば実現できます。

 

 

‥‥とまあ、変数1つで、ちょっと説明しただけで、これくらいは必要になります。

 

最初は覚えることが多くて、それが初心段階の大きな障壁ともなります。

 

なので、いっきに覚えて習得するのは、そもそも無理だと諦めて、今、自分の差し迫って必要な雑事を軽減するためのスクリプトを書くことだけに集中して覚えて、それを繰り返していけば、いつのまにか、「あれ? 自分、プログラムのことをある程度、理解できてるよな?」と我ながら驚くわけです。

 

日本語だってそうだったはず。

 

喋りたいこと、伝えたいことのために、まず言葉を覚えていったのを思い出せばよいです。

 

‥‥で、プログラム、スクリプトは、20〜30代の若い頃に覚えちゃうのが、絶対にお得です。だって、何よりもまず、覚えるための脳の柔軟性がありますもんネ。アラウンド40以降になると、何度も反復しないと覚えられないことが、アラウント30だとあっさり覚えられたりします。ん〜、自身で実感。

 

普通に現代社会の状況の成り行きを考えて、10〜20〜30代の人間は、コンピュータを絡めて仕事をする未来がほぼ確定しています。よほど特殊な職種でない限り、コンピュータと無縁ではいられないはずです。だったら、プログラムの基礎を覚えておいて、損はないはず。

 

代々の農業を兼業するのだって、田畠の管理にコンピュータを使っても良いわけですから、デジタルデータで運用する映像産業に従事するのなら、なおさら‥‥ですよネ。

 

 

 


スクリプト補足

前回に載せた「フォルダ名で、中身のファイルをリネームする」スクリプトですが、あまりにもちゃちゃっとブログ文中で済ませたので、補足しておきます。

 

ちなみに、私はアニメーター100%だった頃、コンピュータやプログラムとは真逆の人間だと周囲から思われていましたし、自分もプログラムなんてとてもじゃないが‥‥と思っていました。学校でコンピュータやプログラムを教わったことなど皆無でしたし。

 

でも、今はこんな‥‥です。

 

なので、本人の気概次第でプログラムの基礎くらいは習得できると思っています。プログラム言語よりも遥かに難解な日本語を話せるのですから。

 

で、前回のスクリプトは‥‥

 

var theFolder=Folder.selectDialog("フォルダを選択してください");
var theFiles=theFolder.getFiles("*_?????.tga");
for(var i=0;i<theFiles.length;i++){theFiles[i].rename(theFolder.name+"_"+theFiles[i].name.split("_")[theFiles[i].name.split("_").length-1]);}

 

‥‥の3行スクリプトでした。

*ブログの表示幅の都合で、自動回り込み改行で4行に見えることもありますが、実際は3行となります。

 

これに注釈を添えると‥‥

 

var theFolder=Folder.selectDialog("フォルダを選択してください");

 

ユーザにフォルダを選択してもらうよう催促するのが、Folder.selectDialog() です。選択したフォルダを記憶しておくために、変数「theFolder」に代入します。変数の名前はtheFolderでなくても構いませんが、予約された単語とは被らないようにします。「folderA」「target_folder」などでも大丈夫です。

 


var theFiles=theFolder.getFiles("*_?????.tga");

 

getFiles() は、文字通り、フォルダの中にあるファイルをゲットする命令です。ただし、ファイル全てをゲットしてしまうと、不要なファイルまでゲットしてしまう可能性も否めません。そこで、「連番ファイルだけを選び出す」ために、条件をつけます。

 

今回の連番のファイル名は、「親フォルダの名前」+「アンダーバー」と「数字5桁」と「ドット」と「TGA拡張子」で構成されていますので、その連番ファイルだけを選び出してゲットします。「選び出し」を可能にするのが、getFiles() の括弧内の指定です。

 

「*」は0文字以上の何らかの文字列、「?」は何らかの1文字を表し、その他はそのままの文字として認識されて、選び出しの条件となります。ゆえに、「*_?????.tga」で「a_00001.tga」などの連番ファイルだけを抜き出すことが可能になります。同じ条件で「zz_xx_cdefg.tga」も条件に引っかかることになりますが、映像制作の素材フォルダにはそのようなファイル名が含まれていないことがわかっていますので、甘い条件でも十分機能します。

 

もし「b_0001.tif」や「b_0122.tif」などの4桁&TIFF連番を抜き出したい場合は「*_????.tif」にすれば良いです。

 

もっと条件をユルくして、「*.???」なら、「b_0001.tif」も「a-ue_001.tga」「anim_06_231_t2_0048.dpx」でも、全部対象になります。「ドット&3文字拡張子」なら何でも抜き出せる‥‥というわけです。中身に何が入っているか、自分自身で確信があるのならそのくらいユルくてもOKですが、スクリプトプログラムを作った本人以外の他人が使う時は注意が必要です。

 


for(var i=0;i<theFiles.length;i++){theFiles[i].rename(theFolder.name+"_"+theFiles[i].name.split("_")[theFiles[i].name.split("_").length-1]);}

*ブログの表示幅の都合で、自動回り込み改行で2行に見えることもありますが、実際は1行となります。

 

for」は繰り返しを処理する構文で、プログラム初心者の「最初のハードル」と言えるかも知れません。「for(var i=0;i<theFiles.length;i++)」は、「まず最初に変数iにゼロを代入し、変数iが変数theFilesの中身の総数より小さい間は処理を繰り返し、繰り返しごとの最後に変数iに1をプラスしてループ先頭に戻る」という意味になります。

 

一方、変数theFilesの中身は、先ほどの「getFiles("*_?????.tga")」によって、TGAの連番ファイルが格納されているので、この、for構文で順番に中身を取り出して処理していきます。theFilesの中にあるTGA連番ファイルは、一番目のファイルを「theFiles[0]」、七番目のファイルは「theFiles[6]」というように「ゼロスタートに読み替えて」指定して取り出すことができます。

 

for構文において、変数iは、繰り返しごとに、0, 1, 2, 3, 4, ....と増えていくので、変数iを呼び出し番号として活用し、theFiles[i]のように用いれば、theFIlesの中身を順番に取り出すことが可能になります。

 

次に、theFiles[i]で呼び出した個々のTGA連番ファイルを、いよいよ、「rename()」命令でファイル名変更しますが、そのためには、新しいファイル名を、親フォルダの名前と古いファイル名を部分的に合体させて生成する必要があります。

 

変更後の名前は、「親フォルダの名前」+「アンダーバー」+「元の連番と拡張子」にしたいので‥‥

 

親フォルダの名前を得る>>theFolder.name

 

‥‥は簡単だとしても、面倒なのは‥‥

 

元のファイル名から連番と拡張子だけを得る>>「a_00001.tga」の「00001.tga」の部分

 

‥‥です。でも、映像制作では連番の前を「アンダーバーなどで区切る」のが一般的なので、それを有効活用します。つまり、ファイル名をアンダーバーで区切れば、「a」と「00001.tga」を分割=split() できます。

 

例えば、"a_b_c_d" という文字列があった場合、"a_b_c_d".split("_") を実行すると、["a","b","c","d"] という配列に分解されます。この配列から3番目の要素である "c" を抜き出したい場合、ゼロから数え直して、[2]という呼び出しかたで抜き出します。つまり、"a_b_c_d".split("_")[2] で "c" を抜き出せます。

 

なので、"a_00001.tga" から "00001.tga" を抜き出すには‥‥

 

"a_00001.tga".split("_")[1]

 

‥‥でうまくいきます。

 

しかし、今回は「a_00001.tga」でしたが、もし「a_un_00001.tga」みたいなファイル名だったら‥‥

 

"a_un_00001.tga".split("_")[1]

 

‥‥では「un」が抜き出されてしまいます。前方から数えて抜き出すのではなく、最後の要素を抜き出せば、必ず、「00001.tga」が抜き出せます。しかし、残念ながら、最後から数えるのに [-1] のような指定方法は通用しません。

 

なので、split() で分割した要素数を数えて、1スタートではなく0スタートで指定するために要素数からマイナス1すれば、最後の要素を指定して抜き出すことが可能になります。要素数を数えるには「length」を使います。

 

"a_00001.tga".split("_")["a_00001.tga".split("_").length-1]

 

"a_un_00001.tga".split("_")["a_un_00001.tga".split("_").length-1]

 

この方法なら、ちょっと文が長くて解りにくくなりますが、どの場合も確実に「00001.tga」を取り出すことができます。スクリプト文中ですと‥‥

 

theFiles[i].name.split("_")[theFiles[i].name.split("_").length-1]

 

‥‥という具合になります。

 

連番と拡張子が取り出せたのなら、あとは親フォルダの名前と合体させるだけです。アンダーバーも忘れずに。

 

theFolder.name+"_"+theFiles[i].name.split("_")[theFiles[i].name.split("_").length-1]

 

新しい名前を生成できたら、rename()」命令で実際にファイル名を変更して終了です。

*ブログの表示幅の都合で、自動回り込み改行で2行に見えることもありますが、実際は1行となります。

 

theFiles[i].rename(theFolder.name+"_"+theFiles[i].name.split("_")[theFiles[i].name.split("_").length-1])

 

 

実際に処理をすると、72ファイル程度のリネームなど「瞬殺」で処理終了です。

 

 

↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

 

 

 

 

たった3行のプログラムですが、最後の行に「for」「rename()」「split()」などが一気に盛り込まれたので、ちょっと難しいようにも思えますが、落ち着いて、行頭から1つ1つ意味を理解して進めば、混乱することはありません。

 

リネームはこのやり方の他にもたくさん方法があります。今回は「親フォルダ名と元の連番&拡張子を合体させる」方針なので、上記の方法になりましたが、文字列の「置換」を使ったり、ソートしてリナンバーする方法も考えられます。

 

何か1つの段取りを守らないとリネームができないわけではなく、工夫次第で色々なアプローチを考えて実践できるのが、プログラムの「実は楽しいところ」です。

 

でも‥‥

 

工夫次第で色々なアプローチを考えて実践

 

‥‥って、絵を描いたり、話を考えたり、視覚効果を追加したり、音楽を作ったりすることと、何だか似てます。料理や運転、経営・経済などにも共通すること‥‥かも知れませんネ。

 

 

 

 

*追記:

今回の3行のサンプルスクリプトは、できるだけ簡潔にするために、例えば「ユーザがキャンセルボタンをクリックした」「フォルダの中身が空だった」などの「false」「null」「[ ]」「undfined」に対応する処理が全く書かれていません。その点に関しては、ESTKの元になっているJava Scriptの指南Webなどで独学してください。

 

例えば‥‥

 

main();

 

function main(){

var theFolder=Folder.selectDialog("フォルダを選択してください");

if (!theFolder) {return false;}

}

 

‥‥などのようにキャンセルに対する処理を施します。

 

 

 


最初の言語

AppleScriptは冗長です。自然言語処理をするために、ファイルのパスなどはいちいち面倒です。私は最初AppleScriptばかりやっていたので、他の言語を覚え始めた時にはじめてAppleScriptの「浮いてる感じ」が意識できました。

 

file "06_201_bg-ok.psd" of folder "BG" of folder "201" of folder "06" of folder "ABC" of disk "MacHD"

 

いかにも冗長ですが、それこそAppleScriptの真骨頂で、プログラム文が英文として理解できるように設計されていたのです。

 

賛否や好みは別として、それはそれで有意義な言語だったと思います。少なくとも私は、その言語スタイルゆえに「最初のハードル」を独習のみで超えられた実感があります。

 

AppleScriptで全てをこなすことはできませんし、AppleScriptの限界を感じて他の言語を追加で習得したわけですが、最初の言語としてはAppleScriptの開発者の方々には感謝しています。

 

 

ちなみに、AppleScriptでも、もっとチャチャッとファイルパスは記述できて、

 

file "MacHD:ABC:06:201:BG:06_201_bg-ok.psd"

 

‥‥と書くこともできますし、

 

POSIX file "/ABC/06/201/BG/06_201_bg-ok.psd"

 

‥‥とUNIXスタイルで書くこともできます。そんな便利な方法、超初心者の頃はまるで知らなくて、延々と「ファイルオブ、フォルダーオブ、フォルダーオブ、フォルダーオブ...」と書いてましたけどネ。

 

プログラム言語は、習得する過程、上達して色々な方法を体得する過程で、コンピュータやネットワークやオペレーションシステムの理解も深くなり、コンピュータがどんどん「自分の中に吸収されて」いきます。

 

例えば、macOSのシステムのパスだと、外付けハードディスクの中にあるファイルは、「HHD1」という名前のハードディスクの場合、

 

file "HDD1:footages:001.mov"

 

‥‥とAppleScriptで書きますが、同じくAppleScriptでUNIXのパスを扱う場合は、

 

POSIX file "/Volumes/HDD1/footages/001.mov"

 

‥‥という文字列になります。

 

単にファイルを読み書きするスクリプトを作りたいだけなのに、色々とナゾ仕様な「Volumes」が現れて、初心者を混乱させますが、実はその混乱は福音でもあります。当人はウンウン悩んで苦しみますが、混乱を収拾する過程で知識ががっぽがっぽ蓄積していくのです。

 

ボリュームズ? マウントポイント? ルート? ルートディスクとルートユーザーとか色々とあるの? ターミナル? コマンドライン? 不可視項目?

 

プログラムの門を開いて中に進む‥‥ということは、鉄の門の向こうにあってブラックボックスだったコンピュータの中にズンズン入っていく‥‥ということです。プログラムを覚えると、「コンピュータの知識特典」が山のようにオマケでくっついてきます。(‥‥オマケという言い方は、少々乱暴ですけどネ)

 

ある程度の規模のプログラムを作るようになると、否が応でも、コンピュータの知識は高まっていきます。

 

自動車の単なる乗客でしかなかった人間が、たとえ50ccでも自動車モドキを自分で製作すれば、エンジンの中身も開けるし溶接もするしで、格段に基本メカニズムや製作技術に詳しくなっていくのと同じです。つまり、「メカ音痴」ではなくなるわけです。

 

同様に、コンピュータ音痴ではなくなります。

 

そればかりか、色々とコンピュータ言語を扱うようになると、使っている言語の弱点がわかって、自分で言語を強化することすら可能になってきます。

 

例えばAppleScriptは文字列処理が「異様に弱い」のですが、他の言語にあるような「split()」や「slice()」などのサブルーチンを作ってモジュール化し、色々なスクリプト作成時にロードすれば、毎回いちいち「AppleScript's text item delimiters」なんて冗長なコードを書かずに済みます。ちなみに、splitは文字列を分割、sliceは文字列を切り抜く処理です。AppleScriptはソート関連も弱いので、ソート関数も強化して使っていました。

 

 

 

人間は、生まれてすぐに「コンストラクタがどうだ、インヘリタンスがどうだ」なんて語り始めるわけもなく、最初は誰もが「ど素人」だったわけです。

 

私なんか、(何度も書くけど)最初のころ、MacOSだったせいもありますけど、拡張子の「.psd」を堂々と全角で力強く「.PSD」とかファイル名に使ってましたし、「PICTファイル」なのに「.psd」という拡張子をつけたり、メチャクチャでしたが、‥‥‥そんなのさ、初心者は超能力者じゃないんだから、「初心者に向かって最初から解ってろという方がオカしい」んですよ。

*注記)Macの場合、MacOS9までは「拡張子」における動作の仕組みはありませんでした。クリエータタイプ&ファイルタイプという独自のリソースで動作していたので、ぶっちゃけ、どんな名前でも構わなかったのです。

 

ただ、いつまでも初心者ぶって、覚える努力もしなければ、人に聞くことだけで乗り切ろうとするのも、ダメダメです。

 

コンピュータで映像制作をおこなうということは、ほぼ一日中、コンピュータをイジりまくっているのです。だったら、プログラム言語の1つ2つ習得しておいて損はないでしょう。

 

使えないより、使えた方が良いのは、明白‥‥ですよネ。

 

 

 

 


言語のおぼえかた

プログラム言語に関して、他人にアレコレ事細かく指南できるほどのスキルは持ち合わせていませんが、経験からくる「覚え方のコツ」は自分なりに理解しています。

 

単語は辞書を引けば良いので、何よりも構造を覚えてしまうのが、プログラム言語習得のコツです。

 

例えば、各国の言語でも、

 

私の名前は江面です。

My name is Ezura. 〜マイ ネーム イズ エズラ

Mein Name ist Ezura. 〜マイン ナーメ イスト エズラ

Меня зовут Эзура. 〜ミニャ ザブゥ エズラ(カタカナにするのが難しい‥‥)

 

‥‥と、構造はかなり似ています。特に上の例文においては英語とドイツ語はクリソツ。

 

これと同じように、プログラム言語も基本的な構造は同じです。以下の内容は「このCompの名前は『ezura Comp』である」という文です。「比較演算子」を用いた文で、「である=true:真」「ではない=false:偽」=真偽値が返ります。

 

thisComp.name == "ezura Comp";

name of thisComp = "ezura Comp"

name of thisComp is "ezura Comp"

name of thisComp is equal to "ezura Comp"

 

辺境のAppleScriptの例が多いですが、AppleScriptは言い回しが多様なので、例として挙げてみました。AppleScriptは「=」だの「is」だの「is equal to」だの色々と言い回しがあってにぎやかです。一方、「==」を使うプログラム言語は多く、ほとんどの言語で通用します。

 

私は一番最初にAppleScriptから入り、やがてシェルスクリプトやPerl、REALbasic、PHP、JavaScriptなどを色々な言語を必要に応じて順次覚えていきました。現在は目下、SwiftやPythonですが、参考書に目を通していても、円滑に理解が進みます。

 

思うに、私がAppleScriptからプログラム言語の習得を始めたのは、「ラッキー」だったと思います。なぜかというと、AppleScriptは今までの経緯で「すったもんだ」があって、「なりゆきとして」言語のスタイルを覚え直すハメになったからです。

 

いわば、「不幸中の幸い」です。

 

私がAppleScriptを最初に覚えたのは、ズバリ、日本語で記述できるのがAppleScriptのウリだったからです。1997年の事です。

 

例えば、

 

アプリケーション “Finder”について

起動項目のフォルダ “テスト”のファイル “picture.psd”の 名前を “picture1.psd”にする

以上

 

‥‥といった具合(記憶で書いてるので半角スペースの入れ方とかは曖昧です)で、日本語でスクリプトの自動処理が書けたのです。これは日本人かつ今までアニメーター100%だった私にとって、とても馴染みやすい仕様でした。

 

しかし、運命とは、残酷なもの。

 

突然のApple(開発元ですネ)による「日本語環境打ち切り」。

 

AppleScriptは英文のみとなり、私にとっては目の前が真っ暗になる仕様変更でした。「アップルのばかーーーーー!」と叫びたい心境‥‥いや、実際に叫んだかもネ。

 

でも、随分と使えるようになった言語を諦めるのもシャクだったので、英文で仕方なく覚え直し始めました。

 

英文で書くと、こんな感じ。

 

tell application "Finder"

    set name of file "picture.psd" of folder "テスト" of startup disk to "picture1.psd"

end tell

 

まあ、見事、無残に、ファイルパスの表記スタイルが真逆です。細かい点ではありますが、 ” が " になったりと、ほとんどゼロから覚え直しでした。

 

しかし、日本語が英語に変わっただけで、構造は同一なことに気づきました。日本語表現形式か、英語表現形式の違いだけで、中身は一緒です。

 

かえって、漫然と日本語スクリプトを覚えていた時よりも、構造に目を向けるようになって、ある程度英語表現に慣れたあとは、今まで以上に理解が進むようになりました。

 

わからない単語は辞書を引けばすみますが、構造がわからなければ、全体のプログラム動作が掴めません。構造を把握することで、プログラム言語で何を覚えれば良いかが開眼できたのです。

 

同じ例文をAdobeのESTKで書いてみると、

 

File("/テスト/picture.psd").rename("picture1.psd");

 

‥‥となります。

 

名前変更の際に、ファイルオブジェクトのファンクション「File(ほにゃらら).rename(新しい名前);」を用いるところとか、macOSゆえのUNIXパスだったりと、色々と違う点もありますが、「対象の項目を指定して処理を加える」という基本動作には何ら変わりはありません。

 

つまり、何らかのプログラム言語を覚えて、その後にもう1つ別のスタイルの言語も覚えれば、言語の差から色々な「覚えるべき有益な要素」があぶりだされて、自然と習得できるようになります。

 

よく聞かれる質問で、「どんな言語を覚えれば有利か」とかがありますが、ぶっちゃけ、自分の今すぐ役に立つ言語を覚えとけば良いです。何が基準かも釈然としない有利不利や損得基準で言語を選ぶよりも、今すぐに活用できる言語を選べば良いです。

 

例えば、アニメ制作でコンポジット周りなら、迷わずAdobeのESTK、すなわちJavaScriptベースの拡張言語でしょう。すぐに役立つもんネ。

 

After EffectsやPhotoshopなどの主要アプリケーションを自動で操作して、様々な業務に活用できます。例えば私は、After Effectsのレンダリングエンジンが「レンダリングするだけしか使えない」のがイヤで、自家製のレンダリングエンジンを作っていました。独自の「キューファイル」(SJISやUTF-8などのテキストファイル)を規定してサーバにキューファイルを書き出し、他のマシンで待ち受け中のAfter Effectsがそのキューファイルを読み取り、キューの記述を読み取って動的に内容変更してレンダリングする仕組みでした。常駐型のスクリプトもESTKでは書けるんですヨ。

 

ESTKでは他の言語同様にテキストファイルの読み書きが可能なので、キューファイルのような「伝票」を作ることなど朝飯前。初心者の腕試しにちょうど良いです。AEPのプロジェクトを次々と開いて、After Effectsの最終コンポジションの内容をリスト化(テーブル化)したHTMLだって、繰り返し文を用いて何のヒネリもなく作れます。

 

長いコード文を掲載するのもブログでは大変なので、お約束のアレをHTMLで書き出してみます。

 

var myFile = new File("/テスト/hello.html");//macOSの場合のパスです
myFile.encoding="UTF-8";
myFile.open("w");
myFile.write('<!doctype html>¥n');
myFile.write('<html>¥n');
myFile.write('<head><meta charset="UTF-8">¥n<title>Hello, World.</title>¥n</head>¥n');
myFile.write('<body>¥n');
myFile.write('<h1>こんにちは、みなさん。</h1>¥n');
myFile.write('<p>いざ、プログラムの世界へ。</p>¥n');
myFile.write('</body>¥n');
myFile.write('</html>');
myFile.close();

 

バックスラッシュが「¥」になっちゃってますが、読み替えてください。¥nはコードの改行です。Pタグの行をどんどん増やせば、どんどん書きたい文章を増やせますネ。

 

このスクリプト文をESTKで実行すると、以下のようなHTMLファイルが自動生成されます。

 

ハロー、ワールド。

 

 

とりあえず、今、使えそうな言語を習得しておけば、その言語が有利か不利かなんて「後でどうにでもなり」ます。

 

一番不利なのは、グズグズ何しようかとぶーたれている間に、全く言語を習得できないこと‥‥ですネ。

 

 

 

*久々にひっぱりだしてきたロシア語(キリル文字)のキーボード。ローマ字入力の英語キーボードではロシア語は無理なので‥‥。

*ちなみに、私は最初、筆記体から入っちゃったので、活字(ずいぶん外見が違うんですよ)が読めないアホな状態で苦しんでおりました。キリル文字のキーボードは手に入らなかったので、ロジテックのK120キリル文字ステッカーを貼っています。

*今日届いたスイフトのリファレンス。新刊です。

*写真の机が随分とカスれてエグれているのは、絵を描く際に袖のボタンが当たってエグれたのです。私は左利きなので、机の左部分だけ木材が露出しています。よほど硬いボタンだったんでしょうかねえ‥‥。記憶にないです。‥‥‥‥でもまあ、ほんとに、駆け出しの頃(18〜22歳)は、死に物狂いで必死だったんでしょうねえ‥‥我ながら。

 


Photoshopの自動処理(2)

PSDファイルから原画体裁のTIFFファイルを書き出すスクリプトは前回に方針が定まったので、あとはスクリプトを書いて動かすだけです。

 

TIFFファイルを書き出すには、ファイルとフォルダの扱いが不可欠です。新規でTIFFファイルを書き出すには、少なくとも、書き出す場所=フォルダ階層と、ファイル名が必要です。

 

しかし、ファイルを書き出すパス‥‥といっても、一筋縄ではいきません。

 

業務上のワークフローのオンラインで扱うファイルに、日本語を使うつもりはないですが、やはり日本国内で制作しているのですから、日本語を使うファイル名が存在しても、正常に処理できたほうが良いです。

 

AdobeのJavaScriptで扱うファイルやフォルダは、パスに日本語が含まれていると、てきめんに文字が化けます。ゆえに「fsName」や「File.decode()」が用意され、文字化けを正常な日本語に戻すことが可能です。

 

例えば、現在Photoshopで開いているドキュメントのパスを取得しようとして、

 

var doc=app.activeDocument;
doc.fullName;

 

‥‥みたいな単純な書き方ですと、もしファイルパスに日本語が含まれていると、それはもう、悲惨な文字列に。

 

/Users/Shared/%E3%81%A8%E3%81%82%E3%82%8B%E3%83%95%E3%82%A9%E3%83%AB

%E3%82%BF%E3%82%99/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3

%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.png

 

 

まあ、わざと日本語をたくさん入れて化けさせてはいますが、以下のようにコードを書き足すだけで、

 

var doc=app.activeDocument;
doc.fullName.fsName;

 

正常な日本語の文字列を得る事ができます。

 

/Users/Shared/とあるフォルダ/スクリーンショット.png

 

 

名前だけが欲しければ、"/"でsplitして最後の要素だけを取り出しても良いですし(macOSの場合)、以下のように、

 

var doc=app.activeDocument;

File.decode(doc.fullName.name);

 

‥‥でも取り出せます。結果は、「スクリーンショット.png」です。もちろん、

 

var doc=app.activeDocument;

doc.name;

 

‥‥でも良いです。注目すべきは、Fileオブジェクトから名前を取得する場合はデコード「File.decode()」が必要で、開いているドキュメント名から取得する場合は単に「Document.name」で文字化けしない点です。

 

ここらへんの段取りの「クセ」を知っておかないと、Photoshop&JavaScriptではファイルを書きだすことができないんですよネ。

 

ちなみに、このあたりのことは、「ADOBE PHOTOSHOP JAVASCRIPT SCRIPTING REFERENCE 」には載ってなくて、別冊の「JAVASCRIPT TOOLS GUIDE」の中に掲載されています。ESTKのフォルダの中にPDFがあるので、それを読むべし。

 

 

ファイルを書き出す‥‥と言っても、まだ考えどころは残されています。

 

  • どこに書き出すのか。=ユーザに尋ねるか、PSD元データと同階層にするか。
  • フォルダにまとめるか。=まとめるのは良いとして、どんな名前のフォルダにするか。
  • 書き出し先に同名の項目があった場合はどうするか。=既存の項目をリネームするか、新作の項目に番号をつけるか、それとも削除するか、上書きするか

 

Photoshopの自動処理自体は、そんなに大した内容ではないですが、こうした足回りの処理は地味に面倒です。でも、これを嫌がると、エラーで止まってばかりのスクリプトになってしまいます。どんなにPhotoshop部分のスクリプトが快調に動作しても、ファイル書き出しで躓けば意味がありません。

 

 

こうしたスクリプト作成の手間を事前に割いて、自動処理をスタンバイしておけば、その後の作業で確実に時間短縮と労力削減が実現します。

 

急がば回れ‥‥です。

 

あと、もう少しで完成して、明日ぐらいから使えそうな予感。

 

 

 

 


PHP

久々にPHPの現在を調べてみると、バージョンは7。‥‥うーむ。私が沢山書いてたころは、3だった記憶があるので、もはや修正するよりも書き直した方が速いレベルですネ。‥‥‥‥まあ、私が撮影業務のアシストアプリとデータベース/Webを必死になって作ってたのって、もう10年以上前だもんなぁ‥‥。

 

宇宙船演算子なんてのも7から加えられたようで、PHPを今後また本格的に使うようなら、7基準でゼロから考え直したほうが良いですネ。

 

<=>

 

その昔、撮影はコアレタスじゃないとできない‥‥なんて言われていた頃から、私らは撮影業務をAfterEffectsでおこなうべく色々と模索していましたが、なぜコアレタスを使わなかったのかというと、「価格が高い」「アニメに特化し過ぎてて拡張性・未来性が乏しい」そして「スクリプトに対応していない」のが理由でした。

 

例えば、何らかのスクリプト対応の表計算があれば、その表計算ソフトをタイムシートアプリにして、タイムシートをキーフレームとして流し込むことも、AfterEffectsからキーフレームをもとに表計算に流し込むことも可能でした。miなどのテキストエディタもタイムシートの入力・編集アプリに早変わりしました。

 

それだけでなく、データベースと連携して、カット情報とタイムシートデータを元に、AfterEffectsで「素組み」レベルまで自動ビルドすることもできましたし、AfterEffectsのレンダリングエンジンとは違う自動レンダリングシステム(データベースと通信しつつレンダリング後の事後処理もおこなう)も実現していました。

 

その際、データベースやライブラリのフロントエンドを提供していたのがPHP3でした。

 

進捗状況を棒グラフ(のようなルック)でHTML上で表示したり、任意のカットの詳細情報を表示したり、終了作品のムービーライブラリを提供したり、当時バージョン3だったPHPでも、撮影作業に有用な色々な事が可能でした。

 

PHPは、個人単位がスクリプトで効率化を図る目的には何も貢献しませんが、「ワークグループ」という概念を実践するのならば、制作進捗情報の共有と同調を可能にして、状況把握の齟齬を解消する大きな役割を果たします。

 

まあ、PHPと同じことができるソリューションなら何でも構わないと言えば構わない‥‥のですが、PHPは何と言っても「手軽」だったのがよかったのです。「ほにゃらら.php」のファイルを作るだけでしたからネ。

*サーバ上でのリダイレクトやエイリアスを活用する場合は、Apacheのコンフィグをイジって連動させる必要はありましたが‥‥。

 

 

 

しかし、PHP。

 

今、私は、Pythonの習得を時間の合間でぼちぼち開始していますが、何だか、PHPとPythonでできる事がかぶってる気がします。

 

管理上の視点からも、もし色々と機能的にかぶっていて重複も甚だしいのなら、どちらかにしぼるべきでしょうネ。

 

 

まあ、PHPは昔覚えたし、今はPythonを主眼にしておこうと思います。

 

 

 

ちなみに、Python。

 

まだ私は始めたばかりですが、ざっと見る限り、言語的にはごく普通にとっつきやすい内容のようです。

 

アニメ作業関係者の人でもAfterEffectsのJavaScriptでスクリプト文に慣れているのなら、ちょっと読みかえれば基本構造は理解しやすいと思います。まあ、何らかの言語をそれなりに突っ込んで覚えた経験のある人なら、「まるで異質には感じない」でしょう。

 

なので、作例や使用例・運用例をいくつか実践してみて、Pythonの流儀に慣れれば問題なくイケそうな感じです。

 

 


Photoshopの自動処理

私は原画作業をProcreateで描いた後に、「共有」でPSD形式でAirDrop越しにiMacやMac Proに書き出します。そして、そのPSDから、紙チェック用の200〜300dpiの印刷データをTIFFで書き出します。

 

アニメ現場でおなじみのTGA(Targa)はそもそも解像度の概念がなく印刷に全く不適合なので、解像度情報を保持できる一般的なTIFFやPSDやJPEG(クオリティ100%で)で書き出しています。‥‥まあ、今の所は、です。

 

‥‥で、そのPSDから「紙の原画仕様ファイル」への書き出しは、結構、面倒です。ケアレスミスも呼びやすいですし。

 

なので、そういうことは一番得意なコンピュータにやらせます。仕様に準じて、ミスなく出力する‥‥なんて、コンピュータの大得意な分野ですもんネ。

 

やるべきことは、PSDファイルを開いて、レイヤー重ねの上からでも下からでも、総当たりでレイヤーの名前と階層を分析し、何をどうすべきかを把握した後に、順番にTIFFで保存する‥‥という段取りです。

 

事前の条件として、PSDファイルの状態は、

 

  • レイヤーおよびレイヤーセットの名前は、規則通りであること
  • レイヤーセットの階層は、検索する深さに準じておくこと

 

‥‥が必要です。

 

 

ちなみに、最近までレイヤーをフォルダに格納した状態を「レイヤーフォルダ」という名称でこのブログで用いていましたが、Adobeの正式な呼称は「レイヤーグループ」のようです。

 

https://helpx.adobe.com/jp/photoshop/using/create-layers-groups.html

 

だが、しかし。 

 

‥‥スクリプトの英文マニュアルには「layer set」との表記があり、実際のスクリプト上でのタイプネームも「LayerSet」です。

 

俗称(他のソフトウェアの呼び名からの転用)も日本語呼称も、スクリプト作成時にいちいち読み替えるのが面倒なので、以後は英文リファレンスに従って、レイヤーセット、もしくはlayer set、LayerSetと呼ぶことにします。

 

 

話を戻して。

 

PSDファイルのレイヤー名やレイヤー階層を事前に規定・規約をしておくことで、コンピュータは「PSDファイルのレイヤーの中身を判断できる」ようになるのです‥‥が、それは人間とて同じことです。

 

例えば、「A3」レイヤーが存在する一方で、他のレイヤーセットの階層深くにもう1つの「A3」レイヤーが発見されたら、どっちが「本当のA3」なのか‥‥なんて、作った本人しかわからないですもんネ。「作った本人しかわからない」ものは、コンピュータも他人も扱いようがありません。

 

場当たり的な名前付けや階層構造は、著しく生産性を低下させます。当事者であっても、数ヶ月・数年経過すると、状況把握が困難になります。当事者ですら持て余す無整理・無秩序状態を、他者やコンピュータが理解できるはずもないのです。

 

まあ、だからと言って、「自動処理の都合に合わせて、人間が余計な労力を割いて従属する」のも本末転倒です。自分の仕事の効率化を図ろうとして自動処理を導入したら、コンピュータの流儀に何もかも合わせるのが重荷になって逆に仕事が増えちゃった‥‥というヤツですネ。

 

つまりは、

 

自分なりの整理整頓術と、自動処理のための状態管理の、接点

 

‥‥を探れば良いのです。‥‥まあ、往々にして悩ましいんですけど、あきらめずに攻略したい命題です。

 

 

話を本題に戻して。

 

繰り返しになりますが、今回の自動処理の達成目標は‥‥

 

PSDドキュメントファイルを開いて、もしくは開いているドキュメントの、レイヤーの状態を分析し、各原画やレイアウトのプリント用のTIFFファイルを生成する

 

‥‥です。

 

そのためには、まず何よりも、レイヤー構造の規定です。

 

3種類のパターンを想定しました。

 

 

 

常時表示したいレイヤーやレイヤーセットは、タップ穴の他にも、レイアウトフレームだったり話数やカット番号の表記だったり(レイアウト作業時)、白紙の背景だったり、色々ありますよネ。いちいち、全てのレイヤーに共通の表示パーツを複製してフラット化する必要はないですし、修正時(表記の間違いなど)に面倒でもあります。常時表示レイヤーの定義は必須です。

 

非表示レイヤーは、例えば提出時には不要だけど消去したくない下書きやアタリとか、メモとか、色々考えられます。常時非表示レイヤーも必須です。

 

順次表示レイヤーは、例えば、A1, A2, A3, A4‥‥のようなセルのシーケンスや、BG, BOOK1, BOOK2のような素材別のレイヤーを、個別出力するのに当然必要です。そもそも、この自動処理を作成する動機が、素材ごとの出力ですからネ。

 

レイヤーセットは、1枚のレイヤーへとフラット化したくない場合、つまり、1枚の絵を複数のレイヤーに分けておけたい場合に必要です。第1階層に未整理のレイヤーがバラバラっと乱雑に置いてあると整理がつきませんが、どんな状態であれレイヤーセットの中にブッ込んでおけば「それ以上は干渉されない」と規定しておけば、執拗にレイヤーの整頓に努めなくても作業は進みます。‥‥なので、レイヤーセットへの考慮も、規定では必須でしょう。

 

最後に「イメージシーケンス」のレイヤーセットです。まあ、普通に考えて、Aセルごと、Bセルごと、Cセルは1枚だからそのままで‥‥みたいな整理整頓はしたいですよネ。ゆえに、セルごと=イメージシーケンスのレイヤーセットを考慮し、その中に入れ子で「表示」「非表示」のレイヤーとレイヤーセットの内包状態を想定する必要があるでしょう。

 

イメージシーケンスをレイヤーセットにまとめて、中身を分析するのは、特に問題なくできましょう。スクリプト的には、レイヤーのタイプ判定してLayerSetだったら、その中身を「LayerSet.layers」により配列で取得して処理すれば良いだけです。

 

問題は、第1階層に存在するであろう、「1枚絵にフラット化したくないレイヤーセット」と「イメージシーケンスのレイヤーセット」を、どう見分けるか‥‥です。

 

一番スマートなのは、レイヤーの状態から分析すること‥‥ですが、ぶっちゃけ、今考えた時点では「何の状態をジャッジして分析するか」が思いつきません。

 

‥‥なので、今のところは、「レイヤーセットの名前から判断」するように規定します。イメージシーケンスであることを示す識別文字=ラベル文字列を規定して用いればよいです。

 

イメージシーケンスのレイヤーセットは、例えば「Aセル」の場合は、「A/」とか「a/」にして判別、ファイル出力時はレイヤーセットの中身のレイヤー名に準ずる‥‥とか、レイヤーセット名とレイヤー名を(スラッシュは抜いて)結合するとか‥‥色々考えられます。

 

気を付けたいのは、検索と置換とか、正規表現などで妙にてこずらないように、ラベル文字列を規定することです。後で、「何故、よりによって、こんな文字を使うかな。過去の自分の馬鹿馬鹿馬鹿」と後悔しないように、先を考えて規定しないとアカンです。自作のスクリプトで自分だけ自己嫌悪に陥るのならまだ良いですが、これが作業現場のシステム設計上だと目も当てられません。

 

う〜ん、どうしようかな‥‥。レイヤーセット名の文字列を「/」で終わらすというのは、安易かな‥‥。コメントの「//」と如何にも被りそうだから、たとえば「:」とかでも良いのかな。iPadで入力が楽な記号はどんなかな‥‥。‥‥いまのところ、文字の考えはまとまらず。

 

妙に長い文字列にすると、入力の際、面倒ですしネ。

 

まあ、常時表示と常時非表示のレイヤーも、レイヤー名の先頭文字列で認識しようと思っていますので、何かしっくりくる文字でキーボードで打ちやすい文字を探してみます。

 

 

 

今日はここまで。

 

もう、書けばすぐに動作するくらいには、考えがまとまりました。

 

ただし、「もし、ユーザのケアレスミスで同名のセル番号が存在した時、どのように動作させるか」などの「エラー対策」はまだまだです。書き出し処理を始める前に、レイヤーを全てチェックして、状態を分析する必要もありましょう。

 

 

 

 


AppleScriptのJavaScriptとExtendScriptのJavaScript

タイトルからして「Script」だらけでややこしい。

 

そして、実際もややこしい。

 

AppleScriptをJavaScriptで書ける‥‥という言い回しがそもそもややこしいですが、利点は大きく、AppleScriptにはないJavaScriptのMathとかStringやArrayの処理がAppleScriptにも使えます。文字列の分解とか配列の結合とかをAppleScript's text item delimitersに頼っているのは、なかなか厳しいですもんネ。

 

じゃあ、Photoshopのスクリプトを書くときに、AppleScript上でJavaScriptを使うと、どんな具合かと言うと‥‥

 

var app=Application("Adobe Photoshop CC 2018");

app.preferences.rulerUnits="pixel units";

var doc=app.Document({name:"TEST",height:1080,width:1920,resolution:200});

doc.make();

 

‥‥のような感じです。「1920px, 1080pxで200dpiの新規ドキュメントを「TEST」という名前で作れ」と言う命令文です。

 

実は、あわよくば、AppleScriptのJavaScriptとExtendScriptのJavaScript(あーややこしい)共用できる部分があるといいな‥‥と思ったのですが、

 

如何にもダメそう

 

‥‥ですネ。

 

ExtendScript、いわゆるESTKで同じ内容を書くと、以下のような感じです。

 

app.preferences.rulerUnits = Units.PIXELS;
var doc=app.documents.add(1920,1080,200,"TEST");

 

‥‥うーむ。共通しているのは、「app.preferences.rulerUnits」の箇所だけか。ESTKのPhotoshopだと、new Document()のコンストラクタが無いんですね。AppleScriptのJavaScriptとは段取りも違います。

 

まあ、たしかに、AdobeのExtendScriptでは、ドキュメントやレイヤーなどはコレクション(たとえばlayerならlayers=複数形で表す)からadd()するのが、昔からの流儀です。importOptionsとかはnewでもいけますが、コレクションオブジェクトのaddで大体は新作しますよね、AfterEffectsとかは。

 

 

まあ、今以上にややこしくしないために、おとなしく、PhotoshopのスクリプトはESTKで作って、必要に応じてAppleScriptはUI程度(Photoshopスクリプトを実行するための窓口)に留めます。

 

 

ちなみに、Photoshopのスクリプトに関するドキュメントは以下から入手できます。

 

https://www.adobe.com/devnet/photoshop/scripting.html

 

歴代のドキュメントが並んでいますネ。2018年現在の最新版はCC 2015みたいです。

 

 

 

 



calendar

S M T W T F S
    123
45678910
11121314151617
18192021222324
252627282930 
<< November 2018 >>

selected entries

categories

archives

profile

search this site.

others

mobile

qrcode

powered

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