# Configuration

This page lists every field of `new FPlyr(config)`, the defaults, and how the `volume`/`mute` options actually behave today.

## config

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | `string` | No | ID of an existing element that becomes the player container; if omitted or not found, a new `div.FPlyr` is created and `player.body` must be inserted manually |
| `video` | `string` | One of | Video URL |
| `youtube` | `string` | One of | YouTube video ID |
| `vimeo` | `string` | One of | Vimeo video ID |
| `audio` | `string` | One of | Audio URL |
| `option` | `object` | No | Panel and playback options, see below |
| `when` | `object` | No | Lifecycle callbacks, see [Lifecycle Events](/lifecycle-events) |

For the priority order when several sources are set, see [Media Sources](/media-sources).

## option

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `panelType` | `string` | `""` | Panel theme, see [Panel Themes](/panel-themes) |
| `panelItem` | `string[]` | `["play", "progress", "time", "volumeMini", "rate", "full"]` | Controls, see [Panel Controls](/panel-controls) |
| `showThumb` | `boolean` | `true` | Show slider drag thumbs |
| `volume` | `number` | `100` | Initial volume (0–100), see the limits below |
| `mute` | `boolean` | `false` | Initial mute, see the limits below |

## Without an id

Without `id`, the player stays off the page until you insert `player.body`:

```demo
<section id="mount" style="height: 240px"></section>
<script>
  const player = new FPlyr({
    video: "https://cdn.pixabay.com/video/2023/11/28/191159-889246512_tiny.mp4",
    option: { panelType: "simple" },
  });
  console.log("attached before append:", player.body.isConnected);
  document.getElementById("mount").appendChild(player.body);
  console.log("attached after append:", player.body.isConnected);
  console.log("class:", player.body.className);
</script>
```

## Invalid Config

If `config` is not an object, the constructor logs `config: 不存在。` with `console.log` and returns without throwing; the instance has no `body`:

```demo
<script>
  const player = new FPlyr("player");
  console.log("body:", String(player.body));
</script>
```

## Current Behavior of volume and mute

- **`option.volume`**: written only when the legacy top-level `volume` is also passed (`src/js/model/player.js:61`); otherwise the default `100` stays.
- **`option.mute`**: likewise needs the legacy top-level `mute` (`:65`); even then, the volume applied right after at readiness (`:424`) unmutes because the volume is not 0 (`:243`), so the initial mute never takes effect.

```demo
<div style="height: 200px"><div id="a"></div></div>
<div style="height: 200px"><div id="b"></div></div>
<script>
  const a = new FPlyr({
    id: "a",
    video: "https://cdn.pixabay.com/video/2023/11/28/191159-889246512_tiny.mp4",
    option: { volume: 30, mute: true },
    when: { ready: () => setTimeout(() => console.log("option only ->", a.option.volume, a.isMuted())) },
  });
  const b = new FPlyr({
    id: "b",
    video: "https://cdn.pixabay.com/video/2023/11/28/191159-889246512_tiny.mp4",
    volume: 30,
    mute: true,
    option: { volume: 30, mute: true },
    when: { ready: () => setTimeout(() => console.log("option + legacy ->", b.option.volume, b.isMuted())) },
  });
</script>
```

## Related Pages

- [Instance API](/instance-api)
- [Deprecations](/deprecations): the legacy top-level fields
