昨日までの内容は、以下から。
さて、HTTPの動画はダウンロード出来たので、次はRTMPの動画のダウンロード。
gem探し
RTMPのプロトコルを読み込んで実装するのはさすがに難しいので、RTMPを扱えるgemを検索。
しかし・・・見つからない!
厳密に言えば、それっぽいgemはいくつか見つかるのだけど、RTMPへの不理解もあって、どのgemを使えばいいのかがよく分からない。
これは困った・・・
rtmpdump
仕方ないので、ちょっと切り口を変えて、RTMPで配信されている動画をダウンロードする方法やツールがないか調べてみたところ、次の情報を発見。
ニコニコ公式アニメポータルのrtmpeプロトコル動画をダウンロードする覚え書き · GitHub
ふむふむ。
rtmpdumpとな。
とりあえずこれを使ってみよう。
インストール
まずはrtmpdumpのインストール。
自分の場合、Macで開発環境(Xcode)も入ってるので、ソースをダウンロード。
Unix系のOSなら同じ方法で大丈夫なはず。
(Windowsの場合は知らない・・・)
$ git clone git://git.ffmpeg.org/rtmpdump $ cd rtmpdump/
そのあと、ビルドとインストール。
詳細はREADME参照だけど、SYS=platform_nameとしてmakeを行う。
platform_nameは、Macなら"darwin"、Unix系ならposix、WindowsでMinGWを使っているならmingwとのこと。
自分の場合は、
$ make SYS=darwin $ sudo make install SYS=darwin
で、ビルドとインストールが出来た。
プログラムの修正
次に、先ほどの情報を元に、プログラムを修正していく。
動画の実際のURLの他に、いくつか情報が必要なようなので、これらをvideo_infoというHashに保存するようにする。
-video_uri = nil +video_info = nil begin info = CGI.parse(response.body) video_url = info['url'].first video_uri = URI.parse(video_url) + + if video_uri.scheme == "http" + video_info = {"uri" => video_uri} + else + fmst2, fmst1 = info['fmst'].first.split(':') + video_info = {"uri" => video_uri, + "original_uri" => URI::HTTP.build(host: VideoHost, path: video_path), + "fmst1" => fmst1, "fmst2" => fmst2} + end rescue raise "Failed to access video information." end
これに合わせて、何箇所か修正。
# set output filename video_extension = ".flv" -if match_data = VideoTypeRegexp.match(video_uri.to_s) +if match_data = VideoTypeRegexp.match(video_info["uri"].to_s) if match_data[1] == "s" video_extension = ".swf"
-http = Net::HTTP.new(video_uri.host) -http.request_get(video_uri.request_uri, - {'Cookie' => "user_session=#{user_session}; nicohistory=#{nicohistory};"}) do |response| - File.open(output_filename, "wb") do |file| - response.read_body do |video_block| - file.write(video_block) +if video_info["uri"].scheme == "http" + http = Net::HTTP.new(video_uri.host) + http.request_get(video_info["uri"].request_uri, + {'Cookie' => "user_session=#{user_session}; nicohistory=#{nicohistory};"}) do |response| + File.open(output_filename, "wb") do |file| + response.read_body do |video_block| + file.write(video_block) + end end end +else + # ここのRTMPで配信されている動画の + # ダウンロードのコード + # ... +end
そして、肝心のRTMPで配信されている動画のダウンロードは、以下のような感じ。
original_uri = video_info["original_uri"] uri = video_info["uri"] uri_without_query = URI::Generic.build(scheme: uri.scheme, host: uri.host, path: uri.path) playpath = uri.query.split('=')[1] fmst1 = video_info["fmst1"] fmst2 = video_info["fmst2"] done = false until done done = system <<END_OF_COMMAND rtmpdump \\ -e \\ -l 2 \\ -a smile \\ -n #{uri.host} \\ -t #{uri_without_query.to_s} \\ -p #{original_uri.to_s} \\ -s http://res.nimg.jp/swf/player/secure_nccreator.swf?t=201111091500 \\ -f "WIN 11,6,602,180" \\ -y #{playpath} \\ -C S:#{fmst1} \\ -C S:#{fmst2} \\ -C S:#{playpath} \\ -o #{output_filename} END_OF_COMMAND end
なお、ループで回しているのは、なぜか1回のダウンロードでダウンロードしきれないから。
-eオプションをつけることで、ダウンロードが中断した箇所からダウンロードが再開されるようになっている。
これで、なんかエラーやらワーニングとかは出ているものの、ダウンロード自体は問題なく出来るようになった。
不要なオプションの削除など
ただ、-sとか-fとかに渡してる値は、参照したページのもので、どうにも怪しげ。
ということで、削除出来るなら削除したいし、もし必要だとしたら正しい値を設定したい。
そんな感じでコマンドラインオプションを修正したあとのコードは、以下。
これでHTTPで配信されている動画もRTMPで配信されている動画もダウンロード出来るようになった。
今日はここまで!