npm package: @hyperstream/audio-player
Description: Embeddable React audio player with HLS streaming, playlists, chapters, transcripts, interactive popups, and imperative ref API
Latest version: 3.6.0

# @hyperstream/audio-player

A React audio player component with HLS streaming, playlists, chapters, transcripts, interactive popups, and analytics.

## Installation

```bash
npm install @hyperstream/audio-player
```

## Usage

```tsx
import { HyperstreamAudioPlayer } from "@hyperstream/audio-player";
import "@hyperstream/audio-player/styles.css";

export default function App() {
  return (
    <HyperstreamAudioPlayer
      src="https://example.com/audio/show.m3u8"
      title="Show Title"
      artist="Creator"
      accentColor="#0C969C"
      initialMode="compact"
      compact
      expanded
      mini
    />
  );
}
```

## Recommended API

Use these canonical props first:

- `src`
- `accentColor`
- `initialMode`
- `compact`
- `expanded`
- `mini`

Legacy aliases like `streamUrl`, `hyperstreamUrl`, `primaryColor`, `brandColor`, and `mode`
are still supported for backward compatibility.

## More Examples

### Minimal player

```tsx
<HyperstreamAudioPlayer
  src="https://example.com/audio/episode-1.m3u8"
  title="Episode 1"
  artist="Flow Automate"
  accentColor="#0C969C"
/>
```

### Start expanded and disable mini mode

```tsx
<HyperstreamAudioPlayer
  src="https://example.com/audio/episode-1.m3u8"
  title="Private Audio"
  artist="Flow Automate"
  accentColor="#7C3AED"
  initialMode="expanded"
  compact={true}
  expanded={true}
  mini={false}
/>
```

### Autoplay configuration

```tsx
<HyperstreamAudioPlayer
  src="https://example.com/audio/episode-1.m3u8"
  title="Autoplay Demo"
  artist="Flow Automate"
  accentColor="#2563EB"
  autoplay
  muteOnStart
  controls
  initialVolume={70}
  playbackSpeed={1.25}
/>
```

## Props

| Prop             | Type                              | Default | Description                                |
| ---------------- | --------------------------------- | ------- | ------------------------------------------ |
| `src`            | string                            | —       | Canonical source URL for playback          |
| `streamUrl`      | string                            | —       | Legacy/direct stream URL alias             |
| `defaultUrl`     | string                            | —       | Fallback audio URL                         |
| `url`            | string                            | —       | Alias for `defaultUrl`                     |
| `hyperstreamUrl` | string                            | —       | Alias for `streamUrl`                      |
| `thumbnail`      | string                            | —       | Cover art / thumbnail image URL            |
| `poster`         | string                            | —       | Alias for `thumbnail`                      |
| `showTitle`      | boolean                           | `true`  | Show / hide title & artist text            |
| `containerWidth` | number                            | —       | Explicit container width in pixels         |
| `watermark`      | string                            | —       | Watermark image URL                        |
| `title`          | string                            | —       | Track title                                |
| `artist`         | string                            | —       | Artist / subtitle                          |
| `accentColor`    | string                            | —       | Canonical accent color                     |
| `primaryColor`   | string                            | —       | Deprecated alias for `accentColor`         |
| `brandColor`     | string                            | —       | Deprecated alias for `accentColor`         |
| `secondaryColor` | string                            | —       | Compatibility-only color input             |
| `textColor`      | string                            | —       | Compatibility-only color input             |
| `initialMode`    | `compact` \| `expanded` \| `mini` | —       | Canonical initial mode                     |
| `mode`           | `compact` \| `expanded` \| `mini` | —       | Deprecated alias for `initialMode`         |
| `compact`        | boolean                           | `true`  | Enable compact mode                        |
| `expanded`       | boolean                           | `true`  | Enable expanded mode                       |
| `mini`           | boolean                           | `true`  | Enable mini mode                           |
| `autoplay`       | boolean                           | `false` | Auto-play on load                          |
| `muteOnStart`    | boolean                           | `false` | Force mute on start                        |
| `showControls`   | boolean                           | `true`  | Show / hide control overlay                |
| `controls`       | boolean                           | `true`  | Alias for `showControls`                   |
| `loop`           | boolean                           | `false` | Loop audio playback                        |
| `initialVolume`  | number                            | `80`    | Initial volume (0–100)                     |
| `playbackSpeed`  | number                            | `1`     | Default playback speed (0.25–4)            |
| `embedMode`      | boolean                           | `false` | Minimal embed mode (no navigation chrome)  |
| `apiKey`         | string                            | —       | API key for authenticated streams          |
| `className`      | string                            | —       | Additional className for the container     |
| `style`          | `React.CSSProperties`             | —       | Additional inline styles for the container |

### Callbacks

