Red5 Documentation

Stream Manager 2.0 Explicit Provisioning

Overview

This guide explains how to use explicit provisioning with Red5 Pro Stream Manager 2.0 autoscaling. Explicit provisioning gives you fine-grained control over where and how provisions are distributed to servers based on capabilities.

For more information about provisions in Stream Manager 2.0:

What’s New: Explicit Distribution

Previously, provisions were distributed automatically when calling Get Server for Publish with specific flags (transcode=true, restream=true). The new workflow introduces:

  1. Separate /distribute endpoint – Explicitly distribute provisions to servers based on capabilities
  2. Capability-based selection – Control exactly which node types receive provisions
  3. Flexible workflows – Create provision → Distribute → Publish, or combine steps
  4. Egress restreaming – Push restreamers to edge nodes instead of origin nodes

Key Concepts

Provision: A configuration that defines additional parameters for a stream (transcoding settings, ingest credentials, cloud storage, etc.)

Distribution: The act of sending a provision to one or more nodes so they can apply the configuration

Capabilities: Node role attributes that determine what functions a node can perform:

  • PUBLISH – Origin nodes that accept published streams
  • TRANSCODE – Transcoder nodes that create ABR variants
  • SUBSCRIBE – Edge nodes that serve subscribers
  • MIX – Mixer nodes for conferencing

For more information about node roles and capabilities, see:


Three-Level Capability Precedence

When selecting servers for provision distribution, capabilities are determined using a three-level precedence system. This applies to both:

  • The new /distribute endpoint
  • The traditional Get Server for Publish endpoint, when distribute=true (or unspecified; true by default)

This gives you flexible control over where provisions are distributed.

1. API Parameter Capabilities (Highest Priority)

If the API call includes an explicit capabilities parameter, those capabilities are used exclusively.

Example:

POST /as/v1/streams/provision/default/distribute/my-provision?capabilities=SUBSCRIBE

Use case: Override provision settings to push a restreamer to edge nodes instead of origin.

2. Provision Capabilities (Medium Priority)

If no API capabilities are provided, check if the provision itself has a capabilities field. If present and non-empty, use those capabilities.

Example provision:

{
  "provisionGuid": "my-provision",
  "capabilities": ["TRANSCODE","PUBLISH"],
  "streams": [...]
}

Use case: Provision declares it requires transcoding capability and an ingress (“PUBLISH”) node.

3. Implicit Capabilities (Lowest Priority/Fallback)

If neither API nor provision specify capabilities, derive them implicitly:

  • If provision has videoParams → Implicit TRANSCODE capability
  • If provision has camParams → Implicit PUBLISH capability
  • Otherwise → Default PUBLISH capability

Example:

{
  "provisionGuid": "abr-provision",
  "streams": [
    {
      "streamGuid": "live/test_1",
      "videoParams": {"videoWidth": 1280, ...}
    }
  ]
}

This implicitly requires TRANSCODE capability because of videoParams.

Why This Matters

Flexibility: The precedence system allows you to:

  • Create a provision with default capabilities
  • Override them per-distribution using the API parameter
  • Enable new use cases (like egress restreaming) without modifying existing provisions

Example – Egress Restreaming:

A restreamer provision normally goes to origin nodes (implicit PUBLISH). But you can override with ?capabilities=SUBSCRIBE to push it to edge nodes instead:

POST /as/v1/streams/provision/default/distribute/rtmp-push?capabilities=SUBSCRIBE

This is how egress restreaming works – the API parameter overrides the implicit behavior.


Workflow Comparison

Old Workflow (Implicit Distribution)

Simple case: ABR with transcoding

  1. Create ABR provision with videoParams
  2. Get Server for Publish (implicitly distributes to origin + transcoder)
  3. Publish to returned server (transcoder)
POST /as/v1/streams/provision/{nodeGroup}
GET /as/v1/streams/stream/{nodeGroup}/publish/{streamGuid}?transcode=true

