> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beyondwords.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Playback Rate Button

> Toggles the player's playback speed between 1x and 1.5x.

export const WebComponentsDemo = ({name}) => {
  const MOCK_CONTENT = [{
    id: "demo-1",
    title: "How AI voices are changing publishing",
    imageUrl: "/images/player-ui/demo-cover.svg",
    sourceUrl: "https://beyondwords.io",
    sourceId: "demo",
    adsEnabled: false,
    duration: 124,
    audio: [{
      id: "audio-1",
      url: "/images/player-ui/demo-silent.mp3",
      contentType: "audio/mpeg",
      duration: 124
    }],
    video: [],
    summarization: {
      audio: [],
      video: []
    },
    segments: []
  }];
  const MOCK_PLAYLIST = [{
    id: "7a974fb1-1b89-4be3-a25d-4ad286d5305b",
    title: "Part 1: The newsroom shift",
    imageUrl: "/images/player-ui/demo-cover.svg",
    sourceUrl: "https://beyondwords.io",
    sourceId: "demo",
    adsEnabled: false,
    duration: 124,
    audio: [{
      id: "audio-1",
      url: "/images/player-ui/demo-silent.mp3",
      contentType: "audio/mpeg",
      duration: 124
    }],
    video: [],
    summarization: {
      audio: [],
      video: []
    },
    segments: []
  }, {
    id: "129e7681-fa4d-4526-8be9-d27c946a5023",
    title: "Part 2: Voices at scale",
    imageUrl: "/images/player-ui/demo-cover.svg",
    sourceUrl: "https://beyondwords.io",
    sourceId: "demo",
    adsEnabled: false,
    duration: 98,
    audio: [{
      id: "audio-1",
      url: "/images/player-ui/demo-silent.mp3",
      contentType: "audio/mpeg",
      duration: 98
    }],
    video: [],
    summarization: {
      audio: [],
      video: []
    },
    segments: []
  }, {
    id: "e9f2257c-14cf-46c0-bab6-bcaa9e229775",
    title: "Part 3: What comes next",
    imageUrl: "/images/player-ui/demo-cover.svg",
    sourceUrl: "https://beyondwords.io",
    sourceId: "demo",
    adsEnabled: false,
    duration: 152,
    audio: [{
      id: "audio-1",
      url: "/images/player-ui/demo-silent.mp3",
      contentType: "audio/mpeg",
      duration: 152
    }],
    video: [],
    summarization: {
      audio: [],
      video: []
    },
    segments: []
  }];
  const MOCK_ADVERTS = [{
    id: "advert-1",
    type: "native",
    placement: "pre-roll",
    vastUrl: null,
    clickThroughUrl: "https://sponsor.example.com",
    imageUrl: "/images/player-ui/demo-cover.svg",
    textColor: "#ffffff",
    backgroundColor: "#943bfc",
    iconColor: "#ffffff",
    audio: [{
      id: "advert-audio-1",
      url: "/images/player-ui/demo-silent.mp3",
      contentType: "audio/mpeg",
      duration: 8
    }],
    video: []
  }];
  const content = JSON.stringify(MOCK_CONTENT).replace(/'/g, "&#39;");
  const playlistContent = JSON.stringify(MOCK_PLAYLIST).replace(/'/g, "&#39;");
  const adverts = JSON.stringify(MOCK_ADVERTS).replace(/'/g, "&#39;");
  const DEMOS = {
    "play-pause-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-play-pause-button></bw-play-pause-button></bw-player-provider>`,
    "time-indicator": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-time-indicator></bw-time-indicator></bw-player-provider>`,
    "prev-segment-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-prev-segment-button></bw-prev-segment-button></bw-player-provider>`,
    "next-segment-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-next-segment-button></bw-next-segment-button></bw-player-provider>`,
    "prev-seconds-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-prev-seconds-button></bw-prev-seconds-button></bw-player-provider>`,
    "next-seconds-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-next-seconds-button></bw-next-seconds-button></bw-player-provider>`,
    "playback-rate-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-playback-rate-button></bw-playback-rate-button></bw-player-provider>`,
    "content-title": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-content-title></bw-content-title></bw-player-provider>`,
    "call-to-action": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-call-to-action></bw-call-to-action></bw-player-provider>`,
    "download-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-download-button></bw-download-button></bw-player-provider>`,
    "beyondwords-logo": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><bw-beyondwords-logo></bw-beyondwords-logo></bw-player-provider>`,
    "prev-track-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${playlistContent}'><bw-prev-track-button></bw-prev-track-button></bw-player-provider>`,
    "next-track-button": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${playlistContent}'><bw-next-track-button></bw-next-track-button></bw-player-provider>`,
    "playlist": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${playlistContent}'><bw-playlist></bw-playlist></bw-player-provider>`,
    "feature-image": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><div style="width:100%;max-width:20rem;min-width:15rem;overflow:hidden;border-radius:0.5rem"><bw-feature-image></bw-feature-image></div></bw-player-provider>`,
    "progress-bar": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}'><div style="display:flex;flex-direction:row;align-items:center;min-width:30rem"><bw-progress-bar></bw-progress-bar></div></bw-player-provider>`,
    "advert-link": `<bw-player-provider data-show-user-interface="false" data-analytics-consent="none" data-content='${content}' data-adverts='${adverts}' data-advert-index="0"><bw-advert-link></bw-advert-link></bw-player-provider>`,
    "standard-player": `<bw-standard-player-provider data-show-user-interface="false" data-analytics-consent="none" data-project-id="9504" data-content-id="ba00ef51-03ac-4a85-8b98-e45c957e8ef8"><bw-standard-player-bar><bw-standard-play-pause-button></bw-standard-play-pause-button><bw-standard-player-info><bw-standard-call-to-action></bw-standard-call-to-action><bw-standard-duration></bw-standard-duration></bw-standard-player-info><bw-standard-playback-controls><bw-standard-playback-rate-button></bw-standard-playback-rate-button><bw-standard-prev-segment-button></bw-standard-prev-segment-button><bw-standard-next-segment-button></bw-standard-next-segment-button><bw-standard-time-indicator></bw-standard-time-indicator><bw-standard-progress-bar></bw-standard-progress-bar><bw-standard-close-widget-button></bw-standard-close-widget-button></bw-standard-playback-controls><bw-standard-beyondwords-logo></bw-standard-beyondwords-logo></bw-standard-player-bar></bw-standard-player-provider>`,
    "minimal-player": `<bw-minimal-player-provider data-show-user-interface="false" data-analytics-consent="none" data-project-id="9504" data-content-id="ba00ef51-03ac-4a85-8b98-e45c957e8ef8"><bw-minimal-player-bar><bw-minimal-play-pause-button></bw-minimal-play-pause-button><bw-minimal-call-to-action></bw-minimal-call-to-action><bw-minimal-prev-seconds-button data-seconds="10"></bw-minimal-prev-seconds-button><bw-minimal-playback-rate-menu></bw-minimal-playback-rate-menu><bw-minimal-current-time></bw-minimal-current-time></bw-minimal-player-bar></bw-minimal-player-provider>`,
    "playlist-player": `<bw-playlist-player-provider data-show-user-interface="false" data-analytics-consent="none" data-project-id="9504" data-playlist-id="153102"><bw-playlist-player-root><bw-playlist-player-bar><bw-playlist-play-pause-button></bw-playlist-play-pause-button><bw-playlist-player-info><bw-playlist-call-to-action></bw-playlist-call-to-action><bw-playlist-duration></bw-playlist-duration></bw-playlist-player-info><bw-playlist-playback-controls><bw-playlist-playback-rate-button></bw-playlist-playback-rate-button><bw-playlist-prev-track-button></bw-playlist-prev-track-button><bw-playlist-next-track-button></bw-playlist-next-track-button><bw-playlist-time-indicator></bw-playlist-time-indicator><bw-playlist-progress-bar></bw-playlist-progress-bar></bw-playlist-playback-controls><bw-playlist-toggle-button></bw-playlist-toggle-button></bw-playlist-player-bar><bw-playlist-list></bw-playlist-list></bw-playlist-player-root></bw-playlist-player-provider>`,
    "video-player": `<bw-video-player-provider data-show-user-interface="false" data-analytics-consent="none" data-video="true" data-project-id="54009" data-content-id="5ab6a5e1-689c-4103-962d-e7e68a4258ff"><bw-video-feature-image></bw-video-feature-image><bw-video-control-bar><bw-video-prev-seconds-button data-color="white" data-seconds="10"></bw-video-prev-seconds-button><bw-video-play-pause-button data-color="white" data-size="56"></bw-video-play-pause-button><bw-video-next-seconds-button data-color="white" data-seconds="10"></bw-video-next-seconds-button></bw-video-control-bar><bw-video-widget-bar><bw-video-play-pause-button></bw-video-play-pause-button><bw-video-widget-controls><bw-video-playback-rate-button></bw-video-playback-rate-button><bw-video-prev-seconds-button data-seconds="10"></bw-video-prev-seconds-button><bw-video-next-seconds-button data-seconds="10"></bw-video-next-seconds-button><bw-video-time-indicator></bw-video-time-indicator><bw-video-progress-bar></bw-video-progress-bar><bw-video-close-widget-button></bw-video-close-widget-button></bw-video-widget-controls></bw-video-widget-bar></bw-video-player-provider>`,
    "vertical-video-player": `<bw-video-player-provider data-show-user-interface="false" data-analytics-consent="none" data-video="true" data-aspect="9/16" data-height="480" data-project-id="54009" data-content-id="5ab6a5e1-689c-4103-962d-e7e68a4258ff"><bw-video-feature-image></bw-video-feature-image><bw-video-control-bar><bw-video-prev-seconds-button data-color="white" data-seconds="10"></bw-video-prev-seconds-button><bw-video-play-pause-button data-color="white" data-size="56"></bw-video-play-pause-button><bw-video-next-seconds-button data-color="white" data-seconds="10"></bw-video-next-seconds-button></bw-video-control-bar><bw-video-widget-bar><bw-video-play-pause-button></bw-video-play-pause-button><bw-video-widget-controls><bw-video-playback-rate-button></bw-video-playback-rate-button><bw-video-prev-seconds-button data-seconds="10"></bw-video-prev-seconds-button><bw-video-next-seconds-button data-seconds="10"></bw-video-next-seconds-button><bw-video-time-indicator></bw-video-time-indicator><bw-video-progress-bar></bw-video-progress-bar><bw-video-close-widget-button></bw-video-close-widget-button></bw-video-widget-controls></bw-video-widget-bar></bw-video-player-provider>`
  };
  const markup = DEMOS[name];
  return <div className="not-prose flex w-full items-center justify-center rounded-lg border p-10" style={{
    minHeight: "16rem",
    fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif'
  }}>
      {markup ? <div dangerouslySetInnerHTML={{
    __html: markup
  }} /> : <p className="text-sm">No preview available for “{name}”.</p>}
    </div>;
};

<Tabs>
  <Tab title="Preview">
    <WebComponentsDemo name="playback-rate-button" />
  </Tab>

  <Tab title="Code">
    ```js PlaybackRateButton.js theme={null}
    import { BwPlayerConsumer } from "@/registry/html/PlayerProvider";

    export class BwPlaybackRateButton extends BwPlayerConsumer {
      _btn = null;
      _listener = null;

      constructor() {
        super();
        this._btn = document.createElement("button");
        this._btn.addEventListener("click", () => {
          if (!this._player) return;
          this._player.playbackRate = this._player.playbackRate === 1 ? 1.5 : 1;
        });
      }

      connectedCallback() {
        super.connectedCallback();
        this._listener = this._player?.addEventListener("<any>", () => {
          this._btn.textContent = `${this._player.playbackRate}x`;
        });
        this._btn.textContent = `${this._player?.playbackRate}x`;
        this.appendChild(this._btn);
      }

      disconnectedCallback() {
        this._player?.removeEventListener("<any>", this._listener);
        this._listener = null;
        super.disconnectedCallback();
      }
    }

    customElements.define("bw-playback-rate-button", BwPlaybackRateButton);
    ```
  </Tab>
</Tabs>

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npx @beyondwords/cli components add playback-rate-button --html
  ```

  ```bash pnpm theme={null}
  pnpm dlx @beyondwords/cli components add playback-rate-button --html
  ```

  ```bash yarn theme={null}
  yarn dlx @beyondwords/cli components add playback-rate-button --html
  ```

  ```bash bun theme={null}
  bunx --bun @beyondwords/cli components add playback-rate-button --html
  ```
</CodeGroup>

## Usage

Import the modules (each calls `customElements.define`), then use the elements. Nest the button inside a `<bw-player-provider>`.

```html theme={null}
<bw-player-provider
  data-project-id="9504"
  data-content-id="ba00ef51-03ac-4a85-8b98-e45c957e8ef8"
  data-show-user-interface="false"
>
  <bw-playback-rate-button></bw-playback-rate-button>
</bw-player-provider>

<script type="module">
  import "@/registry/html/PlayerProvider";
  import "@/registry/html/PlaybackRateButton";
</script>
```

`<bw-playback-rate-button>` finds its nearest
[`<bw-player-provider>`](/player-ui/html/player-provider) ancestor and reads
`playbackRate` from it, updating on every player event. On click, it sets
`player.playbackRate` directly on the instance, toggling between `1` and
`1.5`. The current rate renders as the label (e.g. `1x`). Adjust the toggle
logic to expose whatever speeds you want.

<Warning>
  These components expect the BeyondWords player to be available as a global
  `BeyondWords` (the player UMD script). Load it before the provider connects.
</Warning>

## Reference

|                       |                                                                    |
| --------------------- | ------------------------------------------------------------------ |
| **Attributes**        | None                                                               |
| **Player state read** | `playbackRate`                                                     |
| **Events emitted**    | None. Sets `player.playbackRate` directly                          |
| **Requires**          | a `<bw-player-provider>` ancestor and the player UMD global loaded |
