MacOSXでツール開発

AppleScriptで小道具を作成
連番ファイルをムービーファイルに変換する小道具(1)


●少しだけ、前より欲張った仕様に‥‥

 JPEG変換ツールを作ったその次は、静止画連番をQuickTimeムービー化する小道具を作ってみましょう。‥‥これがあると、日頃何かと役に立ちますよ。

 作成の要点は以下の通り。

  • フォルダを処理する場合は、静止画連番を格納したフォルダとして処理する
  • ファイルを処理する場合は、静止画連番1枚目として処理する
  • 毎回、FPS(1秒あたりのフレーム数)を選択できる
  • 保存形式はQuickTime独立保存、QuickTimeデフォルト設定、AVI形式の3つから選択可能

 ‥‥とまあ、「小道具第2号」としては、ちょっと欲張った仕様にしてみます。


●フォルダとファイルの判別

 今回も前回同様、ドラッグ&ドロップのアプリケーション形式で作りますが、少し趣向を変えて「アプリケーションバンドル形式」で作ってみましょう。アプリケーションバンドル形式はとても柔軟かつ多機能なアプリケーションが作成できます。


 さて、まずフォルダとファイルの判別方法についてですが、その方法はいくらでもあります。今回は定番中の定番である「フォルダが存在するか」方式で判別してみます。

 まず基本事項。「フォルダかファイルか」を認識・管理している代表格は、「Finder」というMacOSXの「世話役」アプリケーションです。すなわち、フォルダかファイルかを判別するには、Finderに聞くのが手っ取り早いのです。前の小道具作りの「Image Events」の命令でも出てきましたが、ファイルを指定するには、以下のような指定方法をおこないます。

file ファイルのパス

 同じ様に、フォルダのパスも以下の様に指定できます。ちょっと注意点ですが、「フォルダ」はFinderが専門に扱いますので、必ずFinderに対して命令します。AppleScriptは、ドロップされた項目を「項目」としてしか認識していないので、それが「フォルダか否か」はFinderに尋ねる必要がある訳です。

tell application "Finder"
 folder フォルダのパス
end tell

 この指定方法を利用して、Finderに「存在の有無」を問い合わせます。存在の有無は「exists」を使って確認できます。

tell application "Finder"
 folder "MacHD:Folder001:" exists
end tell

 文面の意味は簡単、「フォルダ『MacHD:Folder001:』が存在する」‥‥です。存在する、と言い切った形で命令していますが、実際に存在すれかは話が別です。存在すれば「真」=true、存在しなければ「偽」=Falseが、Finderから返答として返ってきます。以下のテスト用スクリプトを使って、実際に「実行ボタン」をクリックして試してみましょう。

 実行ボタンをクリックすると、スクリプトエディタウィンドウの下半分に「false」と表示されました。つまり、「フォルダ『MacHD:Folder001:』が存在する」の問い合わせに対し、「偽」=false、すなわち「存在しない」という結果が返った訳です。

 この段取りを利用すれば、項目がフォルダか否かを確認できます。1つ1つの項目に対してフォルダか否かを問い合わせると言う至極平凡なルーチンですが、その至極平凡なルーチンがいくつも寄り集まると、とても複雑な処理をこなす事ができます。

 プログラムを敬遠している人は、その「至極平凡」な部分を知らないので、プログラムは「何から何まで」難解なものだと思い込んでしまうのです。‥‥んな訳、ありません。ごくごく平凡、日常生活で実際に使っているような解りきった手順で、静止画連番がムービーファイルに変換される様を、見ていきましょう!


●で、あるか?

 信長ぢゃないですよ。「もしも〜だったら」=if分岐の事です。

 今回の目的に合わせてif分岐を使うとしたら、「もしフォルダが存在したらルーチンA、でなければルーチンB」という使い方になります。「if〜then」が「もし〜ならば」を表現し、「else」が「そうでなければ」を表現しています。if分岐の終わりを明示するため、「end if」が書き込まれている点にも注目してください。

tell application "Finder"
 if folder "MacHD:Folder001:" exists then
  
 else
  
 end if
end tell

 QuickTimeの静止画連番読み込みは、連番の1番目のファイルを指定します。つまり連番ファイルを収納したフォルダならそのフォルダ内の1番目のファイルを指定し、ファイルの場合はそのファイルを1番目のファイルとして指定する方法を採る事になります。

on open DropItems
 repeat with DropItem in DropItems
  tell application "Finder"
   set itemPath to DropItem as Unicode text
   if folder itemPath exists then
    set FirstFrameFile to file 1 of folder itemPath
   else
    set FirstFrameFile to file itemPath
   end if
  end tell
 end repeat
