Skip to main content

Multistream

Multistream allows a source stream and transcoded renditions to be pushed to multiple RTMP(S) targets, such as Twitch, Facebook Live, and YouTube Live. This guide will provide an understanding and use of multistream with the following:

  • Stream Object
  • Creating a Stream with Multistream Targets
  • Manage Multistream Targets
    • In the Livepeer Studio Dashboard
    • With the API
  • Understanding Multistream Performance
    • Through the Livepeer Studio dashboard
    • Through the API

The /stream Object

To use a Multistream Target, you need to reference it from a Stream object.

The reference is made in the targets sub-field of the multistream field in the Stream resource (stream.multistream.targets[]). It is represented as an array of target reference objects, each with a profile that should be multistreamed and the id of the corresponding Multistream Target.

The profile field must reference an existing transcoding profile on the same stream, or "source" to multistream the same original video as ingested. The same profile can be multistreamed to several Multistream Targets, but there can be only 1 multistream to a given URL. You can also set the videoOnly field to true to mute the stream audio and stream only a silent video to the target.

To avoid managing separate Multistream Target objects, you can also create targets inlined in the Stream object on the same mutation request (create or update). In that case, the target reference object in the multistream.targets field should have a spec instead of an id with the payload for creating a new Multistream Target. Notice that spec is a write-only field, meaning that Stream objects returned from reads (GET) will always have only a profile and id in the targets. To get the current state of a Multistream Target, fetch from its own read API using that id.

Creating a Stream with Multistream Targets

You can create a Stream already with some Multistream Targets. Either reference an existing Multistream Target by id or create a new Multistream Target inline with the spec field. You can also use both types of targets on the same payload (reference and inline) as long as they are separate entries in the multistream.targets array.

Request by reference

curl -X POST 'https://livepeer.studio/api/stream' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"name": "test_multistream_reference",
"profiles": [
{ "name": "720p", ... },
{ "name": "480p", ... },
{ "name": "360p", ... }
],
"multistream": {
"targets": [
{ "id" :"0bf161f3-95bd-4971-a7b1-4dcb5d39e78a", "profile": "source" },
{ "id" :"95bd0bf1-61f3-a7b1-4971-39e78a4dcb5d", "profile": "720p" }
]
}
}

Response

{
"lastSeen": 0,
"isActive": false,
"record": false,
"suspended": false,
"sourceSegments": 0,
"transcodedSegments": 0,
"sourceSegmentsDuration": 0,
"transcodedSegmentsDuration": 0,
"sourceBytes": 0,
"transcodedBytes": 0,
"profiles": [
{
"name": "720p",
"bitrate": 2000000,
"fps": 30,
"width": 1280,
"height": 720
},
{
"name": "480p",
"bitrate": 1000000,
"fps": 30,
"width": 854,
"height": 480
},
{
"name": "360p",
"bitrate": 500000,
"fps": 30,
"width": 640,
"height": 360
}
],
"name": "test_multistream_reference",
"multistream": {
"targets": [
{
"id": "936aad06-2165-48d7-bec3-41d4af328281",
"profile": "source"
},
{
"id": "36e73bf6-92bb-49cc-838a-2831ef746ecf",
"profile": "720p"
}
]
},
"kind": "stream",
"userId": "eada599f-3d58-499b-ba24-c7f3faf988de",
"renditions": {},
"id": "f9f8de67-f032-4efd-af77-a664538596e7",
"createdAt": 1656436202327,
"streamKey": "f9f8-tesi-a2co-187v",
"playbackId": "f9f8nwl0eou5lxv4",
"createdByTokenName": "Test"
}

Request by inline

curl -X POST 'https://livepeer.studio/api/stream' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"name": "test_multistream_reference",
"profiles": [
{ "name": "720p", ... },
{ "name": "480p", ... },
{ "name": "360p", ... }
],
"multistream": {
"targets": [
{
"profile": "720p",
"videoOnly": true,
"spec": {
"name": "Eli\'s Twitch",
"url": "rtmp://rtmp.twitch.tv/live/SECRET"
}
},
{
"profile": "360p",
"spec": { "url": "rtmp://rtmp.twitter.com/SECRET" }
}
]
}
}

Response by inline

