如何制作过期/签名的视频网址

时间:2018-08-05 00:00:50

标签: php

我有cpanel,我希望为我的客户设置视频流。

我需要设置一次使用以下线程中建议的网址

How to make Expiring/Signed video embed urls

我尝试了完全相同的建议,但是我什至无法通过文件路径播放简单的.mp4文件。

我的参考代码:

libraries / VideoSignature.php

<?php

/*
 * This class allows you to:
 * - Encrypt filepaths and expiration dates into signatures
 * - Decrypt signatures into filepaths and expiration dates
 *
 *
 * Note: String encryption functions were found here:
 * http://stackoverflow.com/a/1289114/1913729
 */

class VideoSignature
{
    // Time before a URL expires, in seconds
    private $expires = 10;
    // Key used to sign your URLs
    private $encryption_key = 'soMeStr0ngP455W0rD!!';
    // Public URL used to serve the content
    private $proxy_url = '/getVideo.php';

    // Encrypts a string
    private function encryptStr($str){
        $iv = mcrypt_create_iv(
            mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
            MCRYPT_DEV_URANDOM
        );

        $encrypted = base64_encode(
            $iv .
            mcrypt_encrypt(
                MCRYPT_RIJNDAEL_128,
                hash('sha256', $this->encryption_key, true),
                $str,
                MCRYPT_MODE_CBC,
                $iv
            )
        );

        return $encrypted;
    }

    // Decrypts a String
    private function decryptStr($str){
        $data = base64_decode($str);
        $iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));

        $decrypted = rtrim(
            mcrypt_decrypt(
                MCRYPT_RIJNDAEL_128,
                hash('sha256', $this->encryption_key, true),
                substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
                MCRYPT_MODE_CBC,
                $iv
            ),
            "\0"
        );

        return $decrypted;
    }

    // Returns a temporary URL
    public function getSignedURL($filepath){
        $data = json_encode(
                array(
                    "filepath" => $filepath,
                    "expires" => time() + $this->expires
                )
            );

        $signature = $this->encryptStr($data);

        return $this->proxy_url . "?s=" . urlencode($signature);
    }

    // Returns a filepath from a signature if it did not expire
    public function getFilepath($signature){
        $data = json_decode( $this->decryptStr($signature), true);

        if($data !== null && $data['expires'] > time() && file_exists($data['filepath'])){
            return $data['filepath'];
        }

        return false;
    }
}

libraries / VideoStream.php

<?php

/*
 * This class was found here:
 * http://stackoverflow.com/a/39897793/1913729
 *
 * It allows you to stream video without giving the real file URL
 */

class VideoStream
{
    private $path = "";
    private $stream = "";
    private $buffer = 102400;
    private $start  = -1;
    private $end    = -1;
    private $size   = 0;

    function __construct($filePath) 
    {
        $this->path = $filePath;
    }

    /**
     * Open stream
     */
    private function open()
    {
        if (!($this->stream = fopen($this->path, 'rb'))) {
            die('Could not open stream for reading');
        }

    }

    /**
     * Set proper header to serve the video content
     */
    private function setHeader()
    {
        ob_get_clean();
        header("Content-Type: video/mp4");
        header("Cache-Control: max-age=2592000, public");
        header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT');
        header("Last-Modified: ".gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT' );
        $this->start = 0;
        $this->size  = filesize($this->path);
        $this->end   = $this->size - 1;
        header("Accept-Ranges: 0-".$this->end);

        if (isset($_SERVER['HTTP_RANGE'])) {

            $c_start = $this->start;
            $c_end = $this->end;

            list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
            if (strpos($range, ',') !== false) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $this->start-$this->end/$this->size");
                exit;
            }
            if ($range == '-') {
                $c_start = $this->size - substr($range, 1);
            }else{
                $range = explode('-', $range);
                $c_start = $range[0];

                $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end;
            }
            $c_end = ($c_end > $this->end) ? $this->end : $c_end;
            if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $this->start-$this->end/$this->size");
                exit;
            }
            $this->start = $c_start;
            $this->end = $c_end;
            $length = $this->end - $this->start + 1;
            fseek($this->stream, $this->start);
            header('HTTP/1.1 206 Partial Content');
            header("Content-Length: ".$length);
            header("Content-Range: bytes $this->start-$this->end/".$this->size);
        }
        else
        {
            header("Content-Length: ".$this->size);
        }  

    }

    /**
     * close curretly opened stream
     */
    private function end()
    {
        fclose($this->stream);
        exit;
    }

    /**
     * perform the streaming of calculated range
     */
    private function stream()
    {
        $i = $this->start;
        set_time_limit(0);
        while(!feof($this->stream) && $i <= $this->end) {
            $bytesToRead = $this->buffer;
            if(($i+$bytesToRead) > $this->end) {
                $bytesToRead = $this->end - $i + 1;
            }
            $data = fread($this->stream, $bytesToRead);
            echo $data;
            flush();
            $i += $bytesToRead;
        }
    }

    /**
     * Start streaming video content
     */
    function start()
    {
        $this->open();
        $this->setHeader();
        $this->stream();
        $this->end();
    }
}

index.php

// Load the signature helper functions
include "libraries/VideoSignature.php";
$vs = new VideoSignature();

?><!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Check out my video!</title>
</head>
<body>
    <!-- /!\ Here, you need to insert a path to your video,
         relative to the getVideo.php file, not an actual URL! -->
    <video src="<?=$vs->getSignedURL("server/path/to/video.mp4");?>"></video>
</body>
</html>

getVideo.php

<?php

// Load the signature helper functions
include "libraries/VideoSignature.php";
$vs = new VideoSignature();
// Load the video streaming functions
include "libraries/VideoStream.php";


if(isset($_REQUEST['s']) && $filepath = $vs->getFilepath($_REQUEST['s'])){
    $stream = new VideoStream($filepath);
    $stream->start();
} else {
    header("HTTP/1.0 403 Forbidden");
    echo "This URL has expired.";
}

我已经检查了文件权限,并且可以通过热链接“ www.mydomain / path / test.mp4”正常工作

但是当我按照建议使用诸如getSignedURL(“ play / tester / test.mp4”);?>“>之类的引用时,视频将无法启动,并且控制台出现错误“找不到文件404错误”。

我需要一个可以帮助我解释如何在访问index.php时使视频网址成为播放器的人。

我唯一想要添加直接URL和流以及签名的东西。

有什么想法吗?

0 个答案:

没有答案