Guide to encoding videos for streaming with Transloadit

Like us at Transloadit, you are probably a fan of streaming services 🎥 But have you ever considered
starting your own? Our /video/adaptive Robot has
you covered in case you did have a wild idea like that! You can use this Robot to encode
mp4 or webm video to either HLS (HTTP Live Streaming) or MPEG-DASH.
In this blog post, we'll walk you through the process of creating a basic proof-of-concept adaptive player in React that supports streaming HLS or MPEG-DASH video, depending on the compatibility of the browser, in a similar vein to one of our JavaScript demos.

What are HLS and MPEG-DASH?
Before we get started, let's clarify what HLS and MPEG-Dash are exactly. Both are streaming protocols that split up video data into small chunks that can be downloaded to a device over HTTP. Both protocols support adaptive playback, switching between encoded versions as network conditions change. HLS has native playback support on Apple devices, while MPEG-DASH is an open standard commonly played through a JavaScript player. Playback and encrypted delivery depend on the browser, player, codecs, and DRM implementation, not just the playlist format.
For this walkthrough, we'll encode to both formats, and use them to work with an adaptive video player.
Storing our files via Assembly
We can jump straight into the Assembly below for an overview of how to use the Robot.
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"hls-encode": {
"use": ":original",
"robot": "/video/encode",
"ffmpeg_stack": "v7",
"preset": "hls-720p"
},
"dash-encode": {
"use": ":original",
"robot": "/video/encode",
"ffmpeg_stack": "v7",
"preset": "dash-720p-video"
},
"thumbnailed": {
"use": "hls-encode",
"robot": "/video/thumbs",
"result": true,
"ffmpeg_stack": "v7"
},
"hls-adaptive": {
"use": {
"steps": ["hls-encode"],
"bundle_steps": true
},
"robot": "/video/adaptive",
"ffmpeg_stack": "v7",
"playlist_name": "my_playlist.m3u8",
"segment_duration": 6,
"closed_captions": false,
"technique": "hls"
},
"dash-adaptive": {
"use": {
"steps": ["dash-encode"],
"bundle_steps": true
},
"robot": "/video/adaptive",
"ffmpeg_stack": "v7",
"playlist_name": "my_playlist.mpd",
"segment_duration": 6,
"technique": "dash"
},
"export-plain": {
"use": "thumbnailed",
"robot": "/google/store",
"credentials": "stream-test",
"acl": "public-read",
"path": "stream-videos/${file.name}"
},
"export-hls": {
"use": "hls-adaptive",
"robot": "/google/store",
"credentials": "stream-test",
"acl": "public-read",
"path": "stream-videos/hls-video/${file.name}"
},
"export-dash": {
"use": "dash-adaptive",
"robot": "/google/store",
"credentials": "stream-test",
"acl": "public-read",
"path": "stream-videos/dash-video/${file.name}"
}
}
}
Don't let the size of these Assembly Instructions worry you. Let's break it down.
In the first Step, the /upload/handle Robot's usage is clear. We utilize it to get a video from an end-user.
Secondly, the /video/encode Robot encodes the
uploaded video into HLS and MPEG-DASH at the hls-encode and dash-encode Steps,
respectively. These are necessary Steps for the
/video/adaptive Robot.
Thirdly, since we're going to be working with a video player, it would be useful if we could easily
extract a thumbnail from our video. Luckily, that's exactly what the
/video/thumbs Robot is doing at the thumbnailed
Step ✨
Now we reach the star of the show - the /video/adaptive
Robot. In the Assembly, we have split its tasks up into two separate
Steps: hls-adaptive and dash-adaptive. Let's take a look at the parameters this
Robot is given. They take their respective encoded videos and generate a .m3u8 and
.mpd playlist. MPEG-DASH and HLS protocol files are composed of a playlist (.m3u8 or .mpd)
and a sequence of segments. The playlist file simply looks for the associated segments necessary
for streaming the video and plays through them sequentially.
Using segment_duration, we can define the maximum amount of time each segment of the streaming
video will have. This can be an important thing to consider when thinking about your user's data and
download capacity. Another quirk of these protocols is that we need to make sure their segments are
always in the same directory as their playlist, otherwise the playlists will be looking for segments
they can't find. Thankfully, at the last overall Step, the
/google/store Robot sets the path for the MPEG-DASH
and HLS files to a defined path like - stream-videos/dash-video/${file.name}. This means that
everything should be bunched together nicely. Just be sure to set up storage.objects.create
permissions in your Bucket. We also store the
thumbnail using the same Robot.
The minimal DASH branch above encodes video only. For a DASH stream with sound, add an audio rendition and bundle it with the video as shown in our MPEG-DASH demo.
A proof of concept via React
Griffith is a video player for React that is very easy to get
started with. It takes props containing the properties of the player and an object sources
consisting of the URL of the video along with its format.
var sources = {
hd: {
bitrate: 905,
size: 10105235,
duration: 0,
width: 1280,
height: 720,
play_url: 'https://storage.googleapis.com/yourbucket/stream-videos/hls-video/my_playlist.m3u8',
},
}
This historical proof of concept checks native media support with the following code. It does not detect playback support supplied by JavaScript libraries through Media Source Extensions; use your player's capability checks when integrating such a library.
function checkCompatibility() {
var compatibility = document.createElement('video')
if (compatibility.canPlayType('application/x-mpegURL')) {
return build_sources('m3u8', 'my_playlist')
}
if (compatibility.canPlayType('application/dash+xml')) {
return build_sources('mpd', 'my_playlist')
}
console.log('No native streaming support found')
}
You can find my basic implementation here. The /video/adaptive Robot really does streamline the generation of streaming media. As people consume more videos over the internet, we're confident that this Robot could prove to be a useful utility for those looking for a simple and sleek solution.
For further reading, our demo: Make video compatible for all devices may interest you as it illustrates how to mix and match this with other formats, depending on what the playback device supports, and provides sample code for a non-React player: Plyr.