# Adaptive bitrate (ABR)

Tip: open your browser's developer console and use the `player` and `THEOplayer` variables to interact with this demo.

ABR strategy

\[ ]`performance`\[ ]`quality`\[x]`bandwidth`

Start with a quality based on the bandwidth measured during previous sessions.

Initial bitrate (`metadata.bitrate`, in bps):e.g. 2000000Apply and reload

```js
player.abr.strategy = {
  type: 'bandwidth'
};
```

Qualities

| Current strategy                | - |
| ------------------------------- | - |
| Initial quality (chosen by ABR) | - |
| Active quality                  | - |
| Bandwidth estimate              | - |

| Available quality                 | Bandwidth |
| --------------------------------- | --------- |
| Press play to load the qualities. |           |

This example shows how the [ABR strategy](https://docs-preview.optiview.dolby.com/pr-894/theoplayer/v11/api-reference/web/types/ABRStrategy) affects the quality that the player picks when it starts playing a stream.

* **`performance`**: start with a lower quality, so the video starts playing as fast as possible.
* **`quality`**: start with the highest quality, for the best visual quality from the start.
* **`bandwidth`** (default): start with a quality based on the bandwidth that was measured in previous sessions.

You can also pass ABR metadata with the strategy. The `metadata.bitrate` property sets the initial bitrate (in bits per second), which the player uses to pick its first quality before it has measured the actual bandwidth.

Choose a strategy, optionally enter an initial bitrate, and click **Apply and reload** to reload the stream with the new strategy. The box below the player lists the available qualities, the initial quality chosen by the ABR strategy, and the quality that is currently playing.

Code

demo.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Adaptive bitrate (ABR)</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet" />
    <style>
      html,
      body {
        margin: 0;
        padding: 0;
      }

      theoplayer-default-ui:not(:defined) {
        display: inline-block;
        box-sizing: border-box;
      }

      theoplayer-default-ui {
        width: 100%;
        aspect-ratio: 16 / 9;
        font-family: 'Noto Sans', sans-serif;
        background: #000;
      }
    </style>
    <script src="https://cdn.theoplayer.com/dash/theoplayer/THEOplayer.js"></script>
    <script nomodule src="https://unpkg.com/@theoplayer/web-ui@2/polyfills"></script>
    <script async src="https://unpkg.com/@theoplayer/web-ui@2"></script>
  </head>
  <body>
    <!--
      libraryLocation: For demonstration purposes, we use the theoplayer.com CDN.
      For production use, we recommend hosting THEOplayer yourself
      and changing this (as well as the <script> tags above)
      to point to THEOplayer's location on your own website.

      licenseUrl: Change this to point to your THEOplayer license file.
      Alternatively, replace it with a "license" property whose value is your THEOplayer license itself.
    -->
    <theoplayer-default-ui
      configuration='{"libraryLocation":"https://cdn.theoplayer.com/dash/theoplayer/","licenseUrl":"../../../../theoplayer-license.txt","abr":{"strategy":"bandwidth"}}'
      source='{"sources":{"src":"https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny_metadata.m3u8","type":"application/x-mpegurl"},"poster":"https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg","metadata":{"title":"Big Buck Bunny"}}'
    ></theoplayer-default-ui>
    <script src="../utils.js"></script>
    <script>
      onPlayerReady((player) => {
        const source = player.source;
        let initialQuality;

        function describeQuality(quality) {
          return quality && { id: quality.id, width: quality.width, height: quality.height, bandwidth: quality.bandwidth };
        }

        function reportState() {
          const track = Array.from(player.videoTracks).find((track) => track.enabled);
          sendToParent('abr', {
            strategy: player.abr.strategy,
            qualities: track ? Array.from(track.qualities).map(describeQuality) : [],
            initialQuality: describeQuality(initialQuality),
            activeQuality: describeQuality(track && track.activeQuality),
            bandwidthEstimate: player.metrics.currentBandwidthEstimate,
          });
        }

        player.videoTracks.addEventListener('addtrack', (event) => {
          const track = event.track;
          track.addEventListener('activequalitychanged', (event) => {
            // The first quality chosen after loading a source is picked by the ABR strategy.
            if (!initialQuality) {
              initialQuality = event.quality;
            }
            reportState();
          });
          reportState();
        });
        player.addEventListener(['progress', 'emptied'], reportState);

        // Change the ABR strategy, then reload the source to see which initial quality it picks.
        onParentMessage('abr-strategy', ({ strategy }) => {
          player.abr.strategy = strategy;
          initialQuality = undefined;
          player.source = source;
          player.play();
          reportState();
        });

        reportState();
      });
    </script>
  </body>
</html>
```
