QuickTime Player と AppleScript

Snow Leopard で QuickTime Player が一新されました。どんなものなのかと思っていましたが...、まだまだ QuickTime Player 7 は必要ですね。そんな QuickTime Player ですが、AppleScript の対応度はどれほどのものなのか。ちょっと、調べてみました。

まず、一通りの操作は AppleScript で行えるようです。以前の QuickTime Player は Pro にすると、編集機能や書き出し機能が利用できるようになりました。これらの機能は Pro 版を購入しなくても AppleScript から利用できることはよく知られていました。

Snow Leopard の QuickTime Player は、Pro といったものがなく、最初から全機能を利用できるようになっています。フルスクリーン再生や画面収録、ビデオ収録、オーディオ収録、不要な部分を切り取るトリムなどの機能が最初から利用可能なのですが、以前の QuickTime Player Pro に比べると、かなり貧弱な機能しか利用できません。

例えば、参照ムービーで保存することはできません。トラックを個別に扱うこともできないですし、テキストトラックの追加もできません。「Web 用に保存...」というメニューで保存を行うと参照ムービーが保存されるのですが、これを開くのは QuickTime Player Launcher というアプリケーションで、参照ムービーを開くと自動的に QuickTime Player 7 が起動されるようになっています。つまり、取り扱えないのですね。

ポスターフレームを設定することもできませんし、書き出しといってもあらかじめ設定された書き出ししか行えません。以前のように細かい設定はできないようになっています。どちらかというと不要な機能を取り除き、シンプルになったという方がいいかもしれません。細かい設定を行いたい場合は iMovie 09 か QuickTime Player 7 を使うしかありません。

同じように AppleScript から扱える機能もシンプルです。

document クラスでいえば、ムービーの時間に関連する current time や duration といった属性が秒数を返すようになっています。秒数で結果が返るので、time scale 属性はなくなっています。duration 属性だけで再生時間が取得できるのは手軽でいいのですが、タイムコードを作るときはどうすればいいのでしょう?

System Events を使うと取得することはできますが。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    if not (exists front document) then return

    set the_file to file of front document
    set time_scale to my get_timescale(the_file)
    set selection_start to current time of front document

    set current_time to (selection_start * time_scale) as integer
    set movie_length to ((duration of front document) * time_scale) as integer
    set movie_length to my make_timecode(movie_length, time_scale)
    set timecode_text to my make_timecode(current_time, time_scale)
    set file_name to name of front document
    activate

    display dialog (file_name & return & return & "Length: " & movie_length & return & "Current Time: " & timecode_text) as text with icon 1 buttons {"Clipboard", "OK"} default button 2
    if (button returned of result) is "Clipboard" then
        set the clipboard to timecode_text
    end if
end tell

on make_timecode(current_time, time_scale)
    set total_seconds to current_time div time_scale
    set partial_seconds to current_time mod time_scale
    set h to total_seconds div hours
    set hh to my add_zero(h, 2)
    set m to (total_seconds - (h * hours)) div minutes
    set mm to my add_zero(m, 2)
    set s to (total_seconds - (m * minutes)) div 1
    set ss to my add_zero(s, 2)
    set partial_seconds to my add_zero(partial_seconds, 3)
    set AppleScript's text item delimiters to ":"
    set timecode_text to {hh, mm, ss} as text
    set AppleScript's text item delimiters to {""}
    set timecode_text to timecode_text & "." & partial_seconds
    return ("[" & timecode_text & "]") as text
end make_timecode

on add_zero(int, digit)
    set this_number to int as text
    set n to count this_number
    if n is digit then
        return this_number
    else
        set zero_count to digit - n
        repeat zero_count times
            set this_number to "0" & this_number
        end repeat
        return this_number
    end if
end add_zero

on get_timescale(this_file)
    if (class of this_file) is in {«class furl», file, alias} then
        set this_file to POSIX path of this_file
    end if

    tell application id "com.apple.systemevents"
        tell QuickTime file this_file
            return time scale
        end tell
    end tell
end get_timescale

でも、これって秒数を返すのですからわざわざ time scale を調べなくてもいいような気がします。

選択した範囲内を切り取る trim 命令は秒数で指定するようになっています。しかし、すべてが秒数指定かというとそうではなく、ムービーの再生場所を少しずつ移動させる step forward や step backward 命令はフレーム単位のままです。

step forward や step backward 命令がフレーム単位なら、全体のフレーム数を数えることもできますね。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    if not (front document exists) then return

    tell front document
        set current_time to current time
        set current time to 0
        step forward -- 1 フレーム動かす
        set frame_length to current time
        set current time to current_time

        -- 全体の秒数を 1 フレームの秒数で乗算(総フレーム数)
        set frame_count to duration / frame_length
        -- 1(秒)を 1 フレームの秒数で乗算(fps)
        set fps to 1.0 / frame_length
        set movie_name to name of it
        set msg to name of it & return & return
        set msg to msg & "1 frame seconds: " & (frame_length as text) & return
        set msg to msg & "Frame count: " & (frame_count as text) & return
        set msg to msg & "FPS: " & (fps as text)

        activate
        display dialog msg with icon 1
    end tell