Limitations:

  • Distribution happens automatically during Get Server for Publish
  • Limited control over where provisions go (always origin + transcoder for transcode=true)
  • Restreamer provisions always go to origin/transcoder nodes (ingest restreaming only)
  • Cannot test distribution separately from publishing
  • Complex case: To use both transcode=true AND restream=true, you must create TWO separate provisions with different provisionGuid values, where the restreamer provision’s streamGuid matches the top-level ABR variant

New Workflow (Explicit Distribution)

Simple case: ABR with transcoding

  1. Create ABR provision
POST /as/v1/streams/provision/{nodeGroup}
  1. Explicitly distribute provision to origin and transcoder
POST /as/v1/streams/provision/{nodeGroup}/distribute/{provisionGuid}?capabilities=PUBLISH,TRANSCODE
  1. Get Server for Publish (optionally skip distribution with distribute=false)
GET /as/v1/streams/stream/{nodeGroup}/publish/{streamGuid}?distribute=false
  1. Publish to returned server (transcoder)
ffmpeg -stream_loop -1 -re -i testvideo.mp4 -c:v libx264 -profile:v baseline -c:a aac -b:v 500k -f flv rtmp://158.0.0.223:1935/live/test1_1

Benefits:

  • Separate distribution from server selection
  • Precise control via capabilities parameter
  • Can push restreamers to edge nodes (egress restreaming) using capabilities=SUBSCRIBE
  • Easier testing and debugging
  • Same workflow works for both simple and complex cases

Authentication

All provision API calls require a valid JWT presented in the Authorization header as a bearer token:

export JWT="your-jwt-token-here"
curl -H "Authorization: Bearer ${JWT}" ...

See the Stream Manager 2.0 Auth API documentation for obtaining tokens.


Use Case 1: ABR Provision Without Transcoding

Scenario: Publish a stream with multiple ABR variants, all generated by the publisher (no server-side transcoding).

Provision Definition

abr-no-transcode.json

[
  {
    "provisionGuid": "abr-stream1",
    "streams": [
      {
        "streamGuid": "live/stream1_3",
        "abrLevel": 3,
        "videoParams": {
          "videoWidth": 320,
          "videoHeight": 180,
          "videoBitRate": 500000
        }
      },
      {
        "streamGuid": "live/stream1_2",
        "abrLevel": 2,
        "videoParams": {
          "videoWidth": 640,
          "videoHeight": 360,
          "videoBitRate": 1000000
        }
      },
      {
        "streamGuid": "live/stream1_1",
        "abrLevel": 1,
        "videoParams": {
          "videoWidth": 1280,
          "videoHeight": 720,
          "videoBitRate": 2000000
        }
      }
    ]
  }
]

Workflow Steps

1. Create Provision

curl -H "Content-Type: application/json" 
     -H "Authorization: Bearer ${JWT}" 
     -X POST 
     --data @abr-no-transcode.json 
     https://streammanager.example.com/as/v1/streams/provision/default

2. Distribute to Origin Node (Explicit)

curl -H "Authorization: Bearer ${JWT}" 
     -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/abr-stream1?capabilities=PUBLISH&endpoints=1&blocking=true"

Response:

[
  {
    "streamGuid": "live/stream1_1",
    "serverAddress": "192.168.1.10",
    "nodeRole": "origin",
    "nodeState": "INSERVICE",
    "subGroup": "us-east"
  }
]

3. Get Server for Publish (Skip Distribution)

curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/stream1_1?distribute=false"

Response: Same as step 2 (provision already distributed)

4. Publish All Variants

Use Red5 Pro SDK or RTMP encoder to publish all three variants to the returned server:

  • live/stream1_1 (1280×720, 2 Mbps)
  • live/stream1_2 (640×360, 1 Mbps)
  • live/stream1_3 (320×180, 500 Kbps)

5. Verify Streams

curl -H "Authorization: Bearer ${JWT}" 
     "https://streammanager.example.com/as/v1/streams/stream/default?stats=true"

