问题
I saw that today vimeo changed the way they are streaming the videos and I can't stream their videos anymore. I saw that when I generate the link to the video, which was for example:
http://vimeo.com/moogaloop/play/clip:6649390/1eab2a25f30f1aadaf5e306d0f40fd6c/1292498602/?q=hd
It's redirecting me to a page saying "Permission denied". I tried using curl, but without any success. I sniffed the traffic and I saw that it's streaming from something like:
http://av.vimeo.com/02047/623/34209065.mp4?token=1292496582_34de09a6d13212cf26af08357d311c30
Does anybody know how to get the working URL to the video file?
The way I'm getting the videos at the moment is:
- Choose link
http://vimeo.com/video_id
. - Get only the
video_id
. - Get the XML for the video
http://vimeo.com/moogaloop/load/clip:video_id;
. parse the XML and find the necessary information:
- request_signature
- request_signature_expires
- isHD
Generate the link:
$video_link = "http://vimeo.com/moogaloop/play/clip:".$video_id."/".$request_signature."/".$request_signature_expires."/?q=".$quality."";
If I do this manually through the browser it works, but if I do it through the script it doesn't.
回答1:
After spending a few hours on finding out how I can get the direct link to vimeo I found a good solution. So here are the steps for the users who want to download and stream video src directly from vimeo. Keep in mind that they block all IP addresses and probably hosts which are downloading the videos in this way, so I just stopped using their services and I will never use them again :).
Steps to get the video sources:
- choose link
http://vimeo.com/video_id
- get only the
video_id
- get the xml for the video
http://vimeo.com/moogaloop/load/clip:video_id;
parse the xml and I find the necessary information I need:
request_signature
request_signature_expires
isHD
Then I generate the link:
$video_link = "http://vimeo.com/moogaloop/play/clip:".$video_id."/".$request_signature."/".$request_signature_expires."/?q=".$quality."";
Then if you are php dev, you call wget command through exec in this way
exec("wget -b '$video_link' -a 'wget.log' -O -");
Then you read the log and find out the link you are looking for. You can simply parse the log file. The direct link is between "Location: " and "[following]"
You return the direct link and clean the log file :)
NOTE: keep in mind again that this won't work forever. Sooner or later they will block your ip :).
回答2:
This javascript works for me.
var player = document.getElementsByClassName("player")[0].getAttribute("id");
player = eval(player.replace("player_", "clip"));
var time = player.config.request.timestamp;
var sig = player.config.request.signature;
var clip_id = window.location.href.substring(17);
var url = "http://player.vimeo.com/play_redirect" +
"?clip_id=" + clip_id +
"&sig=" + sig +
"&time=" + time;
var v = document.getElementById("menu");
v.style.fontSize = "4em";
v.style.lineHeight = "1em";
v.innerHTML =
"<a href='" + url + "'>SD</a>, " +
"<a href='" + url + "&quality=hd'>HD</a>";
source
回答3:
Warning The methods described above are not supported by Vimeo. There is no assurance they work right now, or will continue working in the future. They can (and likely will) break at any moment, without any prior notice.
The only officially supported method of accessing video file URLs is through the API.
If you are trying to access the URLs of videos you own, you must have a PRO account.
If you are trying to access the URLs of videos you don't own, you should embed the video, or open it with the Vimeo iOS app.
回答4:
FYI, the above example won't work, but it's close. You need to send fake cookies. So basically when you visit the page with the XML, you need to grab the cookies, and then send those cookies you previously received while visiting the final video url. So here's how you do it in PHP (using Yii) with curl:
public function actionVimeo($video_id)
{
$xml_url = "http://vimeo.com/moogaloop/load/clip:$video_id";
$ch = curl_init($xml_url);
$cookieFile = Yii::app()->basePath . '/runtime/vimeocookie'. time().'.txt'; //replace this line with code to generate a writeable path in your application
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); //the cookie file will be populated with cookies received while viewing the xml page
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); //you need to send a user agent here and it must be the same below when you visit the video url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string($output);
$request_signature = $xml->request_signature;
$request_signature_expires = $xml->request_signature_expires;
$vid_url = "http://vimeo.com/moogaloop/play/clip:".$video_id."/".$request_signature."/".$request_signature_expires."/?q=sd";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$vid_url);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); //same user agent as on previous vimeo page you visited
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); //the cookies in that cookie file will be used while visiting the video URL
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); //vimeo changes the header location, so you gotta follow it
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$video = curl_exec($ch);
curl_close($ch);
unlink($cookieFile); //remove the temporary cookie file
$savePath = Yii::app()->basePath . '/runtime/testvim.mp4'; //change this to a path your application can write the final video to
file_put_contents($savePath, $video);
exit;
}
回答5:
No need for any scripts, let alone PHP.
I wanted to download protected video (embedded on specific website), that even on vimeo.com cannot be played due to "Privacy settings".
Simply fire-up Developer tools (Opera Dragonfly, Chrome Developer tools, whatever), choose Network and there you go:
http://pdl.vimeocdn.com/23062/181/302074466.mp4?token2=1424299768_bbeb6039c037cd429cd560d668ec851e&aksessionid=1f4d289cd1a3abe1
Method: Get
Status text: 206 Partial content
Type: video/mp4
Just copy that first URL and download with some tool (I used "wget").
Saved.
回答6:
A quick and dirty approach would be:
$base = 'http://player.vimeo.com/play_redirect';
$curl = curl_init(sprintf('http://player.vimeo.com/video/%s', $_GET['id']));
curl_setopt_array($curl, array(
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
CURLOPT_RETURNTRANSFER => true
));
preg_match('/g:(\{.*?\}),a/s', curl_exec($curl), $match);
curl_close($curl);
$json = json_decode($match[1])->request;
$url = sprintf('%s?quality=sd&clip_id=%s&time=%d&sig=%s',
$base,
$_GET['id'],
$json->timestamp,
$json->signature
);
$curl = curl_init($url);
curl_setopt_array($curl, array(
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
CURLOPT_RETURNTRANSFER => true
));
$headers = explode("\r\n", curl_exec($curl));
curl_close($curl);
foreach ($headers as $header) {
if ($header) {
header($header);
}
}
回答7:
The algorithm looks like this:
- Input data: vimeoUrl.
- content = getRemoteContent(vimeoUrl).
- Parse content to find and extract the value from data-config-url attribute.
- Navigate to data-config-url and load the content as JSON Object: $video = json_decode($this->getRemoteContent($video->getAttribute('data-config-url')));
- Return $video->request->files->h264->sd->url — this will return a direct link for SD quality video.
Here is my simple class, that working for this moment:
class VideoController
{
/**
* @var array Vimeo video quality priority
*/
public $vimeoQualityPrioritet = array('sd', 'hd', 'mobile');
/**
* @var string Vimeo video codec priority
*/
public $vimeoVideoCodec = 'h264';
/**
* Get direct URL to Vimeo video file
*
* @param string $url to video on Vimeo
* @return string file URL
*/
public function getVimeoDirectUrl($url)
{
$result = '';
$videoInfo = $this->getVimeoVideoInfo($url);
if ($videoInfo && $videoObject = $this->getVimeoQualityVideo($videoInfo->request->files))
{
$result = $videoObject->url;
}
return $result;
}
/**
* Get Vimeo video info
*
* @param string $url to video on Vimeo
* @return \stdClass|null result
*/
public function getVimeoVideoInfo($url)
{
$videoInfo = null;
$page = $this->getRemoteContent($url);
$dom = new \DOMDocument("1.0", "utf-8");
libxml_use_internal_errors(true);
$dom->loadHTML('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $page);
$xPath = new \DOMXpath($dom);
$video = $xPath->query('//div[@data-config-url]');
if ($video)
{
$videoObj = json_decode($this->getRemoteContent($video->item(0)->getAttribute('data-config-url')));
if (!property_exists($videoObj, 'message'))
{
$videoInfo = $videoObj;
}
}
return $videoInfo;
}
/**
* Get vimeo video object
*
* @param stdClass $files object of Vimeo files
* @return stdClass Video file object
*/
public function getVimeoQualityVideo($files)
{
$video = null;
if (!property_exists($files, $this->vimeoVideoCodec) && count($files->codecs))
{
$this->vimeoVideoCodec = array_shift($files->codecs);
}
$codecFiles = $files->{$this->vimeoVideoCodec};
foreach ($this->vimeoQualityPrioritet as $quality)
{
if (property_exists($codecFiles, $quality))
{
$video = $codecFiles->{$quality};
break;
}
}
if (!$video)
{
foreach (get_object_vars($codecFiles) as $file)
{
$video = $file;
break;
}
}
return $video;
}
/**
* Get remote content by URL
*
* @param string $url remote page URL
* @return string result content
*/
public function getRemoteContent($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_USERAGENT, 'spider');
$content = curl_exec($ch);
curl_close($ch);
return $content;
}
}
Using:
$video = new VideoController;
var_dump($video->getVimeoDirectUrl('http://vimeo.com/90747156'));
回答8:
The answers for this on SuperUser were out of date so I thought I would post it here (not enough reputation to post there)
So I just recorded XHR requests with Chrome devtools and the first request was for the the json file containing the link to the akamai CDN hosted video along with the token akamai provides. This token is important. It is hash that includes a timestamp so the links for the videos here will need to be downloaded somewhat quickly or requests will be refused.
The format for this JSON file was in the form:
https://player.vimeo.com/video/VIDEO_ID/config?byline=0&collections=1&context=Vimeo%5CController%5CClipController.main&default_to_hd=1&outro=nothing&portrait=0&share=1&title=0&watch_trailer=0&s=6cffff97fffffffffff4ffffffff679ec66ffff_14ffffffff
And then I just looked for the highest quality object in the JSON (1080p) and download that file. In the format:
https://fpdl.vimeocdn.com/vimeo-prod-skyfire-std-us/01/XXXXX/8/XXXX/XXXXXXXX.mp4?token=XXXXXXX-0xXXXXXXXXXXXXX
Note the Xs are numbers I replaced for privacy.
来源:https://stackoverflow.com/questions/4460394/how-can-i-find-download-links-for-vimeo-videos