LiveStreamStartedPayload live.stream.started@1

Generated at from openvibe-contracts v0.33.0 and openvibe-sdk v0.5.0.

Version
1.0.0
Owner
live
Visibility
public
Status
active
Compatibility
backward
Decision
ADR-004
Schema
https://openvibe.network/contracts/events/payloads/live.stream.started.v1.json

live.stream.started v1 (OpenVibe.Live server/events/stream-events.js envelopeFor, fired by server/db/database.js createStream). A streams row went live: WebRTC/JSMPEG from the dashboard, RTMP ingest, WHIP, or an OpenRe.Stream session mirrored into Live. Written to Live's event_outbox in the transaction that inserts the row, so the event exists if and only if the stream did. Carries public channel facts only (the stream is listed publicly already); consumers such as Network's go-live notifications decide who hears about it. Never the stream key, the Live user id or the description. Envelope: subject { type: stream, id: <stream_id as a string>, revision: 1 }, visibility public, priority important, actor the streamer's user subject when Live knows it, else service:live.

Fields

FieldTypeRequiredDescriptionConstraints
stream_idintegeryesLive's streams row id (the envelope subject id).
  • minimum 1
channelobjectyes
  • no other fields
channel.usernamestringyesThe streamer's Live username (the channel slug).
  • minLength 1
channel.display_namestringyesThe display name, or the username when there is none.
  • minLength 1
channel.urlstringyesThe channel page, https://openvibe.live/@<username, URI-encoded>. Events from Live before 4c70332 (2026-09-23) carry https://openvibe.live/<username>, which Live answers with a 301 to the @ address since that commit.
  • pattern ^https://openvibe\.live/
  • format uri
channel.subjectobjectThe streamer's canonical subject; absent until Live has seen it (a Network sign-in or the subject backfill).
  • no other fields
channel.subject.typeconstyes
  • = "user"
channel.subject.idstringyes
  • pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$
titlestringyes
categorystring | nullyesnull when the streamer chose none (the AI classifies the stream from what it shows).
protocolenumyesHow the stream is ingested (WHIP is webrtc; OpenRe and RTMP are rtmp).
  • one of "jsmpeg", "webrtc", "rtmp"
is_nsfwbooleanyes
started_atstring | nullyesUTC. null only for a row without a start time, which createStream never writes.
  • format date-time

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: no-subject-no-category
{
  "stream_id": 4212,
  "channel": {
    "username": "jp_guy",
    "display_name": "jp_guy",
    "url": "https://openvibe.live/@jp_guy"
  },
  "title": "jp_guy's Stream",
  "category": null,
  "protocol": "rtmp",
  "is_nsfw": false,
  "started_at": "2026-09-23T18:02:11.000Z"
}
Valid: with-subject
{
  "stream_id": 4211,
  "channel": {
    "username": "alice",
    "display_name": "Alice",
    "url": "https://openvibe.live/@alice",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    }
  },
  "title": "Morning walk through Shinjuku",
  "category": "irl",
  "protocol": "webrtc",
  "is_nsfw": false,
  "started_at": "2026-09-23T18:02:11.000Z"
}
Rejected: carries-ended-fields
{
  "stream_id": 4211,
  "channel": {
    "username": "alice",
    "display_name": "Alice",
    "url": "https://openvibe.live/@alice",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    }
  },
  "title": "Morning walk through Shinjuku",
  "category": "irl",
  "protocol": "webrtc",
  "is_nsfw": false,
  "started_at": "2026-09-23T18:02:11.000Z",
  "ended_at": "2026-09-23T19:02:11.000Z",
  "duration_seconds": 3600
}
Rejected: live-user-id
{
  "stream_id": 4211,
  "channel": {
    "username": "alice",
    "display_name": "Alice",
    "url": "https://openvibe.live/@alice",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    },
    "user_id": 501
  },
  "title": "Morning walk through Shinjuku",
  "category": "irl",
  "protocol": "webrtc",
  "is_nsfw": false,
  "started_at": "2026-09-23T18:02:11.000Z"
}
Rejected: unknown-protocol
{
  "stream_id": 4211,
  "channel": {
    "username": "alice",
    "display_name": "Alice",
    "url": "https://openvibe.live/@alice",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    }
  },
  "title": "Morning walk through Shinjuku",
  "category": "irl",
  "protocol": "srt",
  "is_nsfw": false,
  "started_at": "2026-09-23T18:02:11.000Z"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('live.stream.started@1', value);   // { valid, errors: [{ path, message }] }