Skip to content
Advertisement

How to play video both locally and from url using php

I have reviewed several similar codes, I have tried them all, but they all work when the multimedia file is hosted locally, when the multimedia file is in a url it does not work, it does not play the video.

They could suggest what changes should be used for this script to work on both url and local media files.

    //$path = 'video.mp4';
    $path = 'https://ia601407.us.archive.org/5/items/205_20210726/205.mp4';
    $file = $path;

    $fp = @fopen($file, 'rb');
    $size = filesize($file);
    $length = $size;
    $start = 0;
    $end = $size - 1;

    header('Content-type: video/mp4');
    header("Accept-Ranges: bytes");

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

        $c_start = $start;
        $c_end = $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 $start-$end/$size");
            exit;
        }

        if ($range[0] == '-'){
            $c_start = $size - substr($range, 1);
        } else {
            $range = explode('-', $range);
            $c_start = $range[0];
            $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
        }

        $c_end = ($c_end > $end) ? $end : $c_end;

        if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
            header('HTTP/1.1 416 Requested Range Not Satisfiable');
            header("Content-Range: bytes $start-$end/$size");
            exit;
        }

        $start = $c_start;
        $end = $c_end;
        $length = $end - $start + 1;
        fseek($fp, $start);
        header('HTTP/1.1 206 Partial Content');
    }

    header("Content-Range: bytes $start-$end/$size");
    header("Content-Length: ".$length);

    $buffer = 1024 * 8;

    while(!feof($fp) && ($p = ftell($fp)) <= $end) {
        if ($p + $buffer > $end) {
            $buffer = $end - $p + 1;
        }
        set_time_limit(0);

        ob_clean();

        echo fread($fp, $buffer);
        flush();
    }
    fclose($fp);
    exit();

Advertisement

Answer

So here’s a basic solution to cache a remote file locally so you can re-use your code:

    if (substr($path, 0, 6) === 'http://' || substr($path, 0, 7) === 'https://') {
       $file = md5($path);
       if (!file_exists($file)) {
           $urlStream = fopen($path, 'r');
           $dest = fopen($file, 'w');
           stream_copy_to_stream($urlStream, $dest);  
           fclose($urlStream); 
           fclose($dest);
       }
    } else {   
        $file = $path;
    }
    $fp = @fopen($file, 'rb');
    $size = filesize($file);
    $length = $size;
    $start = 0;
    $end = $size - 1;

    header('Content-type: video/mp4');
    header("Accept-Ranges: bytes");

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

        $c_start = $start;
        $c_end = $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 $start-$end/$size");
            exit;
        }

        if ($range[0] == '-'){
            $c_start = $size - substr($range, 1);
        } else {
            $range = explode('-', $range);
            $c_start = $range[0];
            $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
        }

        $c_end = ($c_end > $end) ? $end : $c_end;

        if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
            header('HTTP/1.1 416 Requested Range Not Satisfiable');
            header("Content-Range: bytes $start-$end/$size");
            exit;
        }

        $start = $c_start;
        $end = $c_end;
        $length = $end - $start + 1;
        fseek($fp, $start);
        header('HTTP/1.1 206 Partial Content');
    }

    header("Content-Range: bytes $start-$end/$size");
    header("Content-Length: ".$length);

    $buffer = 1024 * 8;

    while(!feof($fp) && ($p = ftell($fp)) <= $end) {
        if ($p + $buffer > $end) {
            $buffer = $end - $p + 1;
        }
        set_time_limit(0);

        ob_clean();

        echo fread($fp, $buffer);
        flush();
    }
    fclose($fp);

This will create a file based on the accessed URL. You might want to modify the path you store these files in but this is the general idea. The advantage is you will only need to cache the file once, however you may need to use some process to occasionally clean up the cache (like a scheduled task or something like that)

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement