Stream Videos over Blob Storage
Azure Blob Storage is an easy and cheap solution for hosting files in the cloud. But there is one thing that doesn't work well in the default configuration of a Storage Account: Video streaming.
The important note here is, that this only applies to Storage Accounts that are
general purpose v1
. In V2 everything works out of the box.
For video streaming to work nicley, the browser requires that the source (our Blob Storage) will present the Accept-Ranges
header in the response of the file and know how to handle the Range
header in the request. This is called partial request
in the HTTP world.
Default API version of a StorageAccount in Azure is:
2009-09-19.
This is too old, according to the docs from Microsoft the minimum supported API version for range headers is 2011-08-18
.
The version change can be achieved in two ways:
- Set the
x-ms-version
header with every request to an higher version- This requires you to have full controll over the player you use and you can inject the header with JavaScript to every request the player does. (don't do this...)
- Change the default API version of your storage account
Because the first option has some drawbacks, we are going to concentrate on the second option.
Change the defaults.
To change the defaults you must deploy the following template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2021-09-01",
"name": "storageaccountname/default",
"properties":{
"defaultServiceVersion": "2021-08-06"
}
}
]
}
This template will set the default service version to 2021-08-06
which is the latest version that was available while writing this article. And it is higher than 2011-08-18
.
If you now try to download a file of your blobstorage you will see a new header in your response: Accept-Ranges
. This header has the value bytes. This is perfect for browsers. Now we enabled partial request support from a browser view.
If you now upload a video to your blobstorage you can open it just over the link.
Here is an example: https://rfvk.blob.core.windows.net/asset-6c3d80d3-b845-4b91-b718-c0c6b4ed3b34/Wanderritt.v.2_1280x720_AACAudio_2722.mp4
And if you open the developer tools of your browser, and skip over the preloading bar, you will see a new request will be made that will end in a 206 response code. And in this request you will also see a Range
header that contains a number. That is the byte position the download of the file should continue. That's exactly what we want.
The video codec is important
The things shown before in this blog post won't work with every video. For this solution to work, the video file must be encoded in a special way. In DaVinci Resolve you have an option to encode a video file "optimized for network". This means that the required metadata of the video like:
- how long
- what is the bitrate
are stored at the beginning of the video file and not at the end. Only if this is done the previous behavior will work.
In ffmpeg the option is called -movflags faststart
and has a good explaination here:
https://manpages.org/ffmpeg
Nice to knows
This can be also helpful to support things like continue a download of a big file when it was canceled for example by network loss. So it's a good thing to enable this also for content that isn't a video.