---
title: Player v7 Dual Screen Setup
url: https://docs.kaltura.com/docs/rich-media-cms-apis/content-management/multi-stream-player-v7-dual-screen-setup
---

## Player v7 Dual Screen Setup


The **Dual Screen plugin** (`@playkit-js/playkit-js-dual-screen`) enables synchronized multi-stream playback in Kaltura Player v7 (PlayKit). It requires the `kalturaCuepoints` plugin if showing slides.

### Enable via KMC Studio

1. Log in to KMC and go to the **Studio** tab
2. Select the player you want to configure (or create a new one)
3. Scroll to **Engagement & Interactivity**
4. Toggle **Dual screen** on
5. Configure the default layout:
   - **Picture-in-Picture** — primary video large, secondary as overlay (default)
   - **Side-by-Side** — both streams displayed equally
   - **Single Media** — only one stream visible at a time
6. Set the **PiP position** (Top Right, Bottom Right, Top Left, Bottom Left)
7. Click **Save**

### Enable via JavaScript Config

When using `KalturaPlayer.setup()`, add the `dualscreen` plugin to the config:


```javascript
var config = {
  targetId: 'player-container',
  plugins: {
    dualscreen: {
      layout: 'PIP',
      position: 'bottom-right',
      childSizePercentage: 30,
      childAspectRatio: { width: 16, height: 9 }
    },
    kalturaCuepoints: {}  // Required if showing slides
  }
};

var player = KalturaPlayer.setup(config);
player.loadMedia({ entryId: 'PARENT_ENTRY_ID' });
```


### Plugin Configuration Options

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `layout` | string | `"PIP"` | Initial layout mode (see layout modes below) |
| `position` | string | `"bottom-right"` | PiP overlay position: `"bottom-left"`, `"bottom-right"`, `"top-left"`, `"top-right"` |
| `childSizePercentage` | number | `30` | Height of PiP child as percentage of parent player height |
| `childAspectRatio` | object | `{width: 16, height: 9}` | Aspect ratio of the PiP container |
| `slidesPreloadEnabled` | boolean | `true` | Preload slide images |
| `removePlayerSettings` | boolean | `false` | Hide media settings button when dual screen is active |

These values define the initial appearance on load. Viewers can interactively change layout and position during playback.

### Layout Modes

| Layout | Description |
|--------|-------------|
| `PIP` | Primary video large, secondary as small overlay |
| `PIPInverse` | Secondary video large, primary as small overlay |
| `SideBySide` | Both streams side by side (primary on left) |
| `SideBySideInverse` | Both streams side by side (primary on right) |
| `SingleMedia` | Only primary video shown |
| `SingleMediaInverse` | Only secondary video shown |
| `Hidden` | Dual screen deactivated |

### Programmatic Control via JavaScript API

The plugin registers a `dualScreen` service on the player instance:


```javascript
var player = KalturaPlayer.setup(config);
player.loadMedia({ entryId: 'PARENT_ENTRY_ID' });

// Access the dual screen service
var dualScreenService = player.getService('dualScreen');

// Wait for secondary media to load
dualScreenService.ready.then(function() {
  var activePlayer = dualScreenService.getActivePlayer();
  var pipPlayer = dualScreenService.getPipPlayer();
  var allPlayers = dualScreenService.getDualScreenPlayers();
});
```


**Service methods:**

| Method | Returns | Description |
|--------|---------|-------------|
| `ready` | `Promise<void>` | Resolves when secondary media is loaded |
| `getActivePlayer()` | `DualScreenPlayer` | The player in the primary (large) container |
| `getPipPlayer()` | `DualScreenPlayer` | The player in the PiP (small) container |
| `getDualScreenPlayers(types?, container?)` | `DualScreenPlayer[]` | All dual screen player instances |
| `getDualScreenThumbs(time)` | thumbnail info | Thumbnail data for both screens at a given time |

**Switch layout programmatically at runtime:**

The plugin's initial config (`layout`, `position`) is set via `KalturaPlayer.setup()`. To switch layouts at runtime, access the plugin instance via `player.plugins.dualscreen` and call its internal `_switchTo*` methods after the `dualScreen` service is ready:


```javascript
var dualScreenService = player.getService('dualScreen');

dualScreenService.ready.then(function() {
  var ds = player.plugins.dualscreen;

  // Switch to Side-by-Side
  ds._switchToSideBySide({ force: true }, true);

  // Switch to PiP
  ds._switchToPIP({ force: true }, true);

  // Switch to PiP with screens swapped (secondary becomes main)
  ds._applyInverse();
  ds._switchToPIP({ force: true }, true);

  // Switch to Single Media (primary only)
  ds._switchToSingleMedia({ force: true }, true);

  // Hide dual screen entirely
  ds._switchToHidden(true);
});
```


The first argument is `{ force: true }` to ensure the switch happens even if the plugin thinks it's already in that layout. The second argument (`true`) marks it as a user interaction so the `dualscreen_change_layout` event fires.

For the `Inverse` variants (`PIPInverse`, `SideBySideInverse`, `SingleMediaInverse`), call `ds._applyInverse()` before the `_switchTo*` method to swap which stream is primary vs. secondary.

### Events

The plugin emits two custom events:

| Event | Description |
|-------|-------------|
| `dualscreen_change_layout` | Fired when the layout changes (user interaction or programmatic) |
| `dualscreen_side_displayed` | Fired when a side/layout is rendered |


```javascript
player.addEventListener('dualscreen_change_layout', function(event) {
  console.log('Layout changed to:', event.payload.layout);
});
```


See the [Player Embed Guide](/docs/embeddable-kaltura-products/kaltura-player/player-embed-overview) for full embedding details.