end tell

一応このような計算で総フレーム数や FPS を算出できますが、必ずしも正確ではありません(例えば、画面収録やムービー収録で保存したムービーでは正確な数値を出せない)。正確さを求めるなら、QuickTime Player 7 を使う方がいいです。参考までに QuickTime Player 7 で行った場合を。

Script Editor で開く

tell application id "com.apple.quicktimeplayer"
    if not (front document exists) then return

    tell front document
        set video_track to tracks whose type is "vide"
        set video_track to item 1 of video_track

        set time_scale to time scale
        set movie_length to duration
        set frame_count to count (frames of video_track)

        set num to frame_count * time_scale
        set fps to num / movie_length

        {frame_count, fps}
    end tell
end tell

copy 命令がないのも痛いですね。現在の選択範囲を画像として書き出す...そういうこともできません。そもそも、選択範囲を作り出すことができないですし。当然、ビデオトラックの左右反転や上下反転もできないですし、歪ませることもできません。開かれているすべてのムービーを連結する...そういうこともできません。こうやって見ていると、できないことの方が多いです。できることを並べていった方が早いかな?

では、ムービーのフルスクリーン再生。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    if not (front document exists) then return

    tell front document
        present
        play
    end tell
end tell

present 命令は、以前はいろいろとオプションを指定できましたが、そういう指定はできなくなっています。

次のスクリプトは 10 フレーム先に進むスクリプト。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    if not (front document exists) then return

    tell front document
        if playing then
            stop
        end if

        step forward by 10
    end tell
end tell

step forward を back forward にすれば 10 フレーム戻ります。ムービーの再生速度を変更させるには document クラスの rate 属性を 変更します。2 倍速にするには以下のようにします。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    if not (front document exists) then return

    tell front document
        if playing then
            stop
        else
            set rate to 2.0
        end if
    end tell
end tell

rate 属性にはあり得ない値を設定することもできます。例えば、10000 倍速とか。すごいのは QuickTime Player 7 なら落ちてしまっていた、こういうあり得ない数値でもスムーズに再生し、安定していることです。もっとも、目には何も映りませんが。逆方向に倍速再生したいなら、負の値を rate 属性に設定します。スロー再生したいときは、-1.0 から 1.0 までの値...例えば、0.5 や -0.5 などを設定します。

新しい QuickTime Player は AppleScript から書き出すときでも複数のファイルを並行して書き出すことができます。この辺りが唯一のいいところかもしれません。書き出しの設定は決められたものしか使えませんが。save 命令は同じものを別名で保存するのに利用できます。

書き出しには export 命令を使います。次のスクリプトでは前面のムービーを指定されたフォーマット(複数指定可)で書き出します。

Script Editor で開く

property export_presets : {"Apple TV", "Computer", "iPhone (Cellular)", "iPhone", "iPod", "HD 480p", "HD 720p", "HD 1080p"}
property file_extensions : {".m4v", ".m4v", ".3gp", ".m4v", ".m4v", ".mov", ".mov", ".mov"}

tell application id "com.apple.QuickTimePlayerX"
    activate
    if not (front document exists) then return
    set file_name to name of front document
    set file_path to (file of front document) as text as alias
    set save_folder to my parent_folder(file_path) as text

    set {file_name, ext} to my splitext(file_name)

    set using_presets to choose from list export_presets default items (item 1 of export_presets) with multiple selections allowed
    if using_presets is false then return

    set export_settings to {}
    repeat with i from 1 to count using_presets
        set this_preset to item i of using_presets
        repeat with j from 1 to count export_presets
            if (item j of export_presets) is this_preset then
                set end of export_settings to {item j of export_presets, item j of file_extensions}
            end if
        end repeat
    end repeat

    repeat with this_preset in export_settings
        set {preset_name, ext} to contents of this_preset
        set out_file to save_folder & file_name & " - " & preset_name & ext
        export front document in file out_file using settings preset preset_name
    end repeat
end tell

on splitext(file_name)
    set reversed_name to (reverse of (characters of file_name)) as text
    set num to offset of "." in reversed_name
    if num is 0 then
        set ext to ""
    else
        set reversed_ext to text 1 thru num of reversed_name
        set ext to (reverse of (characters of reversed_ext)) as text
        set ext_num to count ext
        set name_length to count file_name
        set file_name to text 1 thru (name_length - ext_num) of file_name
    end if
    return {file_name, ext}
end splitext

on parent_folder(the_file)
    tell application "Finder" to return container of the_file as alias
end parent_folder

書き出しに利用できるプリセットですが、「コンピュータ」、「Apple TV」、「iPod」、「iPhone」、「iPhone (Cellular)」、「HD 480p」、「HD 720p」、「HD 1080p」だけです。それぞれ、英語で正確に指定します。これらの設定がどこにあるかというと、QuickTime Player のパッケージ内の Resources フォルダにあります。それぞれ、Apple TV.plist といった設定の名前でプロパティリストファイルで保存されています。

このプロパティリストを真似して他の設定を追加することも可能だと思うのですが...。ちょっと、怖くてまだ手を出していません。もし、やってみようと思うなら自己責任でお願いします。

