Some extra background: I worked on a predecessor of this with Matthias about two years back. We had to build a web video player with a lot of advanced capabilities, and found that no open source or commercial player framework would give us what we needed as developers to deliver something really good. I've since moved abroad and haven't been involved with this directly.
A lot of the ideas we came up with made it into this project, and what Matthias did differently in this iteration (like adding Typescript and improving how you write extensions) look really good. You can consider this to be an alternative to video.js, for example, but with easier ways to build advanced extensions without having to fall back to pretty oldschool ways of doing JS.
Matthias' default UI for example is built in React, but there's nothing stopping you from not using his UI extension and building your own that works however you want. Because of the heavy use of Webpack bundle splitting, if you don't use the built-in UI React won't even be loaded, and that approach is core to how this is designed.
2 & 3. According to me, the volume button seems off in mobile. I think I'll remove it completely on mobile devices, people are used to lowering the volume with the physical buttons (assumption). What do you think?
> 2 & 3. According to me, the volume button seems off in mobile. I think I'll remove it completely on mobile devices, people are used to lowering the volume with the physical buttons (assumption). What do you think?
To facilitate mobile development of the library its probably the best approach, at least for now and you can revisit the issues later on :)
Mobile is (typically) a single mode application situation, as in, there's no need to control volumes of simultaneous applications separately. It would also be easy to argue that almost no-one needs that feature.
- Add possibility to watch the player on landscape mode even when this option is disabled in the device settings, I'm not sure it is possible but if so it would be a great feature :P
Do you mean something like: "force the player in landscape mode when you hit the fullscreen button on a mobile device?". I like it, YouTube does that with it's mobile apps and I find it practical.
> Do you mean something like: "force the player in landscape mode when you hit the fullscreen button on a mobile device?". I like it, YouTube does that with it's mobile apps and I find it practical.
Exactly, I also find it useful and get annoyed when I have to manually activate landscape mode on my device to get the player to use the whole screen (I have auto rotation disabled most of the time).
If all you want to do is play a simple unencrypted video without ads, a <video> tag is indeed all you need. As soon as you start working with adaptive streaming (DASH/HLS), need ads, need a more advanced UI or need better metrics, you'll need some sort of base video player 'framework' to deal with those things. This provides that, similar to video-js, but in a more modern way.
It's impossible to play DRM video without heavy JS (except in Safari). Netflix probably uses a similar library to Shaka for their DASH streams.
HTML5 video is only really simple if you want to just play MP4's with H264 encodings. For everything else you're going to want a wrapper to deal with compatibility checks, smoothing out cross-browser bugs, deal with ads, set up DRM, ...
The <video> tag for instance doesn't support MPEG-DASH and HLS (outside of Edge and Safari). So if you want to do DRM or live streaming, that isn't supported. Thats why this project bundles shaka-player and hls.js
Two years ago when we checked out the DASH and HLS support in Edge it turned out to be so unreliable we still just went with Shaka instead.
Fun fact: besides FairPlay compatibility, HLS in Safari is way more annoying to deal with than HLS via hls.js in browsers that don't natively support it. Safari provides you way less information about what's happening stream/buffer wise, and if you work with HLS event streams you need a ton of hacks to make it behave correctly.
Yes, that is what is used with MPEG-DASH and HLS too. But none of the DRM systems implemented (beyond ClearKey) is used on just pure MP4 files. So while EME works in either case, nobody is doing it with the file formats natively supported. It's pretty much always in combination with https://developer.mozilla.org/en-US/docs/Web/API/Media_Sourc...
Video newbie question here. Is it just me or is the html5 video player is really slow? Does using a framework like this help with performance/buffering/streaming? Like skipping video is a common use-case where performance is really key..
html5 video out of the box doesn't consistently provide support for most sorts of adaptive bitrate streaming (HLS/Dash being the pre-eminent ones). Using a single bitrate mp4 has no way to adjust for performance and is usually going to be less than ideal.
Noting that most player still use the video tag under the hood, but a lot of functionality has been pushed to the Media Extensions layer for different formats of video.
Using HLS with HLS.js or Dash with Dash.js is the "Simple" way of adding adaptive bitrate support to HTML5 Video tag for better performance. After that its your video delivery pipeline.
> html5 video out of the box doesn't consistently provide support for most sorts of adaptive bitrate streaming (HLS/Dash being the pre-eminent ones)
Can you elaborate on this? I use <video> to debug HLS issues all the time. Is there something specific that straight-up video tag won't do?
If there are edge cases I'm sure I haven't seen them, because personally I'm only ever using HTML as basically a control group when reproducing bug reports from native video player stuff.
HLS Isn’t supported natively in a lot of browsers. Chrome doesn’t. It’s pretty easy to shim with Media Extensions so it’s fine to use but just sticking it as a src property in a lot of browsers it won’t work.
Personally I think that the Media Extensions API is going to be the primary mechanism for adding new codecs and transports moving forward as opposed to having the browsers need to implement all the options.
Looks pretty good, at first glance I miss the functionality to pause/un-pause by clicking on the video. I believe this is a pretty common functionality that you should consider implementing.
Noticed it too, I have no idea yet. I use a wrapper around the native Fullscreen API's (https://github.com/sindresorhus/screenfull.js/) and it doesn't do anything fancy. Interesting, I'll have a look at it but I'll put it lower on my prio list if you don't mind.
One thing that I would love to have on mobile is an adaptive (?) video seeking. So you touch the "video cursor" and then move: the x axis is for seeking, but y axis is for sensitivity. Moving a finger along the bar (y = 0) is as things are currently - go to the right edge to seek till the end of the video. However moving it along the top edge of the video (y = 720) would only seek in terms of 5 seconds for example.
The scale between y=0 and y=720 wouldn't have to be linear.
Thank you! Why such a useful thing was not copied by everyone (especially by YouTube and Netflix) is beyond me. I have to give Apple the credit for those tiny details.
I haven't been able to find an exact match, but this overly-broad-yet-approved patent might encompass it, and the filing date seems to fit: https://patents.google.com/patent/US9069452
Nice work! As someone that uses https://github.com/sampotts/plyr in one of my projects (and react-plyr), what are the main differences between the two players & designs?
Plyr is really good and has an impressive UI and accessibility. But there is no way extend the player with new complex functionality or a tighter integration with Shaka/hls.js/other ad providers/...
I think Plyr can be seen as a better and unified UI on top of a <video> element, while this is an extensible player 'framework'.
I can't speak for plyr as I am not familiar with their project. What I like about indigo is the way modules are structured, the initial file (indigo-player.js) loads the needed code in order to provide playback, it's basically a mono repo. I've spent a fair amount of time on state management too, meaning you have a well defined & standardized API no matter whether you play DASH/HLS or use FreeWheel / Google IMA ads.
In addition to other feedback in this thread, I'd also want the Volume icon to change: show muted state / volume level state without showing the slider. YouTube does this well.
Your example doesn't actually have an element with id "player" in it, even though you getElementById('player'). Is that a broken example, or am I missing something?
Why not use something like video.js which already has a number of pluggable backend and third party plugins supported. Just for the lack of TypeScript?
The way plugins/backends work in this is fundamentally different. Video.js at it's core does very little and doesn't provide a very strict API. The result tends to be that every ad provider you add on does things slightly differently. If you want to build advanced metrics on top of a video.js instance that can use two different ad providers, it's likely you'll have to manually fix up the ad events to make them track correctly. This project includes base API definitions for all important ad events that other extensions can hook into with set guarantees on how they'll behave.
Another thing is how extensions are dealt with here. In video.js, if you need DASH support, you'll add videojs-contrib-dash and dash.js. Together that's at least 500kB of JS extra. Even in Safari where you won't need any of those, you'll have to do some hacking to avoid loading that JS for no reason. In Indigo here, dynamic bundle loading is core to the extension setup. When reading a config there's a lightweight check to determine what library to use for playback (if one is needed at all), and it'll only be loaded when it's necessary. In Safari, where you generally don't need any libraries, nothing will be loaded. In Chrome, you'll load Shaka when you want to play DASH, and hls.js when you want to player HLS. Indigo makes that very easy (and a default), video.js makes it hard.
These are advanced problems though. You're not likely to hit these issues with video.js if all you do is play a simple stream without DRM and with one single ad provider. But the solutions to those issues that are a core part of this project actually provide benefits in all situations and make development easier, so it's a net win for everyone in the end.
Some extra background: I worked on a predecessor of this with Matthias about two years back. We had to build a web video player with a lot of advanced capabilities, and found that no open source or commercial player framework would give us what we needed as developers to deliver something really good. I've since moved abroad and haven't been involved with this directly.
A lot of the ideas we came up with made it into this project, and what Matthias did differently in this iteration (like adding Typescript and improving how you write extensions) look really good. You can consider this to be an alternative to video.js, for example, but with easier ways to build advanced extensions without having to fall back to pretty oldschool ways of doing JS.
Matthias' default UI for example is built in React, but there's nothing stopping you from not using his UI extension and building your own that works however you want. Because of the heavy use of Webpack bundle splitting, if you don't use the built-in UI React won't even be loaded, and that approach is core to how this is designed.
You're more than welcome to contribute! Good ol' days!
Amazing job, I have a few suggestions on how to improve its UX:
- Clicking the video should pause/play;
- Clicking the volume button on mobile when the volume bar is hidden should not mute the video, instead it should just show the volume bar;
- Interacting with the volume UI on mobile should reset the time until the UI hides, the UI hides while I'm ajusting the volume.
These are a few points I think should be improved, I'd love to hear others opinions on whether or not these make sense :)
Keep the great work!
Thanks for the suggestions!
1. Absolutely, it's on my radar.
2 & 3. According to me, the volume button seems off in mobile. I think I'll remove it completely on mobile devices, people are used to lowering the volume with the physical buttons (assumption). What do you think?
> 2 & 3. According to me, the volume button seems off in mobile. I think I'll remove it completely on mobile devices, people are used to lowering the volume with the physical buttons (assumption). What do you think?
To facilitate mobile development of the library its probably the best approach, at least for now and you can revisit the issues later on :)
Just to jump on these, traditionally hitting the space bar will also toggle play/pause.
+1 for conditionally removing the volume bar.
Mobile is (typically) a single mode application situation, as in, there's no need to control volumes of simultaneous applications separately. It would also be easy to argue that almost no-one needs that feature.
Another suggestion:
- Add possibility to watch the player on landscape mode even when this option is disabled in the device settings, I'm not sure it is possible but if so it would be a great feature :P
Do you mean something like: "force the player in landscape mode when you hit the fullscreen button on a mobile device?". I like it, YouTube does that with it's mobile apps and I find it practical.
> Do you mean something like: "force the player in landscape mode when you hit the fullscreen button on a mobile device?". I like it, YouTube does that with it's mobile apps and I find it practical.
Exactly, I also find it useful and get annoyed when I have to manually activate landscape mode on my device to get the player to use the whole screen (I have auto rotation disabled most of the time).
I'd vote for this - toggling landscape manually is icky. If I press fullscreen the default for video should be landscape mode always.
These two comments are fixed and will be available in a new version in a few minutes!
How is this preferable to using the <video> tag?
If all you want to do is play a simple unencrypted video without ads, a <video> tag is indeed all you need. As soon as you start working with adaptive streaming (DASH/HLS), need ads, need a more advanced UI or need better metrics, you'll need some sort of base video player 'framework' to deal with those things. This provides that, similar to video-js, but in a more modern way.
Is that really true? Netflix uses html5 video to stream. The use case for a pure js player must be fairly small
edit: my bad, I thought the project in the OP didn't use html5 video at all, I see how that it is a wrapper around it.
It's impossible to play DRM video without heavy JS (except in Safari). Netflix probably uses a similar library to Shaka for their DASH streams.
HTML5 video is only really simple if you want to just play MP4's with H264 encodings. For everything else you're going to want a wrapper to deal with compatibility checks, smoothing out cross-browser bugs, deal with ads, set up DRM, ...
The <video> tag for instance doesn't support MPEG-DASH and HLS (outside of Edge and Safari). So if you want to do DRM or live streaming, that isn't supported. Thats why this project bundles shaka-player and hls.js
Two years ago when we checked out the DASH and HLS support in Edge it turned out to be so unreliable we still just went with Shaka instead.
Fun fact: besides FairPlay compatibility, HLS in Safari is way more annoying to deal with than HLS via hls.js in browsers that don't natively support it. Safari provides you way less information about what's happening stream/buffer wise, and if you work with HLS event streams you need a ton of hacks to make it behave correctly.
You can use DRM and html5 video, https://en.wikipedia.org/wiki/Encrypted_Media_Extensions
" This allows the use of HTML5 video to play back DRM-wrapped content such as streaming video services "
Yes, that is what is used with MPEG-DASH and HLS too. But none of the DRM systems implemented (beyond ClearKey) is used on just pure MP4 files. So while EME works in either case, nobody is doing it with the file formats natively supported. It's pretty much always in combination with https://developer.mozilla.org/en-US/docs/Web/API/Media_Sourc...
Video newbie question here. Is it just me or is the html5 video player is really slow? Does using a framework like this help with performance/buffering/streaming? Like skipping video is a common use-case where performance is really key..
html5 video out of the box doesn't consistently provide support for most sorts of adaptive bitrate streaming (HLS/Dash being the pre-eminent ones). Using a single bitrate mp4 has no way to adjust for performance and is usually going to be less than ideal.
Noting that most player still use the video tag under the hood, but a lot of functionality has been pushed to the Media Extensions layer for different formats of video.
Using HLS with HLS.js or Dash with Dash.js is the "Simple" way of adding adaptive bitrate support to HTML5 Video tag for better performance. After that its your video delivery pipeline.
> html5 video out of the box doesn't consistently provide support for most sorts of adaptive bitrate streaming (HLS/Dash being the pre-eminent ones)
Can you elaborate on this? I use <video> to debug HLS issues all the time. Is there something specific that straight-up video tag won't do?
If there are edge cases I'm sure I haven't seen them, because personally I'm only ever using HTML as basically a control group when reproducing bug reports from native video player stuff.
https://www.lambdatest.com/HTTP-Live-Streaming(HLS)
HLS Isn’t supported natively in a lot of browsers. Chrome doesn’t. It’s pretty easy to shim with Media Extensions so it’s fine to use but just sticking it as a src property in a lot of browsers it won’t work.
Personally I think that the Media Extensions API is going to be the primary mechanism for adding new codecs and transports moving forward as opposed to having the browsers need to implement all the options.
Thanks - I've been using "Plyr" [0] for some personal video projects. Interesting to compare features and see this one done in TS.
[0] https://github.com/sampotts/plyr
Looks pretty good, at first glance I miss the functionality to pause/un-pause by clicking on the video. I believe this is a pretty common functionality that you should consider implementing.
Hey, thanks! You're totally right, I have some time during the weekend to implement this.
As long as you're taking feedback (I don't mean to be overwhelming!) - any idea why exiting fullscreen resets the scroll position to 0?
Try scrolling down to the player, entering fullscreen, hitting Escape, you're back to the top of the page.
Noticed it too, I have no idea yet. I use a wrapper around the native Fullscreen API's (https://github.com/sindresorhus/screenfull.js/) and it doesn't do anything fancy. Interesting, I'll have a look at it but I'll put it lower on my prio list if you don't mind.
One thing that I would love to have on mobile is an adaptive (?) video seeking. So you touch the "video cursor" and then move: the x axis is for seeking, but y axis is for sensitivity. Moving a finger along the bar (y = 0) is as things are currently - go to the right edge to seek till the end of the video. However moving it along the top edge of the video (y = 720) would only seek in terms of 5 seconds for example.
The scale between y=0 and y=720 wouldn't have to be linear.
iOS's default video player controls have done this for eight years: https://lifehacker.com/5811660/how-to-control-the-audio-and-...
Thank you! Why such a useful thing was not copied by everyone (especially by YouTube and Netflix) is beyond me. I have to give Apple the credit for those tiny details.
Probably patented.
Disgusting, but probably true.
I haven't been able to find an exact match, but this overly-broad-yet-approved patent might encompass it, and the filing date seems to fit: https://patents.google.com/patent/US9069452
You would get this for free if people would stop reinventing the wheel and let the platform handle the video playback interface.
If I'm understanding you correctly, that's how iOS's native video player works.
Nice work! As someone that uses https://github.com/sampotts/plyr in one of my projects (and react-plyr), what are the main differences between the two players & designs?
Plyr is really good and has an impressive UI and accessibility. But there is no way extend the player with new complex functionality or a tighter integration with Shaka/hls.js/other ad providers/...
I think Plyr can be seen as a better and unified UI on top of a <video> element, while this is an extensible player 'framework'.
Excellent answer - I get it now. Thank you!
I can't speak for plyr as I am not familiar with their project. What I like about indigo is the way modules are structured, the initial file (indigo-player.js) loads the needed code in order to provide playback, it's basically a mono repo. I've spent a fair amount of time on state management too, meaning you have a well defined & standardized API no matter whether you play DASH/HLS or use FreeWheel / Google IMA ads.
Edit: the state interface can be found here: https://github.com/matvp91/indigo-player/blob/master/src/ext...
Really nice UI. Simple, neutral and sharp.
In addition to other feedback in this thread, I'd also want the Volume icon to change: show muted state / volume level state without showing the slider. YouTube does this well.
Thanks for the feedback, this small feature was already part of my roadmap. :) Will hit production soon!
I've added different volume icons based on the current volume, shall hit production anytime!
Your example doesn't actually have an element with id "player" in it, even though you getElementById('player'). Is that a broken example, or am I missing something?
I'm sorry, it was wrong on the Github page, fixed.
Why not use something like video.js which already has a number of pluggable backend and third party plugins supported. Just for the lack of TypeScript?
The way plugins/backends work in this is fundamentally different. Video.js at it's core does very little and doesn't provide a very strict API. The result tends to be that every ad provider you add on does things slightly differently. If you want to build advanced metrics on top of a video.js instance that can use two different ad providers, it's likely you'll have to manually fix up the ad events to make them track correctly. This project includes base API definitions for all important ad events that other extensions can hook into with set guarantees on how they'll behave.
Another thing is how extensions are dealt with here. In video.js, if you need DASH support, you'll add videojs-contrib-dash and dash.js. Together that's at least 500kB of JS extra. Even in Safari where you won't need any of those, you'll have to do some hacking to avoid loading that JS for no reason. In Indigo here, dynamic bundle loading is core to the extension setup. When reading a config there's a lightweight check to determine what library to use for playback (if one is needed at all), and it'll only be loaded when it's necessary. In Safari, where you generally don't need any libraries, nothing will be loaded. In Chrome, you'll load Shaka when you want to play DASH, and hls.js when you want to player HLS. Indigo makes that very easy (and a default), video.js makes it hard.
These are advanced problems though. You're not likely to hit these issues with video.js if all you do is play a simple stream without DRM and with one single ad provider. But the solutions to those issues that are a core part of this project actually provide benefits in all situations and make development easier, so it's a net win for everyone in the end.
Thanks for this response, it gives us (newbies) a better insight for choose a proper tool...
Does it support subtitles ? I've been looking for a video player that supports uploading subtitles, or loading then from a url
WebVTT, yes. https://matvp91.github.io/indigo-player/#/Configuration?id=c...
When will we move on from Big Buck Bunny?
Hopefully never
really awesome.