ustreamの録画flvデータのURLを得るスクリプト
Clouder::Blogger: ustreamの録画した動画のflvをダウンロードする方法
これは想像ですが、swf内でhttp://gw.ustream.tv/gateway.phpをPOSTしているのはわかっているので、そこで取得しているのか、もしくはJavaScriptでAjaxをつかってどこかから取得しているのか、といったところだと思いますが、いずれにしてももう少し解析が必要です。
とあるのをみて、gateway.php を調べてみました。
これはFlashのAMFのRPCサーバーで、録画されたものを再生するときには client.watch_video
という関数を呼んでいるようです。
as3で書くと
package {
import flash.display.*;
import flash.net.*;
public class gw extends Sprite {
public function gw() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var cid:String = stage.loaderInfo.parameters["cid"];
if (cid) {
var nc:NetConnection = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF0;
nc.connect("http://gw.ustream.tv/gateway.php");
nc.call("client.watch_video", new Responder(gatewayHandler), { cid: cid });
}
}
private function gatewayHandler(res:Object):void {
for (var i:String in res) {
log(i+": "+res[i]);
}
}
}
}
こんな感じになります。cid は再生URL http://ustream.tv/recorded/RLdKCmCouWOpkkEznZH4QA
とかの RLdKCmCouWOpkkEznZH4QA
部分です。
これをperlで呼ぶにはどうしたらいいか! ということでがんばってみました。
CPANにこのAPIのサーバー側の実装 (AMF::Perl) があったのでそれを適当に読んだり、実際API呼んでるときのパケットと見比べたりしつつして以下のようにすればできました。
#!/usr/bin/env perl
use strict;
use warnings;
use AMF::Perl;
use LWP::UserAgent;
my $cid = shift || '5Fq8cQp9eHsEEknbQ22OOZniqS2xUiuz';
my $amf = AMF::Perl::Util::Object->new;
$amf->addBody('client.watch_video', '/1', { cid => $cid });
my $outputstream = AMF::Perl::IO::OutputStream->new;
my $serializer = AMF::Perl::IO::Serializer->new($outputstream, 'utf-8');
$serializer->serialize($amf);
my $amfdata = $outputstream->flush;
$amfdata =~ s/\xff\xff\xff\xff/\0\0\0\x31\x0a\0\0\0\x01/;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new( POST => 'http://gw.ustream.tv/gateway.php' );
$req->content( $output );
$req->content_type('application/x-amf');
$req->content_length( length $amfdata );
my $res = $ua->request($req);
my $deserializer = AMF::Perl::IO::Deserializer->new(AMF::Perl::IO::InputStream->new($res->content), 'utf-8');
use YAML;
print Dump $deserializer->getObject->getBodyAt(0)->{value};
これで
---
err_desc: ok
server_id: 9
success: 1
user_id: 32983
video_length: 366.207
video_name: broadcast/35957/1191239239348
video_type: broadcast
とかいう出力がでます。これから
http://flash{server_id}.ustream.tv:18881/{video_name}.flv
というflvのURLが作れます。
perlソースの途中の謎の置換 s/\xff\xff\xff\xff/\0\0\0\x31\x0a\0\0\0\x01/;
してて、これはなにかよくわかってません。ただ実際のパケットと見比べて違う部分置換してみたらいけたという代物です。
あとこれで得られるflvデータの音声部分が謎のcodecで変換できない! だれかこれをmp3とかにする方法ご存知のかたいましたらぜひともお知らせください!