{
"lastSeen": 0,
"isActive": false,
"record": false,
"suspended": false,
"sourceSegments": 0,
"transcodedSegments": 0,
"sourceSegmentsDuration": 0,
"transcodedSegmentsDuration": 0,
"sourceBytes": 0,
"transcodedBytes": 0,
"profiles": [
{
"name": "720p",
"bitrate": 2000000,
"fps": 30,
"width": 1280,
"height": 720
},
{
"name": "480p",
"bitrate": 1000000,
"fps": 30,
"width": 854,
"height": 480
},
{
"name": "360p",
"bitrate": 500000,
"fps": 30,
"width": 640,
"height": 360
}
],
"name": "test_multistream_reference",
"multistream": {
"targets": [
{
"profile": "720p",
"videoOnly": true,
"id": "936aad06-2165-48d7-bec3-41d4af328281"
},
{
"profile": "360p",
"id": "36e73bf6-92bb-49cc-838a-2831ef746ecf"
}
]
},
"kind": "stream",
"userId": "eada599f-3d58-499b-ba24-c7f3faf988de",
"renditions": {},
"id": "",
"createdAt": 1656435768386,
"streamKey": "cf00-nkaf-odbr-dqib",
"playbackId": "cf00sa2snftzfj5p",
"createdByTokenName": "Test"
}

Updating Multistream Targets of a Stream

You can also update an existing Stream to add or remove Multistream Targets. The schema of all fields is the same as the creation API, with the targets being referenced with an id or created inline with a spec. You can also add, remove or update multiple Multistream Targets on the same API call.

Note: Changes to an existing Stream will only take effect when the next stream session is started.

Adding Multistream Targets

Since you can combine inlined and referenced Multistream Targets on the same request, it's really easy to add a target by URL to an existing stream:

Request

1. GET the current state of the Stream
curl 'https://livepeer.studio/api/stream/{id}' \
-H 'authorization: Bearer {api-key}'

Response

{
"name": "test_multistream_reference",
"profiles": [
{ "name": "720p", ... },
{ "name": "480p", ... },
{ "name": "360p", ... }
],
"multistream": {
"targets": [
{ "id" :"0bf161f3-95bd-4971-a7b1-4dcb5d39e78a", "profile": "source" },
{ "id" :"95bd0bf1-61f3-a7b1-4971-39e78a4dcb5d", "profile": "720p" }
]
}
}

Patch Request

PATCH the Stream with the new target.

PATCH can also add new Multistream Targets by id instead of inline, just like on Stream creation.

curl -X PATCH 'https://livepeer.studio/api/stream/{id}' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"multistream": {
"targets": [
{ "id" :"0bf161f3-95bd-4971-a7b1-4dcb5d39e78a", "profile": "source" },
{ "id" :"95bd0bf1-61f3-a7b1-4971-39e78a4dcb5d", "profile": "720p" },
{ "profile": "720p", "spec": {"url": "rtmp://rtmp.twitter.com/SECRET"} }
]
}
}'

Patch Response

The response should be a 204

Removing Multistream Targets

To remove a Multistream Target from a Stream, you can use the same PATCH request as above to either remove or completely clear the multistream.targets array.

After removing the reference from the Stream, you can also delete the Multistream Target object completely by calling the separate Delete Multistream Target API.

Note: Make sure that no other Stream has a reference to that Multistream Target before doing so.

Removing a single Multistream Target

To remove a specific target, we need to make a PATCH request maintaining only the targets that we want to keep in the stream, after removing the desired one.

For Example:

Request

This request removes only the first target from the example above.

curl -X PATCH 'https://livepeer.studio/api/stream/{id}' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"multistream": {
"targets": [
{ "id" :"95bd0bf1-61f3-a7b1-4971-39e78a4dcb5d", "profile": "720p" }
]
}
}'

Response

The response should be a 204

We kept only the remaining targets in the PATCH, i.e. the second one.

Note: Additionally, you can use a single API call to change the profile that should be multistreamed to a specific target by changing the profile field for the given target when building the PATCH request payload.

Removing all Multistream Targets

Request

curl -X PATCH 'https://livepeer.studio/api/stream/{id}' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"multistream": {
"targets": []
}
}'

Response

The response should be a 204

Manage Multistream targets in the Livepeer Studio Dashboard

To add, manage, and delete Multistream Targets, navigate to the Streams page (livepeer.studio/dashboard/streams) and click on a stream name. On the stream detail page, on the Overview tab, you can view all configured targets. You must configure new Multistream Targets for each stream. This will apply the multistream configuration to that stream. Multistream Targets do not carry over when you create new streams.