6. Subscribe

Get edge server for any variant:

curl "https://streammanager.example.com/as/v1/streams/stream/default/subscribe/live/stream1_1"

Use Case 2: ABR Provision With Transcoding

Scenario: Publish one high-quality stream, let the server transcode it into multiple ABR variants.

Provision Definition

abr-transcode.json

[
  {
    "provisionGuid": "abr-transcode1",
    "capabilities": ["TRANSCODE"],
    "streams": [
      {
        "streamGuid": "live/mystream_3",
        "abrLevel": 3,
        "videoParams": {
          "videoWidth": 320,
          "videoHeight": 180,
          "videoBitRate": 500000
        }
      },
      {
        "streamGuid": "live/mystream_2",
        "abrLevel": 2,
        "videoParams": {
          "videoWidth": 640,
          "videoHeight": 360,
          "videoBitRate": 1000000
        }
      },
      {
        "streamGuid": "live/mystream_1",
        "abrLevel": 1,
        "videoParams": {
          "videoWidth": 1280,
          "videoHeight": 720,
          "videoBitRate": 2000000
        }
      }
    ]
  }
]

Workflow Steps

1. Create Provision

curl -H "Content-Type: application/json" 
     -H "Authorization: Bearer ${JWT}" 
     -X POST 
     --data @abr-transcode.json 
     https://streammanager.example.com/as/v1/streams/provision/default

2. Distribute to Origin AND Transcoder (Explicit)

curl -H "Authorization: Bearer ${JWT}" 
     -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/abr-transcode1?capabilities=PUBLISH,TRANSCODE&endpoints=1&blocking=true"

Response:

[
  {
    "streamGuid": "live/mystream_1",
    "serverAddress": "192.168.1.20",
    "nodeRole": "transcoder",
    "nodeState": "INSERVICE",
    "subGroup": "us-east"
  },
  {
    "streamGuid": "live/mystream_1",
    "serverAddress": "192.168.1.10",
    "nodeRole": "origin",
    "nodeState": "INSERVICE",
    "subGroup": "us-east"
  }
]

Note: The transcoder is listed first – this is where you should publish.

3. Get Server for Publish (Combined Approach)

Alternatively, use the traditional approach with transcode=true:

curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/mystream_1?transcode=true&distribute=true"

This both selects servers and distributes the provision in one call.

4. Publish to Transcoder

Publish only live/mystream_1 to the transcoder address (first result).

The transcoder will:

  • Receive your high-quality stream
  • Transcode it into all three variants
  • Forward all variants to the origin

5. Verify All Variants Exist

curl -H "Authorization: Bearer ${JWT}" 
     "https://streammanager.example.com/as/v1/streams/stream/default/live/mystream_1?stats=true"

You should see three streams (mystream_1, mystream_2, mystream_3) all on the origin node.


Use Case 3: Ingest Restreamer (SRT/RTSP/IP Camera)

Scenario: Ingest a stream from an external source (SRT listener, RTSP camera, MPEG-TS) onto an origin node.

Provision Definition

ingest-srt-persist.json

[
  {
    "provisionGuid": "srt-camera1",
    "streams": [
      {
        "streamGuid": "live/camera1",
        "abrLevel": 0,
        "camParams": {
          "properties": {
            "action": "create",
            "type": "srt",
            "ip": "0.0.0.0",
            "port": "9000",
            "frameType": 0,
            "latency": 120,
            "reorder": 16,
            "overhead": 100,
            "keyLength": 0,
            "unlinkClock": false,
            "audio": true,
            "video": true,
            "persist": "true"
          }
        }
      }
    ]
  }
]

Parameters Explained:

  • type: "srt" – SRT listener mode (other options: rtsp, mpegts, zixi-push, zixi-pull)
  • persist: "true" – If the stream goes away, automatically retry/redistribute
  • port: "9000" – Listen on port 9000 for incoming SRT connection

Workflow Steps

1. Create Provision

