Integrating Stream Providers with Maestro
This document can be followed by live-streaming providers to add live streaming capabilities for the Maestro platform.
Maestro supports a range of live streaming providers. To add your live-streaming capabilities to the platform, Maestro require the following minimal capabilities:
- RTMP Ingest
- Live HLS output
- CDN storage for live and recorded on-demand (VOD) assets
Below is a sequence diagram describing Maestro's standardized streaming provider integration workflow.
Optional workflows omitted
Registration
Registering your Streaming Provider Contract
Stream Provider -> Maestro
curl -X POST https://api.maestro.io/streamprovider/v1/register
-d {
"name": "my awesome streaming provider",
"urls": {
"createStream": "https://my.api/create",
"deleteStream": "https://my.api/delete",
"deleteVod": "https://my.api/assets/delete",
"startStream": "https://my.api/start",
"stopStream": "https://my.api/stop",
"verifyAccount": "https://my.api/verify" // required if useAccount: true
},
"accountCredentials": {}, // required if useAccount
"useAccount": false,
}
Response:
{
"id": "0866047ea2e84b41a58fa1b4a3b23687",
"authorization": "b0612f9f-03a8-4f59-9cb3-c7429b57c228"
}
Registration is a one-time event that does not need to be repeated for each session.
Save the authorization value in your database. That value must be present in the authorization header as a Bearer token to all requests back to Maestro, including webhooks, VOD’s, and making modifications to a provider contract that has already been registered (contracts are unique by name). The authorization does not expire and will be used for the lifetime of the registered provider.
Create Stream
Receiving a create stream request
Maestro -> Stream Provider
curl -X POST <your urls.createStream>
-d {
"fallbackImageUrl": "https://cdn.com/slate-image.jpg",
"title": "Baking with Bob",
"accountCredentials": {} // optional, see next section
}
title - A unique string identifier for the live stream.
fallbackImageUrl - A public URL for a static image asset for the transcoder output to fallback to in the case of an interruption in the stream ingest. This image should be the output of the live HLS during an encoder reconnect window.
Your Response:
{
"ingestUrl": "rtmp://some-ingest-url",
"streamKey": "02b1fa17fa634848d98306914b3f901bdb",
"playbackUrl": "https://url-user-can-use-to-view-stream",
"providerStreamId": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba",
}
`providerStreamId`` should be a unique identifier (GUID) to identify the stream (or a particular set of resources) on the stream provider side. In the remaining parts of the streaming workflow, Maestro’s API’s will use this ID to make requests to the streaming provider service.
Creating a stream using an existing client account
(Optional feature. To enable support register with useAccount: true )
Stream creation assumes usage would be billed to a master Maestro account. If you would like to support creating the streams using an existing customer’s account rather than the Maestro account, register the provider with option useAccount: true
. If not, this section can be skipped.
Additional Requirements
- An
accountCredentials
value will be required in the registration payload.
This map is how a streaming provider defines which account data are required in order to create the stream on the client’s account. The createStream
request will include this data in the payload. The schema for this map should be:
accountCredentials {
[credentialName: string]: label as string,
}
credentialName
keys will be reused by Maestro in the verifyAccount & createStream payloads (camelCase preferred).- The
label
will be used as an input field label in the Maestro UI for a client to connect their account details. This text will be rendered to the Maestro admin, so please keep it short and formatted (capitalize appropriately, no punctuation, etc.).
Example registration payload with useAccount feature enabled:
{
"name": "bill my customers",
"accountCredentials": {
"accountId": "Account ID",
"apiKey": "API Key",
},
"useAccount": true,
"urls": {
...
}
}
Example createStream
request including accountCredentials
:
curl -X POST <your createStream endpoint>
-d {
"title": "my stream",
"accountCredentials": {
"accountId": "123456789",
"apiKey": "h2fx-kc8ae-m02v"
}
}
- If the
accountCredentials
in the createStream request are not valid, return401
- If the account is valid but the stream cannot be created for another reason, such as resource limitations, return
403
status
2. If the useAccount
feature is enabled, the urls map in the registration must include verifyAccount. This endpoint will be utilized by Maestro to test the validity of a set of account details.
Example request:
curl -X POST <your verifyAccount url>
-d {
"accountCredentials": {
"accountId": "123456789",
"apiKey": "h2fx-kc8ae-m02v'
}
}
Responses:
- Valid account: respond with 200 status code
- Invalid account: return 401 status code
Start Stream
Receiving a start stream request
At the time of the request to start a stream, all content ingested from then forward should be recorded for later VOD playback. Note that the broadcaster can be previewing their stream before the startStream request. The HLS should be live as soon as the stream is ingesting.
curl -X POST <URL you provided for "startStream">
-d {
"id": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba",
"liveBroadcastId": "9e68e4c3-997c-4e84-b59a-ff083daa5511"
}
id
is theproviderStreamId
returned from the request to create the stream.- The
liveBroadcastId
is generated by Maestro to identify the broadcast. Cache it and return it with the VOD asset (see below).
Stop Stream
Receiving a stop stream request
The Stop Stream request should end the VOD recording, but leave the underlying stream / transcoder active. Content ingested after this request should not be added to the recorded VOD playlist.
curl -X POST <URL you provided for "stopStream">
-d {
"id": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba"
}
VOD Delivery
Sending a recording to Maestro
The request to stopStream finalizes the recording, so at this point a URL to the recorded VOD asset should be delivered back to Maestro.
Stream Provider -> Maestro
curl -X POST https://api.maestro.io/video/v3/vod
-H "Authorization: Bearer b0612f9f-03a8-4f59-9cb3-c7429b57c228"
-d {
"durationSeconds": 300,
"liveBroadcastId": "9e68e4c3-997c-4e84-b59a-ff083daa5511",
"vodId": "<my-unique-asset-id>",
"streamId": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba",
"url": "https://some-cdn/some-playback-url",
}
The Bearer
token GUID is the authorization
value returned to the stream provider from the request to /register.
The liveBroadcastId
returned to Maestro should be the same value from the startStream
request that initiated the VOD recording.
vodId
should be a unique GUID to use to reference a recording within the streaming provider service. The streaming provider should create an ID for a recording after it has been added to CDN storage and deliver that to Maestro’s video API with the url .
Delete (Disable) Stream
Receiving a delete stream request
A request from Maestro to delete a stream should ensure that a client encoder can no longer connect to the resources designated by the stream id. It should effectively block the ingest for that stream key and halt transcoding. The internal method of stopping the ingest is up to the provider, but the end result should be that all transcoding is disabled for that stream.
curl -X POST <URL you provided in "deleteStream">
-d {
"id": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba"
}
Delete VOD
Cleaning up a VOD Recording
The deleteVod endpoint should remove all recorded assets from storage for a specific live broadcast. This is different from the deleteStream endpoint which disables an ingest.
The id should point to a vodId that has already been delivered to Maestro using the video/v3/vod endpoint.
curl -X POST "<my deleteVod endpoint>"
-d {
"id": "a-unique-vod-id"
}
There is no UI in Maestro to trigger the delete Stream/VOD requests from Maestro. In order to complete integration testing, there are two endpoints available to test these requests.
Sending Webhooks to Maestro
Full integration as a Maestro Streaming Provider requires the provider to POST webhook event payloads to Maestro regarding the state of a stream.
This should happen for all streams created using the streaming provider contract, regardless of whether the stream was created on the Maestro account or a mutual customer’s account.
The provider's requests should be triggered when:
- A source encoder either connects to or disconnects from provider rtmp url
- When the live HLS manifest designated by the
playbackUrl
either has content to view or is empty/dead.
Maestro does not proxy the RTMP ingest URL. It is exposed directly to the end user.
Webhook Types
Type | Description |
---|---|
“connected” | Source encoder has connected |
“active” | Live HLS manifest has data, playback url does not 404 |
“disconnected” | Source encoder has disconnected |
“idle” | Live HLS manifest is empty, playback url is “dead” |
For all broadcasts, webhooks should be delivered in the above order. In the event of a non-200 response, use exponential retry backoff.
When thinking about event types, the important thing to remember is that the "connected" /"disconnected" events are concerning the source encoder → rtmp ingest connection state, while the "active" / "idle" events denote the playback and usually transcoder state.
curl -X POST https://api.maestro.io/stream/v1/webhook
-H "Authorization: Bearer b0612f9f-03a8-4f59-9cb3-c7429b57c228"
-d {
"type": "active" | "idle" | "connected" | "disconnected",
"id": "3b6d1467-55ad-4fc1-a89f-a259f55c1fba",
"time": 1613242238573, // unix epoch timestamp in milliseconds
}
Activate Stream (Optional)
It may not be necessary for all streaming providers to use the “activate” workflow.
In the case that a stream must be “activated” in order for the rtmp ingest to accept an incoming connection, the provider contract can support this by adding an activateStream
endpoint to the urls map.
Additionally, if the implementation of the provider deleteStream
url disables the livestream ingest, this route should be used to re-enable that ingest.
Example registration:
{
"name": "transcoder provider name",
"urls": {
...
"activateStream": "https://my.api/activate",
}
}
Example activateStream
request:
curl -X POST <activate stream url>
-H 'Authorization: Bearer <your auth token>`
-d {
"id": <your provider stream id>
}
- Duplicate requests can be ignored. i.e. an
activateStream
request for an already active stream can be ignored (return 200) - Streams should be automatically deactivated by the streaming provider based on an acceptable timeout period. A minimum window of 5 minutes should be allowed for an encoder to reconnect to an ingest before deactivating it.
- Note that deactivating the stream (stopping / cleaning up the transcoder) is different than disabling the stream (blocking the ingest)