Streaming Videos from Azure Blob Storage
Tags: azure, webdev
Published: 2022-04-22 12:32:45

I recently had a project where I needed to stream video content from an Azure Blob Storage account. Should be easy enough right? Just plonk a `<video>` tag in and point it to the Blob URL (the blobs are publicly accessible). Well, it wasn't quite so straightforward. Here are some gotchas that might help you if you need to do something similar.

## Why are we waiting?
For my first naïve attempt, a `<video>` tag pointing to the Blob URL, it turned out it was trying to download the complete video file first before playing, and the videos I wanted to stream were too large for that to be acceptable.

![first attempt network response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3odowgemimu3a1khsx5q.jpg)
> Full video download took 43 seconds, not great...

For streaming, the request needs to specify a range of data at a time instead of the entire video. This is supported via the `Accept-Ranges` HTTP header which returns a HTTP 206 *Partial Content* response. Support for this didn't come in until [version '2011-08-18'](https://docs.microsoft.com/en-us/rest/api/storageservices/version-2011-08-18) of the Azure Storage service which is why the entire file was being downloaded first. You can specify the version when using an SDK or the REST API (via the `x-ms-version` header), but for public anonymous access where I wanted to point a `<video>` tag at a URL, this wasn't an option.

### Set a global default version
Instead, you can set the default version globally at the account level using either one of the SDKs or the ['Set Blob Service Properties'](https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-service-properties) REST API method. This is the part that probably isn't explained fully in the docs, particularly for public anonymous access, although it is [hinted at here](https://docs.microsoft.com/en-us/rest/api/storageservices/versioning-for-the-azure-storage-services#requests-via-anonymous-access). Make a REST/SDK call setting the version to `2011-08-18` or later and your storage account will now support range requests and streaming will work as expected.

```javascript
blobServiceClient.setProperties({
    defaultServiceVersion: "2021-04-10"
})
.then(res => console.log("Set Properties response", res))
.catch(err => console.error("Set Properties error", err));
```
> How to set the default service version via the JavaScript SDK.

![streaming network response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zysaa8fnemlred9o7fw3.jpg)
> With the correct default storage version set, the video can start playing immediately (note the response status code for the video).

> **Note**: To set the default version you will probably need a `PUT` CORS rule on your storage account and a role assignment for the identity making the call. `Storage Account Contributor` should do the trick.

**Bonus**: The partial content response will also let your users scrub the video.

## Content Type
Another gotcha to be aware of is to make sure your blobs' content types are set correctly. This is usually set appropriately during upload but ensure it is a `video/...` type and hasn't defaulted to something like `application/octet-stream`.

## Further Info
- [General Azure Storage versioning best practices](https://docs.microsoft.com/en-us/rest/api/storageservices/versioning-best-practices)