Without Adaptive Streaming
Implementing an option for the video.js player shouldn't take long. In fact, there are two plugins which do exactly what we need:
There are of course other players like LibreVideoJS, but I think sticking to video.js and adding one of these plugins is better. We can also look at them (worst case).
I'd like to create a sample project and get used to working with these plugins, and then I will implement the same for GMG.
After fiddling with CDNs and different versions of video.js to get video-resolution-switcher to work properly, I resorted to adding files from the live demo by kmoskwiak (author). The documentation says that it works properly with video.js v5, but apparently not with all v5 versions (for example,
dynamicLabel option wasn't working with video.js v5.19). You can just download the html file here, and see how it works!
I wasn't very satisfied with video-resolution-selector to be honest. The docs convey that the plugin works with video.js v4.7.3 or higher, but it didn't work well with v5 or v6. The former plugin also includes a gear symbol (when
dynamicLabel: False; pretty much like in YouTube) as the option button which is kinda cool. We can of course use our own icon for the button in video-resolution-selector if needed. But, I feel video-resolution-switcher is more complete.
I'd personally prefer the former since it has more downloads, and is recommended in video.js plugins list.
With Adaptive Streaming
The use case described here is very much the same as the YouTube's feature where a lower resolution of the video is selected if the user's network speed is low. But, I'd like to do this only at the start of the video.
Well, there are a few ways to achieve adaptive streaming:
- HLS (by Apple)
- Smooth Streaming (by Microsoft)
- MPEG DASH
As you mentioned in the IRC, HLS (and Smooth Streaming) is pretty much out of the question because:
- It is slowly getting deprecated (Apple is investing more time on MPEG DASH itself)
- It is codec-specific (H.264 with AAC) as mentioned here. And, we are currently using WebM format (VP8 and Vorbis to be specific).
So, we are left with MPEG DASH as our last option.
- Dash.js (is the official Dash Industry Forums Reference and Production player)
- Shaka (is the open source dash player from Google)
We donot need to do much at the client side as these players will take care of decoding stuff and rendering them if we point them to the .mpd file (in the server). I probably have to spend considerable amount of time trying to learn how to use them.
Well, the real problem is in the server side. Most of the required information can be found here.
We have to create the .mpd file at the server with all the fragments for different resolutions of video.
So, our task at the server end is split into 3 sections:
- Converting the video into a specific format
- Fragmenting the video (creating segments of various bit rates and resolutions)
- Creating the .mpd file (XML doc which has all the information about the fragments)
After doing a bit of research, I found out that FFmpeg has support for webm and MP4 formats.
For MP4 (usually with MP4Box/Bento4):
- Part 1 and Part 2.
Other than FFmpeg, x264 (with MP4Box) is also used:
But, I have not found any support for DASH implementation in Gstreamer. I saw this link, but didn't really understand much.
Q. Can we use other open source libraries (with Gstreamer)? (like FFmpeg) I realize that is far-fetched
Q. Can you also confirm that there is no support from Gstreamer?
Q. If there is support for MP4 fragments in Gstreamer, can we shift to MP4 from WebM?
I'm planning to implement the normal resolution switcher using the help of those plugins. I'm hoping it won't take long.
I also realize that DASH implementation is slightly complex, even if some direct solution exists. A lot of change has to be done to the
Transocder Class to get things working. But, if I implement the easy solution quickly enough, is there a possibility that we can work on DASH implementation?