2

I have uploaded a video to my Windows Storage and noticed, that the seekbar (of the default Chrome's html5 player) is not working. Url of that video is:

http://portalvhdsrwglplr5bdc2k.blob.core.windows.net/vdepot/uploads/video/file/167/surfer-girl-35094486.mp4

Please note: Seekbar is not working when video download is in progress or it's 100% the first time. If video has been downloaded by chrome player and you refresh the page, seekbar works fine.

I'm a video encoding newbie thus i'm not sure if that's the problem with the video, with browser or maybe with windows azure in some way? I also can't find anything about that topic in google.

mbajur
  • 4,406
  • 5
  • 49
  • 79

4 Answers4

8

Properly served files for HTML video need to use HTTP Byte Serving, which allows the browser to request just the part of the file that it needs to let you watch the video. If you don't have this, you run into problems like this one.

When you skip forward in a video past the parts that are buffered, the browser can ask the server for the video file from that point forward, skipping the beginning. You may have noticed in the days when most web video players used Flash, especially on Vimeo, you had to wait until most of the video file was buffered before you could seek ahead, because those Flash players didn't support this feature.

The browser requests the file in this format by using the "Ranges" header. The server should respond with a "206 Partial Content" status code, some HTTP headers about the range data, and only a subset of the actual file. Your server is responding with a standard 200 status response. Here's a more detailed article about this process if you're interested.

http://benramsey.com/blog/2008/05/206-partial-content-and-range-requests/

I don't know much about Windows Storage, but it appears that it does support this feature. You may need to check your version and your configuration. These articles may point you in the right direction:

http://msdn.microsoft.com/en-us/library/windowsazure/ee691967.aspx http://blogs.msdn.com/b/windowsazurestorage/archive/2011/09/15/windows-azure-blobs-improved-http-headers-for-resume-on-download-and-a-change-in-if-match-conditions.aspx

Good luck.

brianchirls
  • 7,661
  • 1
  • 32
  • 32
3

The issue here is that a brand new AZURE storage account default implementation does not support supplying the correct headers "Accept-Ranges: bytes" in the HTTP response for the HTTP 206 Partial Content

To fix this you will need to set the DefaultServiceVersion for your storage account to version 2013-08-15 or later. In their documentation, they say this was officially supported in version 2011-08-18, but in my testing, I do not see it until I set it to version 2013-08-15. In the end, I just updated it to the latest version 2019-02-02. I will show you how to do that in a moment.

With that said here are some steps you can take to test and verify this and then how to fix it.

Create a brand new AZURE storage account, add a new container and then upload an MP4 to that container. To see the default headers for your MP4 run the following curl command

curl -I https://<StorageAccount>.blob.core.windows.net/<YourContainer>/<Your>.mp4

Here are the headers you should see your response

HTTP/1.1 200 OK
Content-Length: 8655515
Content-Type: video/mp4
Last-Modified: Fri, 29 Nov 2019 21:45:12 GMT
ETag: 0x8D7751569DECA07
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: cc44ae3e-b01e-00b5-2337-e4372d000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Access-Control-Expose-Headers: x-ms-request-id,Server,x-ms-version,Content-Type,Last-Modified,ETag,x-ms-lease-status,x-ms-blob-type,Content-Length,Date,Transfer-Encoding
Access-Control-Allow-Origin: *
Date: Sat, 15 Feb 2020 19:36:37 GMT

You will see that the following header is missing is

Accept-Ranges: bytes

You can then verify this header will return when you run the following curl command

curl -I -H x-ms-version:2013-08-15 https://<StorageAccount>.blob.core.windows.net/<YourContainer>/<Your>.mp4

To permanently set the storage account version I used LinqPad and the following code with a reference to the Windows.Azure.Storage Nuget Pacakge

var connectionString = "DefaultEndpointsProtocol=https;AccountName=<YourAcountName>;AccountKey=<YourAccountKey>;";
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
var props = await blobClient.GetServicePropertiesAsync();
props.Dump(); /* Here you will see that the DefaultServiceVersion is null*/
props.DefaultServiceVersion = "2019-02-02";
await blobClient.SetServicePropertiesAsync(props);

The first time you run this you will see that the DefaultServiceVersion is null. If you run this a second time you will then see the DefaultServiceVersion will be the version you set.

If you then run the curl command again.

curl -I https://<StorageAccount>.blob.core.windows.net/<YourContainer>/<Your>.mp4

You will see the following headers, which now includes the "Accept-Ranges: bytes" header and your seek will work.

HTTP/1.1 200 OK
Content-Length: 8655515
Content-Type: video/mp4
Last-Modified: Fri, 29 Nov 2019 21:45:12 GMT
Accept-Ranges: bytes
ETag: "0x8D7751569DECA07"
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: b95228de-f01e-0135-4596-e5d2d2000000
x-ms-version: 2019-02-02
x-ms-creation-time: Fri, 29 Nov 2019 21:45:12 GMT
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
x-ms-server-encrypted: true
x-ms-access-tier: Hot
x-ms-access-tier-inferred: true
Date: Mon, 17 Feb 2020 13:33:00 GMT
Craig Selbert
  • 737
  • 1
  • 8
  • 17
  • 1
    I was able to do that using a node.js back-end and the 'azure-storage' package. I called the equivalent `blobService.getServiceProperties` and `blobService.setServiceProperties` the same way you did. Thanks a lot ! – Cedric Apr 09 '20 at 10:50
0

As @Craig Selbert said, new Azure storage accounts don't support the "Accept-Ranges: bytes" header. You can fix that by setting the DefaultServiceVersion in the Azure Cloud Shell like:

$ctx = New-AzStorageContext -ConnectionString "[connectionstring]"
Update-AzStorageServiceProperty -ServiceType Blob -DefaultServiceVersion 2019-02-02 -Context $ctx

Where [connectionstring] comes from the "Access Keys" tab in the Storage Account.

Lee Richardson
  • 8,331
  • 6
  • 42
  • 65
  • If you found this helpful please upvote Craig's answer, he did all the hard work of figuring it out, I just found an easier way to implement it. – Lee Richardson Jun 10 '20 at 22:41
0

NodeJS way of @Craig Selbert's answer

  1. Retrieve Connection string from "Access Keys" tab in Storage Account

  2. Install "azure-storage". Tested with version 2.10.7

    npm i azure-storage
    
  3. The NodeJS Endpoint

    const azureStorage = require('azure-storage');
    const connectionString = "DefaultEndpointsProtocol=https;AccountName=[accountName];AccountKey=[accountKey];EndpointSuffix=core.windows.net";
    const blobService = new azureStorage.BlobService()
    
    blobService.setServiceProperties({
    DefaultServiceVersion: '2019-02-02'
        }, (err, result, response) => {
    
            // Log service properties
            blobService.getServiceProperties({}, (err, properties) => {
                res.send(properties);
            });
    
    });