| Prop            | Signature                                           | Description                        |
| --------------- | --------------------------------------------------- | ---------------------------------- |
| `onPlay`        | `() => void`                                        | Called when playback starts        |
| `onPause`       | `() => void`                                        | Called when playback pauses        |
| `onTimeUpdate`  | `(currentTime: number, duration: number) => void`   | Called on time update              |
| `onEnded`       | `() => void`                                        | Called when track ends             |
| `onError`       | `(error: string) => void`                           | Called on playback error           |
| `onReady`       | `() => void`                                        | Called when player is ready        |
| `onModeChange`  | `(mode: "compact" \| "expanded" \| "mini") => void` | Called when mode changes           |
| `onTrackChange` | `(index: number, track: any) => void`               | Called when playlist track changes |

All props are reactive — updating them at runtime takes effect immediately without remounting.

## Ref API (Imperative Handle)

Use a ref for programmatic control:

```tsx
import { useRef } from "react";
import {
  HyperstreamAudioPlayer,
  HyperstreamAudioPlayerRef,
} from "@hyperstream/audio-player";

function Player() {
  const ref = useRef<HyperstreamAudioPlayerRef>(null);

  return (
    <>
      <HyperstreamAudioPlayer ref={ref} src="..." />
      <button onClick={() => ref.current?.play()}>Play</button>
      <button onClick={() => ref.current?.pause()}>Pause</button>
      <button onClick={() => ref.current?.seek(30)}>Jump to 0:30</button>
    </>
  );
}
```

| Method                  | Returns         | Description                     |
| ----------------------- | --------------- | ------------------------------- |
| `play()`                | `Promise<void>` | Start playback                  |
| `pause()`               | `void`          | Pause playback                  |
| `seek(time)`            | `void`          | Seek to time in seconds         |
| `setVolume(vol)`        | `void`          | Set volume (0–1)                |
| `setPlaybackRate(rate)` | `void`          | Set speed (0.25–4)              |
| `setMuted(muted)`       | `void`          | Mute / unmute                   |
| `getCurrentTime()`      | `number`        | Current playback time (seconds) |
| `getDuration()`         | `number`        | Audio duration (seconds)        |
| `getHlsInstance()`      | `Hls \| null`   | Underlying HLS.js instance      |

## Non-React (HTML / WordPress / Webflow)

Drop a single `<script>` tag onto any page — no bundler, no npm, no React required.

```html
<script src="https://audioplayer.flowautomate.com/player.js"></script>

<hyperstream-audio-player
  src="https://example.com/audio/show.m3u8"
  title="Show Title"
  artist="Creator"
  poster="https://example.com/cover.jpg"
  accent-color="#0C969C"
  initial-mode="compact"
  compact="true"
  expanded="true"
  mini="true"
  show-title="true"
  container-width="600"
  autoplay="false"
  muted="true"
  controls="true"
  volume="70"
  speed="1"
></hyperstream-audio-player>
```

The `<script>` tag auto-detects its own origin, so embeds work cross-origin out of the box —
no patching required.

### Web Component Attributes

#### Source & Metadata

| Attribute         | Type   | Default | Description                                                             |
| ----------------- | ------ | ------- | ----------------------------------------------------------------------- |
| `src`             | string | —       | Canonical source URL (HLS `.m3u8` or direct)                            |
| `url`             | string | —       | Alias for `src`                                                         |
| `hyperstream-url` | string | —       | Alias for `src`                                                         |
| `title`           | string | —       | Track title                                                             |
| `artist`          | string | —       | Artist / subtitle                                                       |
| `poster`          | string | —       | Cover art / thumbnail image URL                                         |
| `api-key`         | string | —       | API key for authenticated streams                                       |
| `base-url`        | string | auto    | Explicit base URL for the player app (auto-detected from script origin) |

#### Player Modes

| Attribute      | Type    | Default   | Description                                           |
| -------------- | ------- | --------- | ----------------------------------------------------- |
| `initial-mode` | string  | `compact` | Initial player mode (`compact` / `expanded` / `mini`) |
| `player-mode`  | string  | —         | Deprecated alias for `initial-mode`                   |
| `mode`         | string  | —         | Legacy alias for `initial-mode`                       |
| `compact`      | boolean | `true`    | Enable compact mode                                   |
| `expanded`     | boolean | `true`    | Enable expanded mode                                  |
| `mini`         | boolean | `true`    | Enable mini mode                                      |

#### Appearance

| Attribute       | Type    | Default | Description                               |
| --------------- | ------- | ------- | ----------------------------------------- |
| `accent-color`  | string  | —       | Canonical accent color (hex)              |
| `color`         | string  | —       | Deprecated alias for `accent-color`       |
| `brand-color`   | string  | —       | Deprecated alias for `accent-color`       |
| `show-title`    | boolean | `true`  | Show / hide title & artist text           |
| `skin`          | string  | `bar`   | Forward-compatible; currently only `bar`  |
| `overlay`       | string  | `dark`  | Forward-compatible; currently only `dark` |
| `glassmorphism` | boolean | `true`  | Forward-compatible; currently ignored     |

#### Layout & Sizing