end open

 興味深いのは、file 1 of folder itemPathの部分です。「フォルダitemPathのファイル1」をそっくりそのまま英文で表現している点は、AppleScriptの大変面白いところです。普段使っている文体=自然言語に近い命令文はAppleScriptの特徴の1つです。

 変数FirstFrameFileに連番開始ファイルをセットしました。次はいよいよ、QuickTimeを命令で動かします。


●QuickTime Playerを命令で動かす

 QuickTime PlayerはMacOSXユーザならずともご存知でしょう。QuickTimeムービーと呼ばれるムービー形式の再生をおこない、さらにはmpeg形式、AVI形式、3gpp形式などの様々な形式のムービーをも再生します。その他、MIDIファイル、AIFFファイル、WAVEファイルなどの音声ファイルの再生も可能、音声の録音や映像の録画まで可能と言う、まさに「マルチメディア」なアプリケーションです。アニメ業界など映像制作分野では「業界標準」となっており、作業のやり取りでは編集性の高いQuickTimeのロスレス圧縮によるファイルが頻繁に用いられます。

 QuickTime Playerは単にメディアの再生だけではなく、新規ファイルの書き出しも可能です。そして(ここからが重要)、そのQuickTime Playerに備わっている各種機能は、AppleScriptから命令を送って実行する事が可能です。つまり、先の小道具で「JPEG変換」を実現したのと同様、QuickTime Playerを用いる事で「QuickTime機能の自動処理」を実現できる訳です。

 では、本題。まず連番静止画をQuickTimeムービーとして開きましょう。「イメージシーケンス(連番静止画)で開くにはプロ版が必要でしょ?」と言う人は、QuickTime Playerの機能をよくご存知ですね。でも、実はプロ版ライセンスは不要です。AppleScriptから命令した場合は、スタンダード版でもプロ版の機能を使う事ができます。眠っているプロ版機能をAppleScriptで呼び覚ます‥‥と言ったところですネ。

 イメージシーケンスを開くには、以下の書式を用います。

open image sequence 連番1番目のファイル frames per second フレームレート

 解りやすい命令文ですね。ただし、この命令を実行するには、読んでの通り、事前にフレームレートを決める必要があります。もしフレームレートを24しか使わないのなら直に「24」と書いても良いのですが、折角ですから24,30の2つから選択する方法を組み込んでみましょう。2つから選択する‥‥と言う事は、使う人に24,30のどちらかから選択してもらう事になります。使用者に選択を即す為に、「choose from list」と言う便利な命令が、AppleScriptには備わっています。

choose from list {24,30}

 見慣れないカタチが出てきました。{}、波括弧です。この波括弧は「リスト」を命令文の中に表現する為に使います。「リスト」とはその名の通り、「何かを集めたモノ」=項目の集合体です。今回は24と30という数字のリストです。

 このchoose from list {24,30}を実行すると以下のような画面が出現します。

 この画面から24を選べば、{24}という「1項目だけのリスト」が返ります。30を選べば{30}が返ります。では、キャンセルを押したら? ‥‥偽、すなわち、falseが返ります。‥‥という事は、choose from list命令を用いるには、その結果がまず「false」かどうかを調べて、使用者がキャンセルしたか否かを確認します。もしキャンセルした場合は「そこで処理を止めたい」訳ですから、そのように命令文を書きます。処理を中途で停止するには「return」を書きます。

set res to choose from list {24, 30}
if res is false then return

 choose from listの結果を変数「res」にセットし、もしそのresがfalseだったらreturn=途中で返る=途中で停止するよう、命令を書きます。

 先ほど「24を選べば、{24}という『1項目だけのリスト』が返る」と書きました。つまり、{24,30}の中から使用者が選択した数字は、{24}と言うリストで返ってくるのです。しかし結果として欲しいのは{24}というリストではなく、24という数字です。どうしたらよいでしょうか?‥‥こうしましょう。

set fps to item 1 of res

 ぎゃふん‥‥て言う感じですね。なんて簡単なんでしょうか。res、すなわち24か30のどちらかを含んだ1項目のリストから、1番目の項目を変数fpsに入れれば、結果、数字が取得できます。「箱の中にある1番目の林檎が欲しいのなら、1番目の林檎が欲しいと要望を出す」‥‥当たり前すぎて、逆に戸惑ってしまいますね。

 フレームレート選択の段取りを整理して書くと、以下の様になります。

set res to choose from list {24, 30}
if res is false then return
set fps to item 1 of res

 フレームレートも確定し、イメージシーケンスを開く準備が整いました。早速「open image sequence」命令を組み込みましょう。

on open DropItems
 repeat with DropItem in DropItems
  tell application "Finder"
   set itemPath to DropItem as Unicode text
   if folder itemPath exists then
    set FirstFrameFile to file 1 of folder itemPath
   else
    set FirstFrameFile to file itemPath
   end if
  end tell
  set res to choose from list {24, 30}
  if res is false then return
  set fps to item 1 of res
  tell application "QuickTime Player"
   open image sequence FirstFrameFile frames per second fps
  end tell
 end repeat