curl -H "Content-Type: application/json" 
     -H "Authorization: Bearer ${JWT}" 
     -X POST 
     --data @ingest-srt-persist.json 
     https://streammanager.example.com/as/v1/streams/provision/default

2. Distribute to Origin Node

curl -H "Authorization: Bearer ${JWT}" 
     -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/srt-camera1?capabilities=PUBLISH&blocking=true"

Response:

[
  {
    "streamGuid": "live/camera1",
    "serverAddress": "192.168.1.10",
    "nodeRole": "origin",
    "nodeState": "INSERVICE",
    "subGroup": "us-east"
  }
]

3. Get Server for Publish (Alternative)

curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/camera1?restream=true"

This combines steps 2-3 using the implicit distribution approach.

4. Send SRT Stream to Origin

From your camera or encoder, send SRT stream to srt://192.168.1.10:9000:

ffmpeg -f lavfi -re -i testsrc=size=1280x720:rate=30 
       -f lavfi -re -i sine=frequency=1000:sample_rate=44100 
       -pix_fmt yuv420p -c:v libx264 -b:v 2000k 
       -c:a aac -b:a 128k 
       -f mpegts "srt://192.168.1.10:9000?pkt_size=1316"

5. Verify Stream is LIVE

curl -H "Authorization: Bearer ${JWT}" 
     "https://streammanager.example.com/as/v1/streams/stream/default/live/camera1?stats=true"

Expected state: "state": "LIVE"

6. Subscribe

curl "https://streammanager.example.com/as/v1/streams/stream/default/subscribe/live/camera1"

7. Stream Stops – Automatic Recovery

If the SRT source disconnects and then reconnects, the persist: "true" flag ensures the restreamer automatically retries and the stream comes back without manual intervention.


Use Case 4: Combined ABR + Restreamer (Ingest with Transcoding)

Scenario: Ingest from an IP camera and transcode into multiple variants.

Provisions

Create two separate provisions:

ingest-camera.json (Restreamer)

[
  {
    "provisionGuid": "camera-ingest",
    "streams": [
      {
        "streamGuid": "live/camera1",
        "abrLevel": 0,
        "camParams": {
          "properties": {
            "action": "create",
            "type": "rtsp",
            "rtspUri": "rtsp://192.168.100.50:554/stream",
            "immediate": "true",
            "persist": "true"
          }
        }
      }
    ]
  }
]

transcode-camera.json (ABR Transcoding)

[
  {
    "provisionGuid": "camera-abr",
    "capabilities": ["TRANSCODE"],
    "streams": [
      {
        "streamGuid": "live/camera1_3",
        "abrLevel": 3,
        "videoParams": {
          "videoWidth": 320,
          "videoHeight": 180,
          "videoBitRate": 500000
        }
      },
      {
        "streamGuid": "live/camera1_2",
        "abrLevel": 2,
        "videoParams": {
          "videoWidth": 640,
          "videoHeight": 360,
          "videoBitRate": 1000000
        }
      },
      {
        "streamGuid": "live/camera1_1",
        "abrLevel": 1,
        "videoParams": {
          "videoWidth": 1280,
          "videoHeight": 720,
          "videoBitRate": 2000000
        }
      }
    ]
  }
]

Workflow Steps

1. Create Both Provisions

curl -H "Content-Type: application/json" -H "Authorization: Bearer ${JWT}" 
     -X POST --data @ingest-camera.json 
     https://streammanager.example.com/as/v1/streams/provision/default

curl -H "Content-Type: application/json" -H "Authorization: Bearer ${JWT}" 
     -X POST --data @transcode-camera.json 
     https://streammanager.example.com/as/v1/streams/provision/default

2. Distribute Restreamer to Origin

curl -H "Authorization: Bearer ${JWT}" -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/camera-ingest?capabilities=PUBLISH&blocking=true"

The origin node immediately begins ingesting from the RTSP camera.

3. Distribute ABR to Origin and Transcoder

