【问题标题】:Get direct link videos from Vimeo in PHP在 PHP 中从 Vimeo 获取直接链接视频
【发布时间】:2012-07-08 09:12:41
【问题描述】:

我想要使用 PHP 脚本直接链接到来自 Vimeo 的视频。 我设法手动找到它们,但我的 PHP 脚本不起作用。 这是倡议: 比如我拍了这个视频:http://vimeo.com/22439234

当您进入页面时,Vimeo 会生成与当前时间戳和该视频相关联的签名。此信息存储在 JavaScript 变量中,大约在第 520 行之后: window.addEvent ('domready', function () {

然后当您点击播放时,HTML5 播放器会读取此变量并发送 HTTP 请求:

http:// player.vimeo.com/play_redirect?clip_id=37111719&sig={SIGNATURE}&time={TIMESTAMP}&quality=sd&codecs=H264,VP8,VP6&type=moogaloop_local&embed_location=

但它也适用于:

http:// player.vimeo.com/play_redirect?clip_id=37111719&sig={SIGNATURE}&time={TIMESTAMP}&quality=sd

如果此 URL 未使用打开 http://vimeo.com/22439234 的 IP 地址打开,则会返回带有错误消息的 HTTP 代码 200。

如果使用正确的 IP 地址打开此 URL,则标头“Location”会重定向到视频文件的链接: http://av.vimeo.com/XXX/XX/XXXX.mp4?aksessionid=XXXX&token=XXXXX_XXXXXXXXX

当我手动构建此链接http://player.vimeo.com/play_redirect?...(“右键单击”>“源代码”>“第 520 行”)时,它可以工作。

但是对于 PHP 和正则表达式,它会返回带有错误消息的 HTTP code 200

为什么?

根据我的观察,Vimeo 不会检查 HTTP 请求的标头 http:// player.vimeo.com/play_redirect?... GETHEAD、带 cookie、不带 cookie、引荐来源网址等...不会改变。

对于 PHP,我使用函数 file_get_contents()get_headers()

    <?php
    function getVimeo($id) {

    $content = file_get_contents('http://vimeo.com/'.$id);

    if (preg_match('#document\.getElementById\(\'player_(.+)\n#i', $content, $scriptBlock) == 0)
        return 1;

    preg_match('#"timestamp":([0-9]+)#i', $scriptBlock[1], $matches);
    $timestamp = $matches[1];
    preg_match('#"signature":"([a-z0-9]+)"#i', $scriptBlock[1], $matches);
    $signature = $matches[1];

    $url = 'http://player.vimeo.com/play_redirect?clip_id='.$id.'&sig='.$signature.'&time='.$timestamp.'&quality=sd';

    print_r(get_headers($url, 1));
    }

【问题讨论】:

    标签: php download vimeo


    【解决方案1】:

    算法如下:

    • 输入数据:vimeoUrl。
    • content = getRemoteContent(vimeoUrl)。
    • 解析内容以从 data-config-url 中查找和提取值 属性。
    • 导航到 data-config-url 并将内容加载为 JSON 对象: $video = json_decode($this->getRemoteContent($video->getAttribute('data-config-url')));
    • 返回 $video->request->files->h264->sd->url — 这将返回一个 标清质量视频的直接链接。

    这是我的简单课程,目前正在工作。

    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;
        }
    
    }
    

    使用:

    $video = new VideoController;
    var_dump($video->getVimeoDirectUrl('http://vimeo.com/90747156'));
    

    【讨论】:

    • 如果视频是机密的并且您可以访问它:只需找到带有嵌入视频的&lt;iframe&gt; 并在&lt;body&gt; 内您将看到带有JS 功能的&lt;script&gt; 标签。在这个函数中找到var config,然后你可以看到JSON键"progressive",其值为数组,链接到不同分辨率的视频。
    【解决方案2】:

    尝试在每个请求的标头中添加一个有效的用户代理。 为此,您必须使用 cURL 或 HttpRequest 而不是 file_get_contents()。

    经过这样的操作,我得到了一个下载视频文件的工作链接。

    这是我的代码:

    function getVimeo($id) {
        // get page with a player
        $queryResult = httpQuery('http://vimeo.com/' . $id);
        $content = $queryResult['content'];
    
        if (preg_match('#document\.getElementById\(\'player_(.+)\n#i', $content, $scriptBlock) == 0)
            return 1;
    
        preg_match('#"timestamp":([0-9]+)#i', $scriptBlock[1], $matches);
        $timestamp = $matches[1];
        preg_match('#"signature":"([a-z0-9]+)"#i', $scriptBlock[1], $matches);
        $signature = $matches[1];
    
        $url = 'http://player.vimeo.com/play_redirect?clip_id=' . $id . '&sig=' . $signature . '&time=' . $timestamp . '&quality=sd';
    
        // make the request for getting a video url
        #print_r(get_headers($url, 1));
        $finalQuery = httpQuery($url);
        return $finalQuery['redirect_url'];
    }
    // make queries via CURL
    function httpQuery($url) {
        $options = array(
            CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19',
            CURLOPT_RETURNTRANSFER => true,
        );
        $ch = curl_init($url);
        curl_setopt_array($ch, $options);
        $content = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        $result = $info;
        $result['content'] = $content;
    
        return $result;
    }
    
    echo getVimeo(22439234);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多