2009-02-15

YouTube動画をSLで - Yahoo Pipes 2

さて、前回のpipeをもうちょっと工夫してみましょう。

動画の品質を指定するには、
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」を参考にしています。

1 件のコメント:

Unknown さんのコメント...

はじめまして。
http://www.youtubemp4.com/ のサイトの動作が不安定なので、色々と他のURLの変換方法を探していたら、たどり着きました。

試したのですが、動画が再生されませんでした。

YouTubeの仕様変更があったそうですが、その影響でしょうか?

このフォーマットに変ったそうですが・・・
http://www.youtube.com/get_video?video_id=ビデオID&t=トークン&noflv=1