curl -H "Authorization: Bearer ${JWT}" -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/camera-abr?capabilities=PUBLISH,TRANSCODE&blocking=true"

The transcoder pulls live/camera1 from the origin and begins creating variants.

4. Verify All Streams

curl -H "Authorization: Bearer ${JWT}" 
     "https://streammanager.example.com/as/v1/streams/stream/default?stats=false"

You should see camera1, camera1_1, camera1_2, camera1_3.


Use Case 5: Egress Restreamer (RTMP Push to Social Media)

Scenario: Push a live stream to a social media platform (YouTube, Facebook, custom RTMP) from an edge node to avoid loading the origin.

Why Egress Restreaming?

Traditional (Old) Workflow:

  • Restreamer provisions always go to origin/transcoder nodes (using PUBLISH or TRANSCODE capability)
  • Origin node must both serve the stream AND push to social media
  • Increases origin load

New Egress Workflow:

  • Set capabilities: ["SUBSCRIBE"] to push restreamer to an edge node
  • Edge node subscribes to the stream and pushes to social media
  • Origin only serves the stream, egress load is offloaded to edge

Provision Definition

egress-rtmp-youtube.json

[
  {
    "provisionGuid": "social-youtube",
    "capabilities": ["SUBSCRIBE"],
    "streams": [
      {
        "streamGuid": "live/mystream",
        "abrLevel": 0,
        "camParams": {
          "properties": {
            "action": "create",
            "type": "rtmp-push",
            "rtmpUri": "rtmp://a.rtmp.youtube.com/live2/your-stream-key-here",
            "immediate": "false",
            "attempts": "3",
            "delayS": "10",
            "persist": "true"
          }
        }
      }
    ]
  }
]

Parameters Explained:

  • capabilities: ["SUBSCRIBE"]Key change! Pushes restreamer to edge node
  • type: "rtmp-push" – Push mode (forwards stream to external RTMP server)
  • immediate: "false" – Wait for source stream to be live before attempting push
  • attempts: "3" – Try up to 3 times if push fails
  • delayS: "10" – Wait 10 seconds between retries
  • persist: "true" – If stream stops and restarts, automatically resume push

Workflow Steps (Old Way – Ingest Restreamer)

For comparison, the old workflow for RTMP push:

# Create provision
curl -H "Content-Type: application/json" -H "Authorization: Bearer ${JWT}" 
     -X POST --data @old-rtmp-push.json 
     https://streammanager.example.com/as/v1/streams/provision/default

# Get Server for Publish distributes restreamer to ORIGIN
curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/mystream?restream=true"

# Publish to origin (origin pushes to YouTube)

Problem: Origin node handles both publishing and RTMP push.

Workflow Steps (New Way – Egress Restreamer)

1. Start Publishing First

# Get origin server
curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/mystream"

# Publish to origin (normal workflow, no restreaming yet)

2. Create Egress Provision

curl -H "Content-Type: application/json" 
     -H "Authorization: Bearer ${JWT}" 
     -X POST 
     --data @egress-rtmp-youtube.json 
     https://streammanager.example.com/as/v1/streams/provision/default

3. Distribute to Edge Node (Egress)

curl -H "Authorization: Bearer ${JWT}" 
     -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/social-youtube?capabilities=SUBSCRIBE&blocking=true"

Response:

[
  {
    "streamGuid": "live/mystream",
    "serverAddress": "192.168.1.30",
    "nodeRole": "edge",
    "nodeState": "INSERVICE",
    "subGroup": "us-west"
  }
]

What Happens:

  1. Provision distributed to edge node (not origin!)
  2. Edge node subscribes to live/mystream from origin
  3. Edge node pushes received stream to YouTube RTMP server
  4. Origin continues serving stream normally

4. Stream Stops and Restarts

If you stop publishing and restart, the persist: "true" flag ensures:

  1. Edge detects stream came back online
  2. RTMP push automatically resumes
  3. No manual intervention needed

