Today's addition to the tips series has a funny history. A friend
of mine was stuck in an envrionment, where she couldn't install Perl or CLive but
PHP with some PECL modules was installed.
She needed to download a few videos for a presentation, but didn't know how to
fetch the videos from YouTube. So I was asked to help. ;-)
After some pondering of the problem, I came up with the following script:
<?php
if(php_sapi_name() !== 'cli')
die("This script needs to be run on the CLI!\n");
if($argc !== 2 )
die("No URL given on CLI or too much parameters!\n");
if(filter_var($argv[1], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) === false)
die("Parameter given as URL does not seem to be an URL or contain a query!\n");
if(!$ch = curl_init($argv[1]))
die("Couldn't init cURL handle for »".$argv[1]."«\n");
curl_setopt($ch, CURLOPT_HEADER, false );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
$htmlsource = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if($htmlsource === false)
die('cURL returned an error: '.$error."\n");
unset($error);
if(!preg_match('/url_encoded_fmt_stream_map=([a-zA-Z0-9%\.,\-_]+)&/',
$htmlsource, $matches))
die("No matches found for url_encoded_fmt_stream_map!\n");
$final = NULL;
foreach(explode(',', urldecode($matches[1])) as $decoded_url_map) {
parse_str($decoded_url_map, $tmp);
if($tmp['quality'] === 'hd1080') {
$final = $tmp;
$final['url'] = urldecode($tmp['url']);
break;
}
}
if(!is_array($final) || is_null($final))
die("No 1080p version of the video was found!\n");
if(!preg_match('/<meta property="og:title" content="(.*)"/', $htmlsource, $title))
die("Couldn't determine title!\n");
$ftitle = preg_replace('/[^\w\d]*/', '', $title[1]);
printf("Found hd1080-quality video for »%s«.\n", $argv[1]);
printf("Downloading to %s.mp4 ...", $ftitle);
if(!$ch=curl_init($final['url']))
die("\nCouldn't create cURL handle for »".$final['url']."«\n");
if(!$fh = fopen(getcwd().DIRECTORY_SEPARATOR.$ftitle.'.mp4', 'wb')) {
curl_close($ch);
die("\nCouldn't create »".$ftitle.".mp4«.\n");
}
curl_setopt($ch, CURLOPT_HEADER, false );
curl_setopt($ch, CURLOPT_FILE, $fh );
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true );
if(!curl_exec($ch)) {
$error = curl_error($ch);
fclose($fh);
curl_close($ch);
die("\nCouldn't download video. cURL error: ".$error."\n");
}
curl_close($ch);
fclose($fh);
printf(" done.\n");
?>
You can download it from my website or you can just copy the
code given above into a file. No matter how you obtain the code, the invocation
will look like: php -f /path/to/script.php
http://www.youtube.com/watch?v=[ID].
Now, before I get a lot of e-mails telling me, what could be improved on the
script or its other limitations (like only being able to download 1080p videos),
please remember that it was hacked together for a simple use case with no real
intent on my part to use it for anything else. It only later occurred to me,
that others might be in a similar pinch sometime. Thus I'm releasing the above
code "as is" under the GNU GPLv3. Therefore you're
free to adapt it to your needs. Please also note, that I'm not recommending
using the above script instead of CLive. If you can install CLive, do so and
don't bother with the above.