動画の品質を指定するには、
http://www.youtube.com/get_video?video_id={動画ID}&t={動画識別コード}&fmt={出力形式}
の、「fmt={出力形式}」の部分を変えるだけで実現できます。指定値は前々回に書いた通り、
- fmt=18...MP4 H.264/AAC stereo
- fmt=17...MP4 MPEG-4/AAC mono (モバイル)
- fmt=22...MP4, H.264/AAC stereo (HD)
です。
ですから、「http://www.youtube.com/get_video?video_id={動画ID}&t={動画識別コード}」の部分までをPipeで作成・出力し、「&fmt={出力形式}」の部分をSL内でユーザに指定させて、LSLで
http://www.youtube.com/get_video?video_id={動画ID}&t={動画識別コード}&fmt={出力形式}
という処理形態にするのが自然かと思います。
特にhttp_responseイベントで取得できるデータ長さは2Kbyteという制限があるので、短いに越したことはありません。
(pipe側も複雑になると動かなくなることがあります)
そこを改良したpipeがこちら。
movie formatのInput Numberモジュールを削除し、最後のLoopモジュール内のString Builderモジュールから"fmt="、"text"の2項目を削除するだけです。
後は受け取ったLSL側のllParcelMediaCommandList()関数に指定するURLに"fmt=xx"を付加するようにします。
これでfmt=18とfmt=17の対応は終わりです。
前々回も書きましたが、どのYouTube動画でもこのfmt=18とfmt=17は有効です。
ただしYouTube動画で「高画質」が用意されていない場合、fmt=18がきちんと「MP4 H.264/AAC stereo」になるかどうかはチェックしてません。でも再生時にvideoとして認識されない、ということはありませんので安心してください。
- - - - - - - - - - - - - - - - - - - - - - - - - - -
ただし、fmt=22(HD)の場合は元動画がHDでないと有効になりません(SL内でMedia URLにセットしてもvideoとして認識されません)。その動画がHDかどうか、YouTube URLを指定する前に事前にどこかでチェックしないといけないのです。
この「HDかどうか」をYouTubeページを参照する前に確認する方法はないのでしょうか。
実はあります。
参考:「Youtube でHD動画に対応しているか確認する裏技見つけた」
前回の「動画識別コード」を取得するために参照した部分、ここにその情報も含まれています。
この「fmt_map」の値の先頭が"22"であるならば、その動画はHD動画です。
ちなみに「高品質」がない動画の場合は
「高品質」がある場合(でHDがない場合)は
のようです。
(判定する必要はないですが)
"pipeで「HDかどうか」をLSLに返して、LSL側で出力形式を指定し再生用URLを組み立てる"
という処理形態にのっとってpipesとLSLを変更します。
そこで
という感じにしてみます。
●pipe
右側のモジュールで「YouTube video URL (url)」とその下の「String Regex」についての説明はいままでと同じですので省きます。
右側3番目の「Item Builder」モジュールで、取得したYouTube IDを基に、itemを作成します。
左側のモジュールの一番上、「Fetch Page」もいままでと同様です。
左2番めの「Filter」モジュールで、取得してきたHTMLソースから"fmt_map=xxxx"と"t=xxx"の部分をitemとして取り出し(permit)ます。
上から3番目の「Filter」ですが、ごくたまに"dtst=xxxx"というitemが取得できることがあります。ほんとにたまーにで、毎回ではないようなので何かYouTube側で機能を盛り込み途中なのかもしれません。とりあえず今は必要ないので、運悪く取得できてしまった時のために"dtst=xxx"のitemは取り除き(block)ます。
次の「Rename」モジュール以降で、itemの体裁を整えます。
整えるために、新たにvideo.titleとvideo.descriptionという属性を、とりあえずitem.contentの値で追加します。
「Sub-element」モジュールで、video.titleとvideo.description属性のみを取り出します。取り出したのでそれぞれ、item.title、item.descriptionという属性になります。
次の「Regex」モジュール。item.titleとitem.descriptionには、"fmt_map=xxx"もしくは"t=xxx"が入っています。
item.titleの値が"fmt_map="で始まっていたら、item.titleには"fmt"を、"t="で始まっていたら"t"をセットします。
また、item.descriptionの値が"fmt_map="で始まっていたらその後ろの値を、"t="の場合もその後ろの相対をitem.descriptionにセットします。
右側下の「Union」モジュールで、先程作成したYouTube IDの入ったitemと、左モジュールで取得してきたfmtとtのitemを結合して出力します。
出力結果(CSV形式)はこうなります。
LSL側は…長いので別ページに用意しました。コピペし、適当なobjectに詰めてお使いください。
[2009-02-17追記]
HTTPリクエストからhttp_response待ちの間、正式に作成するならばタイマーを張って応答タイムアウトを取るのがベストかと思います。どこかでなんらかのエラーが発生した場合、このままだと永遠に(スクリプト・リセットをしない限り)処理が止まります。
ちなみに、http_responseのstatusについては「Studying HTTP」の「HTTP Status Code」を参考にしています。