5. Delete Provision (Stop Push)

curl -H "Authorization: Bearer ${JWT}" 
     -X DELETE 
     "https://streammanager.example.com/as/v1/streams/provision/default/social-youtube"

The edge node stops pushing to YouTube.


API Reference Summary

Create Provision

Endpoint: POST /as/v1/streams/provision/{nodeGroupName}

Request Body: Array of ProvisionRequest objects

Response: 201 Created

See Stream Manager 2.0 Streams Provision API for complete schema.


Distribute Provision

Endpoint: POST /as/v1/streams/provision/{nodeGroupName}/distribute/{provisionGuid}

Query Parameters:

Parameter Type Required Default Description
capabilities Set No (inferred) Comma-separated capabilities: PUBLISH, TRANSCODE, SUBSCRIBE, MIX, ZIXI, XILINX
strict Boolean No false If true, require exact subgroup match
subgroup String No null Preferred subgroup/region
endpoints Integer No 1 Number of nodes to select
blocking Boolean No true Wait for distribution to complete

Capability Precedence:

  1. API parameter (highest priority) – ?capabilities=SUBSCRIBE
  2. Provision capabilities"capabilities": ["TRANSCODE"] in provision JSON
  3. Implicit capabilities (lowest priority):
    • If provision has videoParamsTRANSCODE
    • If provision has camParamsPUBLISH
    • Otherwise → PUBLISH

Response: 200 OK with array of StreamLocation objects

Example:

curl -H "Authorization: Bearer ${JWT}" -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/my-provision?capabilities=PUBLISH,TRANSCODE&endpoints=1&blocking=true"

Get Server for Publish (Enhanced)

Endpoint: GET /as/v1/streams/stream/{nodeGroupName}/publish/{streamGuid}

Query Parameters:

Parameter Type Required Default Description
distribute Boolean No true New! Set to false to skip provision distribution
transcode Boolean No false Request transcoder node (implies distribution)
restream Boolean No false Request restreamer provision (implies distribution)
strict Boolean No false Require exact subgroup match
subgroup String No null Preferred subgroup/region
endpoints Integer No 1 Number of origin nodes

New Behavior:

  • distribute=false – Only selects servers, does not distribute provision. Use this after calling /distribute explicitly.
  • distribute=true (default) – Selects servers AND distributes provision (old behavior, still supported).

Example (Skip Distribution):

# 1. Distribute explicitly
curl -H "Authorization: Bearer ${JWT}" -X POST 
     "https://streammanager.example.com/as/v1/streams/provision/default/distribute/my-provision?capabilities=PUBLISH"

# 2. Get server without redistributing
curl "https://streammanager.example.com/as/v1/streams/stream/default/publish/live/mystream?distribute=false"

Delete Provision

Endpoint: DELETE /as/v1/streams/provision/{nodeGroupName}/{provisionGuid}

Deletes the provision and kills any active restreamers on nodes.

Example:

curl -H "Authorization: Bearer ${JWT}" -X DELETE 
     "https://streammanager.example.com/as/v1/streams/provision/default/my-provision"

Best Practices

1. Use Explicit Distribution for Testing

Separate distribution from publishing when testing:

# Test distribution
curl -X POST ".../distribute/my-provision?capabilities=PUBLISH"

# Verify it worked
curl ".../provision/default/my-provision?status=true"

# Then publish
curl ".../publish/live/mystream?distribute=false"

2. Egress Restreaming for Scale

For RTMP push (social media, CDN), always use egress restreaming:

{
  "capabilities": ["SUBSCRIBE"],
  "streams": [{
    "camParams": {
      "properties": {
        "type": "rtmp-push",
        "rtmpUri": "rtmp://..."
      }
    }
  }]
}

This offloads push to edge nodes.

3. Persist for Reliability

Always use "persist": "true" for production restreamers (ingest and egress):

"camParams": {
  "properties": {
    "persist": "true"
  }
}