trim 命令は選択範囲を切り取る命令です。秒数で範囲を指定し、その範囲を切り出します。以下のスクリプトはムービーを均一の長さ(ここでは 10 分単位)に分割して保存します。

Script Editor で開く

property split_length : minutes * 10

tell application id "com.apple.QuickTimePlayerX"
    if not (front document exists) then return

    tell front document
        set file_name to name of it
        set file_path to (file of it) as text as alias
        set save_folder to my parent_folder(file_path) as text
        set {file_name, ext} to my splitext(file_name)
        set movie_length to duration

        if movie_length < split_length then return

        set split_count to movie_length div split_length
        set rest_length to movie_length mod split_length

        set length_list to {}
        repeat with i from 1 to (split_count * split_length) by split_length
            set end of length_list to {(i - 1), i + split_length - 1}
        end repeat
        if rest_length is not 0 then set end of length_list to {movie_length - rest_length, movie_length}

        repeat with i from 1 to count length_list
            set {start_time, end_time} to item i of length_list
            set out_file to save_folder & file_name & "_" & (i as text) & ext
            trim from start_time to end_time
            save it in file out_file
            close it saving no
            open file_path
        end repeat
    end tell
end tell

on splitext(file_name)
    set reversed_name to (reverse of (characters of file_name)) as text
    set num to offset of "." in reversed_name
    if num is 0 then
        set ext to ""
    else
        set reversed_ext to text 1 thru num of reversed_name
        set ext to (reverse of (characters of reversed_ext)) as text
        set ext_num to count ext
        set name_length to count file_name
        set file_name to text 1 thru (name_length - ext_num) of file_name
    end if
    return {file_name, ext}
end splitext

on parent_folder(the_file)
    tell application "Finder" to return container of the_file as alias
end parent_folder

0 から 10 分、10 分から 20 分 というようにわざと最初と最後の一秒をかぶらせています。新しいドキュメントを作ってそこにコピーする...といった操作ができないので、オリジナルのファイルから範囲を切り取ったら保存せずに閉じ、またオリジナルのファイルを開く...といったことを繰り返しています。何となく、見栄えが悪いな。

最後に画面収録、オーディオ収録、ビデオ収録について。これらも AppleSciprt から利用することができます。document クラスにはこれらに関する属性、current microphone(音声を録音するのに利用するマイク), current camera(ビデオを録画するのに利用するカメラ), current audio compression(音声の圧縮設定), current movie compression(ビデオの圧縮設定), current screen compression(画面収録の圧縮設定)) があります。

これらの属性は新規に作成した画面収録、オーディオ収録、ビデオ収録、いずれかがないと利用できません。どのような設定や入力源が利用できるかは以下のようにして調べることができます。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    audio recording devices -- 音声入力源一覧
    video recording devices -- ビデオ入力源一覧

    audio compression presets -- 音声収録圧縮設定の一覧
    movie compression presets -- ビデオ収録圧縮設定の一覧
    screen compression presets -- 画面収録圧縮設定の一覧
end tell

これらは application クラスの要素なので、tell document 1 などとしている中では利用できません。また、新規に作成した画面収録、オーディオ収録、ビデオ収録などの属性を実際に変更するには a reference to 演算子を使って参照にしておく必要があります。

新規にオーディオ収録を作成し、オーディオの入力源を変更するには以下のようにします。

Script Editor で開く

tell application id "com.apple.QuickTimePlayerX"
    activate
    set device_names to name of audio recording devices -- 音声入力源一覧
    set using_device to choose from list device_names
    if using_device is false then return

    -- 参照に
    set using_device to a reference to (audio recording device (using_device as text))

    close documents saving no

    set audio_recording to new audio recording
    set current microphone of audio_recording to using_device
end tell

途中で開かれているすべてのムービーを閉じているのは、画面収録、オーディオ収録、ビデオ収録は一度に一つしか作成することができないからです。画面収録をしながらオーディオ収録(またはビデオ収録)ということはできるのですが(QuickTime Player の隠し設定でできるようになったような...)、どのムービーがどの収録を行っているムービーなのかといったことは AppleScript から調べることができません。これも QuickTime Player 7 だと調べることができるのですが。そのため、エラーを回避するためにすべて閉じています。

start 命令で収録の開始が行えます。pause 命令で収録の一時停止ができますが、画面収録では利用することはできません。pause 命令で一時停止している収録は、resume 命令で再会することができます。stop 命令で収録を終了することができます。

これぐらいでしょうか。AppleScript で制御できるのは。QuickTime Player 7 だととてもこの分量でまとめきれないのですが。嬉しいような、悲しいような。

QuickTime Player の AppleScript をまとめたものをおいておきます。基本的にはすべて ~/Library/Scripts/Applications/QuickTime Player に置いて、スクリプトメニューからの利用を想定していますが、使いやすいようにご利用ください。Automator の「AppleScript を実行」アクションを使ってサービスメニューにするのもいいかもしれません。いつものことですが、ご利用はご自身の責任でお願いします。

0 件のコメント :

コメントを投稿