2010-06-29

【PHP】下載 YouTube 影片

常常覺的Youtube上的影片有些還真有趣,

就會想要下載下來,以後無聊可以看看。

所以就研究了一下怎麼寫。

其實程式不難,短短的就可以搞定了。

下面就貼上我亂寫的一些Code。

第一種方式,是使用 get_video_info 來取得影片資訊,進而拿到token ,取得影片路徑。

function doHttpRequest($url) {
    $ch = curl_init();
    $header[] = "Cache-Control: no-cache";
    $header[] = "Pragma: no-cache";
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
    curl_setopt($ch, CURLOPT_TIMEOUT, 4);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_FAILONERROR, 1);

    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

$url = 'http://www.youtube.com/watch?v=q_gfD3nvh-8';
// video_id
$key = explode("v=",$url);
$key = $key[1];

$content = doHttpRequest("http://youtube.com/get_video_info?video_id=".$key);

$a = explode('&', $content);  
$info = array();
foreach($a as $item){
    $tmp = explode('=', $item);
    $info[$tmp[0]] = urldecode($tmp[1]);
}
$token = $info['token'];
$url= 'http://www.youtube.com/get_video?fmt=18\&video_id='.$key.'\&t='.$token;
$cmd = '/usr/bin/wget '.$url. ' -O /tmp/'.$key;

system($cmd, $ret_val);
echo $ret_val; // 回0表正常抓到檔案。 

但第一種方式會有一個缺點,就是當影片有限制時,會有錯誤,例如回傳下列錯誤訊息。

array(3) { ["status"]=>  string(4) "fail" ["errorcode"]=>  string(3) "150" ["reason"]=>  string(90) "這部影片含有 SM Entertainment 所擁有的內容,禁止在特定網站上播放。" }

所以這時候,可以改成用下列這種方式來抓影片,這個方式是直接把Youtube的播放頁Html全部抓回來,

然後取得所要的token及相關資訊,程式如下:

$url = 'http://www.youtube.com/watch?v=q_gfD3nvh-8';
// 取得 video id, 必要
$key = explode("v=",$url);
$key = $key[1];

$txt = urldecode(file_get_contents($url));
// 取得 title, 非必要
preg_match('/
$title = substr($title[0], 28, -2);
// 取得 keywords, 非必要
preg_match('/
$keywords = substr($keywords[0], 31, -2);
// 取得 token, 必要
preg_match('/&t=[\w-=_]+/',$txt,$t_temp);
$t = substr($t_temp[0], 3);

$url= 'http://www.youtube.com/get_video?fmt=18\&video_id='.$key.'\&t='.$t;
$cmd = '/usr/bin/wget '.$file. ' -O /tmp/'.$key;
system($cmd, $ret_val);
echo $ret_val; // 回0表正常抓到檔案。

所以基本上只要用第二種方式,就可以了抓到影片了。

不過我不太會regExp,所以寫的有點…暴力……

以上~~

 

 

附上 fmt 資訊 ( 來源:一次搞懂十種YouTube格式 )

※影片格式與&fmt參數對應

  • MP4格式:&fmt=18、22、37
  • 3GP格式:&fmt=13、17
  • FLV格 式:其他皆是

※&fmt參數與影片規格對照

參數 檔案格式 影片大小 聲音格式 備註
&fmt=0 FLV 320 x 240 單聲道 22KHz MP3 與&fmt=5相同
&fmt=5 FLV 320 x 240 單聲道 44KHz MP3  
&fmt=6 FLV 480 x 360 單聲道 44KHz MP3  
&fmt=34 FLV 320 x 240 雙聲道 44KHz MP3 YouTube預設影片格式
&fmt=35 FLV 640 x 380 雙聲道 44KHz MP3  
&fmt=13 3GP 176 x 144 雙聲道 8KHz 適合小螢幕手機
&fmt=17 3GP 176 x 144 單聲道 22KHz 適合小螢幕手機
&fmt=18 MP4 480 x 360 雙聲道 44KHz AAC H.264編碼
&fmt=22 MP4 1280 x 720 雙聲道 44KHz AAC H.264編碼
&fmt=37 MP4 1920 x 1080 雙聲道 44KHz AAC H.264編碼

 

2010-08-05 更新:

不久前發現 http://www.youtube.com/get_video 這隻不能用了~

真的很麻煩,現在改成用 get_video_info 取得影片資訊,

然後 Parsing 裡面的 fmt_url_map ,取得各種格式的網址去下載。



PS. fmt_url_map 己經換成 url_encoded_fmt_stream_map。

1 comments:

  1. Parser url_encoded_fmt_stream_map的資訊,在local端可以正常出現正確url, 但是部署到外部Server所取到的url不正確。 好像只能在local端使用?

    回覆刪除