end open

 ちょっとテストしてみましょう。連番を格納したフォルダをアプリケーションにドロップしてみます。

このフォルダには以下のような連番が入っています

フォルダごと、アプリケーションアイコンにドロップ!

今回は「24」を選択!



 あれれ? 何かエラーが出ました。

Finder でエラーが起きました:document file "inu_jpg_0001.jpg" of folder "inu_jpg" of folder "MiscPictures" of disk "HD3" は «event MVWRopis» メッセージを認識できません。

 なぜでしょうか?‥‥QuickTime Playerのバグでしょうか? いえいえ、そんな事はありません。命令がうまくいってないだけです。良く文面を見てみましょう。「«event MVWRopis» メッセージ」とは恐らく「open image sequence」命令の事でしょうから、その命令が「document file」を認識できないと言う事が、エラーメッセージから読み取れます。

 でも、「open image sequence」命令は1番目のファイルを指定する事で命令実行するはずです。何がいけないのでしょうか。

 答えはズバリ、「document file」だからです。QuickTime Playerは「file」は認識しますが、「document file」は認識しない‥‥と言う事です。何か、お役所仕事みたいですが、ぶっちゃけた話、そう言う事です。以下のような問答は、現実世界でも目にしますよね?

来訪者:「環境保全課はありますか?」

受付:「環境保全課はございません。」

来訪者:「では、環境課はありますか?」

受付:「環境課はございます。」

 似ているようでも、呼び名が違えば通用しない。‥‥そんな事は日々の生活でも良くある事です。ではどうするのか?‥‥答えは簡単、上記の問答のように「言い直せば良い」のです。QuickTime Playerは「file」なら認識します。と言う事は、QuickTime Playerへの命令内で「document file」から「file」へ言い換えれば良いのです。「file」の言い表し方は「JPEG変換」の小道具でも解説した通り、「file 項目のパス」です。

on open DropItems
 repeat with DropItem in DropItems
  tell application "Finder"
   set itemPath to DropItem as Unicode text
   if folder itemPath exists then
    set FirstFrameFile to file 1 of folder itemPath
   else
    set FirstFrameFile to file itemPath
   end if
  end tell
  set res to choose from list {24, 30}
  if res is false then return
  set fps to item 1 of res
  tell application "QuickTime Player"
   open image sequence file (FirstFrameFile as Unicode text) frames per second fps
  end tell
 end repeat
end open

 では再度チャレンジ。気を取り直して、連番のフォルダをドロップしてみます。‥‥で、新規に出来上がったのが、下のムービーです。ちゃんと連番ファイルがムービーファイルとして読み込まれています。

 うーん、思惑どおり!! (場合によっては再生が追いつかずコマ落ちしますが)ちゃんと1秒間24フレームで読み込まれています。QuickTime Playerの「ムービー情報」パレットで確認しましょう。

 ‥‥でも喜ぶのはまだ早いです。現状では、イメージシーケンスを開いただけで、保存は一切していません。保存しなければ消えてしまいます。

 それならば、続けて、保存命令を書きましょう。


●ムービーの保存、もしくは書き出し

 まず、保存するには保存先の特定、これが定石です。早速「ムービーの保存先の指定」も命令文に組み込みましょう。今回は保存先のフォルダを使用者に選択してもらう趣向でいってみます。フォルダ選択を使用者に即すには、「choose folder」命令を使います。後の行程での使い勝手を考えて、選択と同時にパスに変換しておきましょう。

set SaveFolderPath to (choose folder) as unicode text

 さて、ムービ−の保存ですが、「保存」とひとくちに言っても色々種類があります。QuickTimeに詳しい方ならば、保存方法や書き出し方法にいくつも種類がある事を知っている事でしょう。保存形式を固定してしまっても良いですが、折角色々書き出せるのですから、イメージシーケンスをどのような形式で保存するのか使用者に選択してもらう事にしましょう。コツはフレームレートの時と同じです。結果をセットする変数名は「movieType」という名前にしました。

set movieType to choose from list {"QuickTime独立保存形式","QuickTimeデフォルト設定","AVIムービー形式"}
if movieType is false then return

 選択結果がfalseの場合に途中停止するのは前と同じですが、今度は選択結果によってQuickTime上の保存処理を変えるよう、命令文を書きます。「choose from list」命令から返ってくる結果はリストですので、その点に注意しつつ命令文を「素組み」します。

if movieType is {"QuickTime独立保存形式"} then

else if movieType is {"QuickTimeデフォルト設定"} then

else if movieType is {"AVIムービー形式"} then

