Skip to main content

Scenes

The scenes composition mode enables you to create layouts driven directly via the Layout API. RTMP, Webpages, Videos and Images can currently be embedded. For a comprehensive list on all the layer type supported, see the layer types documentation.

For an end-to-end example of working with scene composition, see the step-by-step guide or view the full example project.

Scene composition model

When working with scene composition, a project is created with composition mode "scenes" enabling the ability to render API driven layouts and scene switching.

The project holds the active layout ID, which can be updated during the broadcast. Each layout has a "root" node which holds reference to the child layers to display. The order of layer ids within the children property of the root layer is used to infer the stacking order.

Creating a layout

To enable functionality required for a scene composition, you must define the layout type to be LAYOUT_TYPE_SCENE when creating it. (note: this cannot be changed later).

Setting the layout type to be LAYOUT_TYPE_SCENE will introduce an initial layer of type root which all other layers must be a child of (note: the root layer cannot be deleted!). This also enables some guardrails when interacting with the Layout API's layers that would otherwise not be present.

import { ApiStream, LayoutAPIModel } from '@api.stream/sdk';
const api = new ApiStream();

const project = /* your project */;

const layout = await api.LayoutApi().layout.createLayout({
layout: {
width: project.rendering?.video?.width,
height: project.rendering?.video?.height,
collectionId: project.collectionId,
projectId: project?.projectId,
type: LayoutApiModel.LayoutType.LAYOUT_TYPE_SCENE,
}
});

Working with Scene composition

Creating layers

When adding layers, you should reference the layer types documentation to understand what layers are available and what configuration is possible with them. Any layer created must be a child of the root layer in order to be displayed.

tip

If updating the active layout in a composition, keep in mind that changes will automatically be reflected in the live composition. Consider using a batch change if you need to modify multiple layers or an entirely different layout with our scene switching API.

import { ApiStream } from '@api.stream/sdk';
const api = new ApiStream();

const LAYOUT_ID = 'fake-layout-42fa-be5f-addd9d14641e';

// List all existing layers within the layout.
const response = await api.LayoutApi().layer.listLayers({ layoutId: layoutId });

// When a layout is created with the "scene" type, a layer with type "root" will be automatically created. Any
// layers should be assigned as children to that.
const rootLayer = response.layers.find(layer => layer.type === 'root');

const layer = await api.LayoutApi().layer.createLayer({
layoutId: layoutId,
layer: {
x: 0,
y: 0,
width: 1280,
height: 720,

// Layer specific configuration.
type: 'webpage',
data: {
url: 'https://example.org',
},

// This will automatically make this layer the top-most layer.
// This can also be done manually by creating a separate update request _or_ a batch request.
parentId: rootLayer.id,
},
});

Switching Layouts

By updating the selected layout ID on a project, you can switch between multiple unique layouts.

note

Note: layout switching isn't instantaneous. We make sure the layout is ready and any layers have loaded (images, webpages). There may be a delay while new resources load in (up to a maximum of 5 seconds)

import { ApiStream } from '@api.stream/sdk';
const api = new ApiStream();

const COLLECTION_ID = 'fake-collection-4274-8e52-e7edb5b57f8f';
const PROJECT_ID = 'fake-project-4988-aab3-8cce055df163';
const NEW_LAYOUT_ID = 'fake-layout-42fa-be5f-addd9d14641e';

// Switch scenes
await api.LiveApi().project?.updateProject({
collectionId: COLLECTION_ID,
projectId: PROJECT_ID,
composition: {
scene: {
selectedLayoutId: NEW_LAYOUT_ID,
},
},
updateMask: { paths: ["composition.scene.selectedLayoutId"] },
});

Batch Requests

Batch requests provide a fast way to setup a large layout without having to fire off multiple API requests. If you're interacting with more than 1 layer, you should use batching.

tip

When creating a batch request you can self-reference other layers by using the string index:<number> in place of the ID. For example, if you create a layer and update another layer referencing it, you can set children to ['index:0']

note

If you're batch updating a layout in order to completely re-layout the active layout, consider creating a new layout and use layout switching. Layout switching has built-in mechanisms to ensure the full layout is ready before switching, where a simple batch request does not. If you add layers manually, you may see them gradually load in as opposed to clean layout switch.

import { ApiStream } from '@api.stream/sdk';
const api = new ApiStream();

const LAYOUT_ID = 'fake-layout-42fa-be5f-addd9d14641e';

// Find the root layer.
const response = await api.LayoutApi().layer.listLayers({ layoutId: layoutId });
const rootLayer = response.layers.find(layer => layer.type === 'root');

const layer = await api.LayoutApi().layer.batch({
layers: [
// Create the a base layer using a web page.
{ create: { type: 'webpage', width: 1280, height: 720, x: 0, y: 0, data: { url: 'https://example.org' } } },
// Create an image layer on top.
{ create: { type: 'image', height: 60, x: 100, y: 100, data: { media: { url: 'https://api.stream/img/Horizontal-Logo-Primary-Color.svg' } } } },

// Update the root layer with the layers created.
{ update: { id: rootLayer.id, children: ['index:0', 'index:1']} },
],
layoutId: layoutId,
});