To add a new target, select Create on the right side of the Multistream Targets section. You'll be asked to name your target, provide the Ingest URL and a stream key, being Ingest URL the only required value. The Ingest URL and stream key should be provided by the platform that you're streaming into and can be of the RTMP, RTMPS or SRT protocols. Select the rendition profile that you'd like to send to that target and click Create Target. Once created, you can toggle the targets on and off.

To edit a Multistream Target, click on the three dots to the right of the target name and then on Edit to open up the target settings. Select Update target when you've completed your changes.

To delete a multistream target, click on the three dots to the right of the target name and then on Delete.

Note: Any changes to Multistream Targets, including creating new targets, will apply only to the next active session. If you make changes while a stream is active, those changes will not apply until the current session has ended and a new session begins.

Managing Multistream targets with the API

About Multistream Target Objects

You can also manage Multistream Target objects, /multistream/target, from the API. Each target represents a specific endpoint where a stream could be multistreamed to. See details in the API reference.

Notice that the existence of a Multistream Target object itself is not enough for the multistream to happen. You also need to reference the target from the Stream object that should be multistreamed. To avoid managing the separate Multistream Target objects, you can also create the targets inlined in the Stream creation and update APIs. See: the Stream Object section for more information.

Create Targets inlined in the Stream creation

Request

POST /api/multistream/target

curl -X POST 'https://livepeer.studio/api/multistream/target' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"name": "Eli\'s Twitch",
"url": "rtmp://rtmp.twitch.tv/live/SECRET"
}'

Note: Supported Protocols -- RTMP and RTMPS.

Response

{
"id": "{id}",
"userId": "USER123",
"name": "Eli's Twitch",
"url": "rtmp://rtmp.twitch.tv/live/SECRET"
}

Read

You can fetch a specific Multistream Target with their ID, returned on the creation request. The destination url will not be returned since it contains sensitive user data. This way the application developer doesn't have to worry about storing and securing their users' stream keys.

Request

GET /api/multistream/target/{id}

curl 'https://livepeer.studio/api/multistream/target/{id}' \
-H 'authorization: Bearer {api-key}'

Response

{
"id": "{id}",
"userId": "USER123",
"name": "Eli's Twitch"
}

List

You can also list all existing Multistream Targets in the account by omitting the {id} segment in the above request.

Request

GET /api/multistream/target

curl 'https://livepeer.studio/api/multistream/target' \
-H 'authorization: Bearer {api-key}'

Response

The response is an array of Multistream Target objects, as returned from the read API above. The pagination should be done exactly the same as the other Livepeer Studio list APIs.

Update

You can change an existing target properties at will, and it will affect any stream that is currently using it. Notice that changes will only take effect when the next stream session is started.

One of the updateable properties is the disabled field. It can be used to disable multistreaming to a specific target without the need of removing them from streams nor deleting the target completely.

Request

PATCH /api/multistream/target/{id}

curl -X PATCH 'https://livepeer.studio/api/multistream/target/{id}' \
-H 'content-type: application/json' \
-H 'authorization: Bearer {api-key}' \
-d '{
"name": "Not Eli\'s Twitch",
"url": "rtmp://rtmp.twitter.com/SECRET",
"disabled": true
}'

Response

All request fields are optional. There is no response on a success (HTTP 204 No Content).

Delete

Finally, you can also delete a Multistream Target object completely by calling the delete API. You should not do this if any Streams are still referencing that target or a broken reference will be left. So first update (PATCH) any Stream removing the reference to the Multistream Target and only then actually delete it.

Request

DELETE /api/multistream/target/{id}

curl -X DELETE 'https://livepeer.studio/api/multistream/target/{id}' \
-H 'authorization: Bearer {api-key}'

Response

There is no response on a success (HTTP 204 No Content).

Understanding Multistream Performance

Dashboard

While a session is active that has multistream targets configured, you'll be able to see if a destination is "Active" or "Offline". NOTE: There may be a slight delay between starting the stream and the push destinations connecting. When starting to stream to multistream targets, use these indicators to understand whether it has connected to its target(s).

On the stream page where you've configured your multistream targets, select the "Health" tab at the top. While a session is active, you'll see the ingest rate of the source stream.

API

We have 3 webhooks to help you monitor the state of your Multistream Targets::

  • multistream.connected: When we have successfully connected to the Multistream Target and you're also online in the other service you are multistreaming to.
  • multistream.error: In case any error has occurred during connection to the Multistream Target. This means some kind of problem with the configuration or the other service you are multistreaming to.
  • multistream.disconnected: Sent after a stream is ended to indicate that Multistream has also ended for the respective target.