среда, 4 апреля 2012 г.

Как грабить видео с rutube из PHP

В отличие от YouTube, где видео грабится довольно просто, на RuTube используется rtmp.
И вот этот самый rtmp съел мне весь мозг, т.е. я вообще то знаю как грабить rtmp поток, но в этом случае все оказалось несколько сложнее.
Обычно для граббинга rtmp используется команда примерно такого вида (пример уже для ролика на rutube, может и не работать уже, ибо ссылки походу протухают)
rtmpdump -r rtmp://video-13-17.rutube.ru/rutube_vod_1 -W "http://rutube.ru/player.swf?file=http://bl.rutube.ru/79739a3e8ff8023db07dfe1f2d50edc6.iflv" -y "mp4:vol32/movies/79/73/79739a3e8ff8023db07dfe1f2d50edc6.mp4?e=1333442242&s=55c404be47f98c43d26df9a845ae8aca"  --timeout=4 -o out.mp4 [--resume]
возможные ошибки:
 - никаких & в командной строке, только &
 - если выполнять из консоли linux, параметры, содержащие амперсанд (&) нужно взять в кавычки (как в примере выше)

гемор:
 - рутуб выдает с ограниченной скоростью, rtmpdump выкачивает с максимальной скоростью, и когда буфер достигает 1.5Мб (второй догоняет первого) - случается коллапс.. рассуждая так, я пробовал искуственно ограничить скорость выкачки, получилось примерно следующее
$cmd = 'rtmpdump -r rtmp://video-13-17.rutube.ru/rutube_vod_1 -W "http://rutube.ru/player.swf?file=http://bl.rutube.ru/79739a3e8ff8023db07dfe1f2d50edc6.iflv" -y "mp4:vol32/movies/79/73/79739a3e8ff8023db07dfe1f2d50edc6.mp4?e=1333442242&s=55c404be47f98c43d26df9a845ae8aca"  --timeout=4';
$size = 0;
if (!($fp = popen($cmd_tpl, 'r'))) {
    echo 'cant open cmd pipe' . "\n";
    die;
}
while ($bytes = fread($fp, 1024)) {
    usleep(50000); // try to grab in realtime 10sec video in real 10 seconds
    $size += strlen($bytes);
    echo '.' . $size;
    //fwrite($wf, $bytes); // запись в целевой файл, здесь не представлен
}
качалось медленно, чего и добивался, однако не помогло) при (долгой) закачке первых же 1.5Мб кэша - обрыв
пришлось пойти другим путем - использовать параметр --resume команды rtmpdump

exec($cmd_tpl, $out, $ret);
$cycles = 100; // защита от бесконечности
while ($ret !== 0 and $cycles-- > 0) {
    exec($cmd_tpl . ' --resume', $out, $ret);
}
if ($ret !== 0 and $cycles <= 0) {
    echo 'Failed to grab' . "\n";
    die;
}
echo 'Successfully grabbed ' . "\n";
в несколько подходов, довольно долго, но все же в итоге мы сохранили видео с rutube! на выходе - flv-видеофайл! Параметр timeout рекомендую поставить  от  2 до 4 сек
enjoy

upd: видимо у меня была несколько косячная версия rtmpdump (из репов), последняя 2.4 из git://git.ffmpeg.org/rtmpdump качает без разрывов