| Attribute         | Type   | Default | Description                         |
| ----------------- | ------ | ------- | ----------------------------------- |
| `width`           | string | `100%`  | Player container width (CSS value)  |
| `height`          | string | `auto`  | Player container height (CSS value) |
| `container-width` | number | —       | Explicit container width in pixels  |

#### Playback

| Attribute  | Type    | Default | Description                                        |
| ---------- | ------- | ------- | -------------------------------------------------- |
| `autoplay` | boolean | `false` | Auto-play on load (forces mute per browser policy) |
| `muted`    | boolean | `false` | Start muted                                        |
| `controls` | boolean | `true`  | Show / hide controls                               |
| `loop`     | boolean | `false` | Loop playback                                      |
| `volume`   | number  | `80`    | Initial volume (0–100)                             |
| `speed`    | number  | `1`     | Playback speed (0.25–4)                            |

#### Responsive Device Overrides

Most attributes support device-specific overrides via `-tablet` and `-mobile` suffixes.
On screens < 768px the `-mobile` value is used; on 768–1024px the `-tablet` value applies;
otherwise the base attribute is used.

```html
<hyperstream-audio-player
  src="https://example.com/audio/show.m3u8"
  volume="80"
  volume-mobile="60"
  volume-tablet="70"
  show-title="true"
  show-title-mobile="false"
  skin="bar"
  skin-tablet="bar"
  width="100%"
  width-mobile="100%"
  container-width="800"
  container-width-mobile="360"
  autoplay="false"
  autoplay-mobile="false"
  speed="1"
  speed-mobile="1"
  accent-color="#0C969C"
  color-mobile="#2563EB"
></hyperstream-audio-player>
```

Responsive suffixes are supported for: `skin`, `width`, `height`, `autoplay`, `loop`, `muted`,
`controls`, `volume`, `speed`, `color`, `overlay`, `glassmorphism`, `show-title`, `container-width`,
`accent-color`, `brand-color`.

### JavaScript API

```js
const player = document.querySelector("hyperstream-audio-player");

player.play();
player.pause();
player.seek(30); // seconds
player.setVolume(0.8); // 0–1
player.setPlaybackRate(1.5); // 0.25–4
player.setMuted(true);
player.setLoop(true);
player.setMode("expanded"); // compact / expanded / mini

// Promise-based state query
const state = await player.getState();
console.log(state); // { currentTime, duration, volume, paused, ... } or null on timeout

// Check if the player iframe is ready
console.log(player.ready); // true / false
```

| Method / Property       | Returns                | Description                             |
| ----------------------- | ---------------------- | --------------------------------------- |
| `play()`                | `void`                 | Start playback                          |
| `pause()`               | `void`                 | Pause playback                          |
| `seek(time)`            | `void`                 | Seek to time in seconds                 |
| `setVolume(vol)`        | `void`                 | Set volume (0–1)                        |
| `setPlaybackRate(rate)` | `void`                 | Set speed (0.25–4)                      |
| `setMuted(muted)`       | `void`                 | Mute / unmute                           |
| `setLoop(loop)`         | `void`                 | Enable / disable loop                   |
| `setMode(mode)`         | `void`                 | Switch mode (compact / expanded / mini) |
| `getState()`            | `Promise<state\|null>` | Query full playback state (3s timeout)  |
| `.ready`                | `boolean`              | Whether the player iframe is ready      |

### Events

The web component dispatches `CustomEvent`s you can listen to directly:

```js
const player = document.querySelector("hyperstream-audio-player");

player.addEventListener("ready", () => {
  console.log("Player ready");
});

player.addEventListener("play", () => {
  console.log("Playing");
});

player.addEventListener("pause", () => {
  console.log("Paused");
});

player.addEventListener("ended", () => {
  console.log("Audio ended");
});

player.addEventListener("timeupdate", (e) => {
  // e.detail = { currentTime: number, duration: number }
  console.log(e.detail.currentTime, "/", e.detail.duration);
});

player.addEventListener("volumechange", (e) => {
  // e.detail = { volume: number, muted: boolean }
  console.log("Volume:", e.detail.volume, "Muted:", e.detail.muted);
});

player.addEventListener("ratechange", (e) => {
  // e.detail = { rate: number }
  console.log("Speed:", e.detail.rate);
});

player.addEventListener("error", (e) => {
  console.error("Player error:", e.detail);
});
```

| Event          | Detail                      | Description                  |
| -------------- | --------------------------- | ---------------------------- |
| `ready`        | —                           | Player loaded and ready      |
| `play`         | —                           | Playback started             |
| `pause`        | —                           | Playback paused              |
| `ended`        | —                           | Audio reached the end        |
| `timeupdate`   | `{ currentTime, duration }` | Fires during playback        |
| `volumechange` | `{ volume, muted }`         | Volume or mute state changed |
| `ratechange`   | `{ rate }`                  | Playback speed changed       |
| `modechange`   | `{ mode }`                  | Player mode changed          |
| `error`        | error info                  | A playback error occurred    |

## License

MIT