npm package: @github/media-players
Description: <p align="center">   <img src="https://cloud.githubusercontent.com/assets/98681/24211275/c4ebd04e-0ee8-11e7-8606-061d656a42df.png" width="60" height="60">
Author: Nikola Stamatovic
Latest version: 1.1.1

<p align="center">
  <img src="https://cloud.githubusercontent.com/assets/98681/24211275/c4ebd04e-0ee8-11e7-8606-061d656a42df.png" width="60" height="60">

  <h1 align="center">GitHub Media Players</h1>
</p>

Well hello hello! 👋 And welcome to the amazing world of GitHub's very own custom HTML `Video` and `Audio` player.✨ Written to fully utilise the power of the amazing GitHub Catalyst.

Why we did it, you might ask?

* We want to have full control over the player and it's optimisation
* With that said, we want a GitHub branded player that can be easily adapted to GitHub's different sub-brands
* And seriously, embedding third party players is lazy and brings performance costs and security concerns

<p align="center">
  <h3 align="center"><a href="https://media-players.github.com">View the DEMO &rarr;</a></h3>
</p>

### Video Player `<video-player>`

<br>

![Screenshot 2022-12-15 at 00 02 16](https://user-images.githubusercontent.com/1429864/207734614-f1cb99ee-46bc-4703-adba-71f6444ec657.jpg)

<br><br>

### Audio Player `<audio-player>`

<br>

![Screenshot 2022-12-15 at 00 02 51](https://user-images.githubusercontent.com/1429864/207734532-c74aab2e-1fd6-4923-a4b7-fc0912afe4f9.jpg)

<br><br>

## 🧩 Features

| | Video Player | Audio Player | |
|---|---|---|---|
| Play/Pause | ✅ | ✅ | |
| Seek bar | ✅ | ✅ | |
| Buffered progress visualisation | ✅ | ✅ | |
| Buffering state visualisation | ✅ | ✅ | |
| Skip forward / backward | no UI<sup>*</sup> <br>keyboard controlled only | ✅ | |
| Mute toggle | ✅ | no UI<sup>*</sup> | state memorised in visitor browser as an accessibility feature |
| Volume control | ✅ | no UI<sup>*</sup> | state memorised in visitor browser as an accessibility feature |
| Fullscreen | ✅ | / | |
| Download link | no UI<sup>*</sup> | ✅ | |
| Closed captions toggle | ✅ | / | state memorised in visitor browser as an accessibility feature |
| Subtitles `vtt` | ✅ | / | currently supports only one subtitle (language), can support more but a subtitle selector needs to be implemented |
| Keyboard controls | ✅ | except mute and volume | requires initial interaction with the video/audio to become active |
| Live streaming | ✅ | ✅ | can work with HLS and DASH-MPEG both live and on demand links. ⚠️ Please see the [Live streaming guide](https://github.com/github/media-players/edit/main/README.md#live-streaming-guide) |
| Optimised video poster | ✅ | / | use `<picture>` element with optimised variety of sources as a poster |
| Themes 🎨 | ✅ | ✅ | easily create themes by overriding CSS variables |

**<sup>*</sup>no UI** - means that the feature exists in the code but we will need to iterate the design, especially for mobile screens in order for this UI to be implemented.

### ⌨️ Keyboard controls

* Play/Pause <kbd>Space</kbd>
* Skip forward <kbd>Arrow Right</kbd>
* Skip backward <kbd>Arrow Left</kbd>
* Volume Up <kbd>Arrow Up</kbd>
* Volume Down <kbd>Arrow Down</kbd>
* Mute toggle <kbd>M</kbd>
* Fullscreen toggle <kbd>F</kbd>
* Captions toggle <kbd>C</kbd>

These are the most common keyboard controls that appear on platforms like Youtube, Vimeo and other popular custom players.

<br>

### 📹 Live streaming guide

#### [HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) support

Supported natively only in **Safari**, needs a [hls.js](https://www.npmjs.com/package/hls.js) third party dependancy for HLS to be enabled for Chrome(ium) and Firefox browsers with a few [lines of code](https://github.com/github/media-players/blob/360f86f588e36240009527222fe759ef427e0c10/_scripts/github/marketing/audio-player.ts#L60-L68) in the `onConnected` callback.

⚠️ **Note:** Add HLS support only if and where needed - this dependancy will increase the bundle size and reduce the page performance.

To enable HLS for Chrome(ium) and Firefox, follow these easy steps steps:

1. `npm install --save hls.js`
2. `import Hls from 'hls.js'` into `_scripts/github/marketing/audio-player.ts` [#L2](https://github.com/github/media-players/blob/360f86f588e36240009527222fe759ef427e0c10/_scripts/github/marketing/audio-player.ts#L2)
3. Paste the following code into `connectedCallback` callback here `_scripts/github/marketing/audio-player.ts`. [#61,#68](https://github.com/github/media-players/blob/360f86f588e36240009527222fe759ef427e0c10/_scripts/github/marketing/audio-player.ts#L61-L68)

```javascript
const hlsSource = this.media.querySelector<HTMLElement>('source[type="application/x-mpegurl"], source[type="application/vnd.apple.mpegurl"], source[type="audio/mpegurl"]')
if (hlsSource && !this.media.canPlayType('application/vnd.apple.mpegurl') && Hls && Hls.isSupported()) {
  const hls = new Hls()
  const src = hlsSource.getAttribute('src')
  if (!src) return
  hls.loadSource(src);
  hls.attachMedia(this.media);
}
```

#### [MPEG-DASH](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP) support

Not supported natively by browsers. Third party [dash.js](https://github.com/Dash-Industry-Forum/dash.js/) dependancy is needed for this type of protocol to work.

⚠️ **Note:** Add MPEG-DASH support only if and where needed - this dependancy is ~800KB in size and minified!!!

To enable MPEG-DASH, follow these easy steps steps:

1. Download `dash.all.min.js` from https://github.com/Dash-Industry-Forum/dash.js/
2. Include `<script async src="assets/js/dash.all.min.js" ></script>` wherever you want - P.S. I didn't succeed in using this as a NPM package, their guide was poor and after failing to include it's `index.js` from `node_modules` I stopped trying 😬
3. Add `data-dashjs-player` attribute to the `<video>` element of the `<video-player>` template

<br><br>

## 🌎 Browser support

Tested in BrowserStack

### Desktop

* Safari 13.1+
* Chrome 80+ / Edge 80+
* Firefox 78+
* Opera 80+

### Mobile

Tested and working on a low-end Android phone: Nokia 3; Android 9; Chrome 80

* iOS Safari 13.4+
* Chrome 80+
* Firefox 78+
* Samsung Internet 17+
* UC Browser ❌ (whatever this is)

<br><br>

## 💻 Local Development

*New to running code on your laptop here at GitHub? Talk to @github/marketing-platform-services and we'll help get you sorted before diving into these setup instructions.*

Install this project's dependencies by running the following from Terminal:

```
$ script/bootstrap
```

To start the server and view this site locally, run:

```
$ script/server
```

This will compile the structure of the site for you and start a local server at <http://localhost:4000/>. Jekyll will watch HTML updates for changes, automatically rebuilding the site as needed.

Then open a new Terminal window and run:

```
$ npm run watch
```

This will run Rollup with a watch option and compile and watch for changes of the SASS and JS/TS files. Located in `_sass` and `_scripts` respectively.

<br>

----

#### Dependencies

* [@github/catalyst](https://www.npmjs.com/package/@github/catalyst) - `1.6.0+`
* [@primer/css](https://www.npmjs.com/package/@primer/css) - `19.0.0+`

----

<br>

#### Structure

##### VideoPlayer
```
_includes/video-player.html
```

##### AudioPlayer
```
_includes/audio-player.html
```

<br>

#### Styles

```
_sass/github/marketing/components/media-players.scss
```

<br>

#### Scripts

`VideoPlayer` inherits all of the `AudioPlayer` functionality and adds only features related to video, like fullscreen, hiding controls, captions, poster and a big overlaying play button.

##### VideoPlayer
```
_scripts/github/marketing/audio-player.ts
```

##### AudioPlayer
```
_scripts/github/marketing/video-player.ts
```

----

<br>

#### New to @github/catalyst?

GitHub Catalyst is an amazing framework that minimises coding effort when creating custom elements. It also makes the code look much more cleaner and therefore more readable and easier to maintain.

Most importantly it allows us to lazy define the custom element so it's constructed only when the element becomes available in the DOM:

```javascript
  lazyDefine('audio-player', () => import('./github/marketing/audio-player'))
  lazyDefine('video-player', () => import('./github/marketing/video-player'))
```

If you are new to Catalyst, we have included the simplest video player custom element `micro-video-player` as a demo to get you started quickly. It's functionality is basically click to play and click to pause.

```
_includes/micro-video-player.html
```

```
_scripts/github/marketing/micro-video-player.ts
```
<br><br>

## 📝 TO DO:
* [ ] Issue with 206 http response - partial content
* [ ] Accessibility
  * [ ] `VideoPlayer` video download
  * [ ] `VideoPlayer` and `AudioPlayer` playback speed selector
  * [ ] `VideoPlayer` captions language selector
  * [ ] `VideoPlayer` video quality selector - this will need a system to load, probably in an unattached `<video>` element, and replace the existing one so the change would appear on the fly.
* [ ] Integrate analytics
* [ ] `VideoPlayer` iOS fake fullscreen

<br><br>

## 💖 Design Credits

### Audio Player

Initially created for the purposes of [ReadME Project Podcasts](https://github.com/readme/podcast), but is also used in marketing pages like: [/about/diversity/report](https://github.com/about/diversity/report) and [/about/diversity/communities-of-belonging/blacktocats](https://github.com/about/diversity/communities-of-belonging/blacktocats).

Designed by **Matt Lee** [@mattjohnlee](https://github.com/mattjohnlee)

### Video Player

Initially created as a BaM Passion week: August 2022 project and to be included initially in ReadME Project and other marketing pages.

Designed by **Mary He** [@maryhehehe](https://github.com/maryhehehe)