The Stream Manager will automatically retry/redistribute if the stream goes away.

4. Immediate Flag for Ingest

For ingest restreamers, use "immediate": "true" when the source is already streaming:

"camParams": {
  "properties": {
    "type": "rtsp",
    "rtspUri": "rtsp://camera.local/stream",
    "immediate": "true"
  }
}

For egress/push, use "immediate": "false" to wait for the source stream.

5. Retry Configuration

For unreliable networks, configure retries:

"camParams": {
  "properties": {
    "attempts": "20",
    "delayS": "15"
  }
}

This gives 20 attempts × 15 seconds = 5 minutes of retry time.


Troubleshooting

Provision Not Distributing

Symptom: /distribute returns success but nodes don’t show the provision.

Check:

  1. Verify node roles have the requested capabilities in nodegroup config
  2. Check node capacity – nodes over capacity are skipped
  3. Verify nodes are in INSERVICE state: GET /as/v1/streams/stream/debug/nodes
  4. Check Stream Manager logs for errors

Restreamer Not Starting

Symptom: Provision distributed but restreamer doesn’t activate.

Check:

  1. Check node logs at /usr/local/red5pro/log/red5.log
  2. For ingest: verify source is reachable from node
  3. For egress: verify source stream is LIVE before restreamer attempts

Stream State is WAIT Instead of LIVE

When a restreamer is provisioned but the source stream doesn’t exist yet, the state shows WAIT. This is expected – once the source appears or restarts, the restreamer will activate and state becomes LIVE.

Capability Confusion

Symptom: Wrong nodes selected for distribution.

Remember the precedence:

  1. API ?capabilities= parameter (overrides everything)
  2. Provision "capabilities": [...] field
  3. Implicit (inferred from videoParams/camParams)

Use explicit API parameter to override: ?capabilities=SUBSCRIBE


Migration from Old to New Workflow

For Ingest (RTSP, SRT, IP Cameras)

Old:

curl -X POST --data @provision.json .../provision/default
curl ".../publish/live/camera1?restream=true"

New (equivalent):

curl -X POST --data @provision.json .../provision/default
curl -X POST ".../distribute/camera-provision?capabilities=PUBLISH"

New (explicit):

curl -X POST --data @provision.json .../provision/default
curl -X POST ".../distribute/camera-provision?capabilities=PUBLISH"
curl ".../publish/live/camera1?distribute=false"

For RTMP Push (Social Media)

Old (ingest restreamer on origin):

{
  "provisionGuid": "social1",
  "streams": [{
    "streamGuid": "live/mystream",
    "camParams": { "properties": { "type": "rtmp-push", "rtmpUri": "..." } }
  }]
}
curl ".../publish/live/mystream?restream=true"

New (egress restreamer on edge):

{
  "provisionGuid": "social1",
  "capabilities": ["SUBSCRIBE"],
  "streams": [{
    "streamGuid": "live/mystream",
    "camParams": { "properties": { "type": "rtmp-push", "rtmpUri": "..." } }
  }]
}
curl ".../publish/live/mystream"  # No restream flag
curl -X POST ".../distribute/social1?capabilities=SUBSCRIBE"

Summary

Explicit provisioning gives you:

Separation of concerns – Create, distribute, and publish as independent steps
Capability-based control – Choose exactly which node types receive provisions
Egress restreaming – Offload RTMP push to edge nodes using SUBSCRIBE capability
Easier testing – Test distribution separately from publishing
Backward compatibility – Old implicit workflow still works

Key Takeaways:

  • Use POST /as/v1/streams/provision/{nodeGroup}/distribute/{provisionGuid} for explicit distribution
  • Set ?capabilities=SUBSCRIBE for egress restreaming (RTMP push to social media)
  • Use ?distribute=false in Get Server for Publish to skip redistribution
  • Always use "persist": "true" for production restreamers
  • API capabilities parameter overrides provision capabilities

For more details on provision schemas, see Stream Manager 2.0 Streams Provision API.