Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

brooven's avatar

Can't seek video from Storage.

Hi, I am storing media files in my storage folder via a public disk. When I try to display the video, I am unable to use the seek slider. This happens on Chrome and Edge.

I am aware that I need to request 'partial content' 206 from looking at the web.(everyone recommends it)

The problem is that I don't know how to do it and I can't find a PHP way of doing it. Does anyone know how can I do it in Laravel, is there any package or a code snippet?

Much appreciated.

0 likes
15 replies
martinbean's avatar

@brooven The problem is you sound like you’re just displaying an MP4 or something. This will use progressive downloading and not streaming.

Most browsers will implement partial content downloading so that when you click somewhere random in the timeline, it’ll start loading the bytes from that point. But there’s going to be lag whilst the browser downloads those bytes.

brooven's avatar

hi @martinbean. Thanks for answering. I might be wrong on this one. I'll try to explain how I reached to this conclusion. I am storing my .mp4 files in azure blob storage. When I open one of the videos, if the videos is over 100mb it will take 10-30 secs to load it and then I can't jump on time from the seeker bar ( it resets to 00:00). On Firefox it still takes time for the video to load but you can seek. This link might give you more details:

https://social.msdn.microsoft.com/Forums/azure/en-US/979b4cf4-056f-4c1e-ab4b-3997e2be1740/how-can-i-make-azure-blob-give-me-206-partial-content-for-mp4-getting-200?forum=windowsazuredata

This is how Microsoft recommends fixing the problem (set blob service properties) but I have no idea how to do this in Laravel?

https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-service-properties

Not sure if it's laravel, chrome or azure, any ideas on how to approach this?

Tray2's avatar

I suggest you use a video hosting site like vimeo

brooven's avatar

Hi @tray2, I did not choose azure. I had to work with it. I am using azure blob storage for all media files, like thumbnails, subtitles.. I have an admin panel that is uploading these files to azure blob storage. Is there no way to make this work with azure?

Tray2's avatar

I would never store a blob in the database like that. It will affect the performance greatly. Store all binaries on a filesystem is much better.

You can try using a dlna server software like serviio and use it's api on your own page.

https://serviio.org/

brooven's avatar

I am only storing the path to these videos. Each video record has a video_path and thumnbail_path. And I display them as a source on the View. Is that bad practice?

martinbean's avatar

Blob storage is just file storage (like S3) isn’t it? And not a database…?

brooven's avatar

yes, blob storage is the equivalent to s3 on Azure. (mainly used for big unstructured data)

martinbean's avatar

@brooven Seems the issue is with Azure. Most other services support partial content. It’s just a standard HTTP feature known as “range requests” (as you’re requesting a range of bytes from a larger file): https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

I’m guessing your bucket (or whatever Azure calls them) configuration will need updating to accept and return the HTTP headers involved in range requests. Services like S3 will do this automatically.

martinbean's avatar

@brooven That API is for configuring the blob service. So you would only need to call it once.

Looking at the documentation, you’ll need to send a request setting the AllowedHeaders (to tell the blob service you want to use the range headers) and then possibly ExposedHeaders to tell the blob service to return the headers in responses as well.

brooven's avatar

How can I send this request. Is it via postman?

martinbean's avatar

@brooven Yes. Or any other method of sending a HTTP request: cURL, an Artisan command, etc.

brooven's avatar

I reached this point but I receive an ERROR:

" The MAC signature found in the HTTP request 'random hashed string produced' is not the same as any computed signature. Server used following string to sign: 'GET x-ms-date:Mon, 08 Feb 2021 10:53:22 GMT x-ms-version:2017-11-09 /name/media comp:properties restype:service'."

Any ideas what is wrong with the code?

    $account_name = "randomname";
    $containername = "media";
    $access_key = "access_key1 from portal";

    $canonicalizedHeaders  = "x-ms-date:$date\nx-ms-version:2017-11-09";
    $canonicalizedResource = "/$account_name/$containername\ncomp:list\nrestype=service&comp=properties";

    $arraysign = array();
    $arraysign[] = 'GET';                     /*HTTP Verb*/
    $arraysign[] = '';                        /*Content-Encoding*/
    $arraysign[] = '';                        /*Content-Language*/
    $arraysign[] = '';                        /*Content-Length (include value when zero)*/
    $arraysign[] = '';                        /*Content-MD5*/
    $arraysign[] = '';                        /*Content-Type*/
    $arraysign[] = '';                        /*Date*/
    $arraysign[] = '';                        /*If-Modified-Since */
    $arraysign[] = '';                        /*If-Match*/
    $arraysign[] = '';                        /*If-None-Match*/
    $arraysign[] = '';                        /*If-Unmodified-Since*/
    $arraysign[] = '';                        /*Range*/
    $arraysign[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
    $arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

    $stringtosign = implode("\n", $arraysign);

    $signature = 'SharedKey' . ' ' . $account_name . ':' . base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($access_key), true));

    $endpoint = 'https://' . $account_name . '.blob.core.windows.net';
    $url = $endpoint . '/' . $containername . '?restype=service&comp=properties';

    $headers = [
        "x-ms-date:{$date}",
        'x-ms-version:2017-11-09',
        'Accept:*/*',
        "Authorization:{$signature}"
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response  = curl_exec($ch);
    echo curl_error($ch);
    curl_close($ch);
    echo '<pre>';
    print_r($response); ```

Please or to participate in this conversation.