end if

 なんとまあ、明快なルーチン。「はじめてのお使い」のような、けなげなルーチンですね。

 まず、「QuickTime独立保存形式」の場合から作っていきましょう。「QuickTime独立保存形式」で保存するには、「save self contained」命令を使います。保存命令は「QuickTime Playerで開いているどのムービーを保存するのか」命令します。つまりファイルやフォルダから保存するのではなく、ムービーというQuickTime Player独自の項目から保存、すなわちファイルに書き出します。

 先ほど開いたムービーをどうやって言い表すのか?‥‥「JPEG変換」の時を思い出して、応用すれば良いのですよ。つまり、「open image sequence」命令の結果を変数にセットしてそれを使い回せば良いのです。

set myMovie to open image sequence FirstFrameFile frames per second fps

 これにより、開いたイメージシーケンスは変数「myMovie」で扱える事になりました。保存命令で早速使いましょう。

save self contained myMovie

 何か、足りないですよね。‥‥保存先です。では先ほどの保存先フォルダのパスを‥‥‥と早合点せずに、よく考えてみましょう。先の命令で保存先のフォルダは指定しましたが、保存するファイル名は指定していません。つまり保存しようとするファイルのパスが完成していないのです。これでは、保存はうまくいきません。まず、ファイル名を確定する段取りですが、今回も名前+拡張子でいきましょう。

tell application "Finder" to set newName to (name of DropItem) & ".mov"

 変数newNameにオリジナル項目名+拡張子がセットされました。後は、保存先フォルダのパスと合体させて完成です。

save self contained myMovie in file (SaveFolderPath&newName)

 これで「QuickTime独立保存形式」の保存命令は終了です。どんどん次に行きましょう。

 2番目の保存形式「QuickTimeデフォルト設定」は書き出し命令「export」を使います。「デフォルト設定」で書き出しますので、「using default settings」というオプションも書き加えます。

export myMovie as QuickTime movie using default settings to file (SaveFolderPath & newName)

 2番目は終了。最後の3番目、「AVIムービー形式」も同じ要領で命令文を書きます。

export myMovie as AVI using default settings to file (SaveFolderPath & newName)

 ちょっと待った! AVIファイルの拡張子は「.avi」です。現状では「.mov」になっています。これではマズいですね。ifの条件分岐の際にAVIファイルの場合は拡張子を「.avi」にするように変更しましょう。

tell application "Finder" to set newName to (name of DropItem) & ".avi"

 最後にmyMovieを閉じて終わります。閉じないと、どんどん開いているムービーが増えていきますからね! 「saving no」としているのは、既に前の命令で書き出しが済んでいるので、ムービーを閉じる時にわざわざ保存する必要がないからです。

close myMovie saving no

 さて、説明の為に命令文の前後が混乱してきましたので、ここで一度、命令文全文を清書してみましょう。

on open DropItems
 repeat with DropItem in DropItems
  tell application "Finder"
   set itemPath to DropItem as Unicode text
   if folder itemPath exists then
    set FirstFrameFile to file 1 of folder itemPath
   else
    set FirstFrameFile to file itemPath
   end if
  end tell
  set res to choose from list {24, 30}
  if res is false then return
  set fps to item 1 of res
  set SaveFolderPath to (choose folder) as Unicode text
  set movieType to choose from list {"QuickTime独立保存形式", "QuickTimeデフォルト設定", "AVIムービー形式"}
  if movieType is false then return
  tell application "QuickTime Player"
   set myMovie to open image sequence file (FirstFrameFile as Unicode text) frames per second fps
   if movieType is {"QuickTime独立保存形式"} then
    tell application "Finder" to set newName to (name of DropItem) & ".mov"
    save self contained myMovie in file (SaveFolderPath & newName)
   else if movieType is {"QuickTimeデフォルト設定"} then
    tell application "Finder" to set newName to (name of DropItem) & ".mov"
    export myMovie as QuickTime movie using default settings to file (SaveFolderPath & newName)
   else if movieType is {"AVIムービー形式"} then
    tell application "Finder" to set newName to (name of DropItem) & ".avi"
    export myMovie as AVI using default settings to file (SaveFolderPath & newName)
   end if
   close myMovie saving no
  end tell
 end repeat
end open

 上手く出来た! これで連番静止画のムービー化もバッチリ!

 しかし、喜ぶのは時期尚早です。「コンパイル」をうまく通過しても、実行テストの結果を見るまでは「本当にうまくいっているか」は解りません。‥‥実は出来上がったこの小道具には「致命的な欠陥」がある事を、次の項でおこなう「実行テスト」で痛感する事になります。



→連番ファイルをムービーファイルに変換する小道具(2)


					

INDEX


IntegerQ INDEX
h.ezura / afx / ezqnet