Skip to content

Transitions

In this guide, you will learn how to implement basic animated transitions to the View and Rescaler components.

Basic setup

Start Smelter server, register inputs (input_1, input_2, input_3, input_4) and register video output (output_1) similarly to examples shown in Quick start guide.

Width transition

Set initial scene

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 480,
"child": { "type": "input_stream", "input_id": "input_1" },
}
]
}
}
}

Trigger transition

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 1280,
"transition": { "duration_ms": 2000 },
"child": { "type": "input_stream", "input_id": "input_1" },
}
]
}
}
}

In the first update request, you can see that the Rescaler has a width of 480, and in the second one, it is changed to 1280 and "transition.duration_ms": 2000 was added.

The component must have the same "id" in both the initial state and the update that starts the transition, otherwise it will switch immediately to the new state without a transition.

Sibling component transitions

If there are two sibling Rescaler components and only one of them has a width transition applied, the layout of the other will be adjusted automatically.

Set initial scene

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 480,
"child": { "type": "input_stream", "input_id": "input_1" },
},
{
"type": "rescaler",
"child": { "type": "input_stream", "input_id": "input_2" },
}
]
}
}
}

Trigger transition

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 1280,
"transition": { "duration_ms": 2000 },
"child": { "type": "input_stream", "input_id": "input_1" },
},
{
"type": "rescaler",
"child": { "type": "input_stream", "input_id": "input_2" },
}
]
}
}
}

In the first update request, you can see that the Rescaler has a width of 480, and in the second one, it is changed to 1280 and "transition.duration_ms": 2000 was added.

Compared to previous section, this example also includes sibling component next to one that have a transition. That component will also animate based on its sibling’s behavior.

Customizing interpolation functions

All the examples above utilize the default linear interpolation; however, you can also choose from other available modes.

Set initial scene

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 320, "height": 180, "top": 0, "left": 0,
"child": { "type": "input_stream", "input_id": "input_1" },
},
{
"type": "rescaler",
"id": "rescaler_2",
"width": 320, "height": 180, "top": 0, "left": 320,
"child": { "type": "input_stream", "input_id": "input_2" },
},
{
"type": "rescaler",
"id": "rescaler_3",
"width": 320, "height": 180, "top": 0, "left": 640,
"child": { "type": "input_stream", "input_id": "input_3" },
},
{
"type": "rescaler",
"id": "rescaler_4",
"width": 320, "height": 180, "top": 0, "left": 960,
"child": { "type": "input_stream", "input_id": "input_4" },
},
]
}
}
}

Trigger transition

POST: /api/output/output_1/update
Content-Type: application/json
{
"video": {
"root": {
"type": "view",
"background_color": "#4d4d4d",
"children": [
{
"type": "rescaler",
"id": "rescaler_1",
"width": 320, "height": 180, "top": 540, "left": 0,
"child": { "type": "input_stream", "input_id": "input_1" },
"transition": { "duration_ms": 2000 },
},
{
"type": "rescaler",
"id": "rescaler_2",
"width": 320, "height": 180, "top": 540, "left": 320,
"child": { "type": "input_stream", "input_id": "input_2" },
"transition": {
"duration_ms": 2000, "easing_function": {"function_name": "bounce"}
},
},
{
"type": "rescaler",
"id": "rescaler_3",
"width": 320, "height": 180, "top": 540, "left": 640,
"child": { "type": "input_stream", "input_id": "input_3" },
"transition": {
"duration_ms": 2000,
"easing_function": {
"function_name": "cubic_bezier",
"points": [0.65, 0, 0.35, 1]
}
}
},
{
"type": "rescaler",
"id": "rescaler_4",
"width": 320, "height": 180, "top": 540, "left": 960,
"child": { "type": "input_stream", "input_id": "input_4" },
"transition": {
"duration_ms": 2000,
"easing_function": {
"function_name": "cubic_bezier",
"points": [0.33, 1, 0.68, 1]
}
}
}
]
}
}
}