1NIP-532======34Live Streaming and Spaces5-------------------------67`draft` `optional`89This NIP introduces event kinds to advertise live spaces and the participation of pubkeys in them.1011## Live Streaming1213A special event with `kind:30311` "Live Streaming Event" is defined as an _addressable event_ whose tags advertise the content and participants of a live stream.1415Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity.1617For example:1819```yaml20{21 "kind": 30311,22 "tags": [23 ["d", "<unique identifier>"],24 ["title", "<name of the event>"],25 ["summary", "<description>"],26 ["image", "<preview image url>"],27 ["t", "hashtag"]28 ["streaming", "<url>"],29 ["recording", "<url>"], // used to place the edited video once the activity is over30 ["starts", "<unix timestamp in seconds>"],31 ["ends", "<unix timestamp in seconds>"],32 ["status", "<planned, live, ended>"],33 ["current_participants", "<number>"],34 ["total_participants", "<number>"],35 ["p", "91cf9..4e5ca", "wss://provider1.com/", "Host", "<proof>"],36 ["p", "14aeb..8dad4", "wss://provider2.com/nostr", "Speaker"],37 ["p", "612ae..e610f", "ws://provider3.com/ws", "Participant"],38 ["relays", "wss://one.com", "wss://two.com", /*...*/],39 ["pinned", "<event id of pinned live chat message>"],40 ],41 "content": "",42 // other fields...43}44```4546A distinct `d` tag should be used for each activity. All other tags are optional.4748Providers SHOULD keep the participant list small (e.g. under 1000 users) and, when limits are reached, Providers SHOULD select which participants get named in the event. Clients should not expect a comprehensive list. Once the activity ends, the event can be deleted or updated to summarize the activity and provide async content (e.g. recording of the event).4950Clients are expected to subscribe to `kind:30311` events in general or for given follow lists and statuses. Clients MAY display participants' roles in activities as well as access points to join the activity.5152Live Activity management clients are expected to constantly update `kind:30311` during the event. Clients MAY choose to consider `status=live` events after 1hr without any update as `ended`. The `starts` and `ends` timestamp SHOULD be updated when the status changes to and from `live`5354The activity MUST be linked to using the [NIP-19](19.md) `naddr` code along with the `a` tag.5556### Proof of Agreement to Participate5758Event owners can add proof as the 5th term in each `p` tag to clarify the participant's agreement in joining the event. The proof is a signed SHA256 of the complete `a` Tag of the event (`kind:pubkey:dTag`) by each `p`'s private key, encoded in hex.5960Clients MAY only display participants if the proof is available or MAY display participants as "invited" if the proof is not available.6162This feature is important to avoid malicious event owners adding large account holders to the event, without their knowledge, to lure their followers into the malicious owner's trap.6364### Live Chat Message6566Event `kind:1311` is live chat's channel message. Clients MUST include the `a` tag of the activity. An `e` tag denotes the direct parent message this post is replying to.6768```yaml69{70 "kind": 1311,71 "tags": [72 ["a", "30311:<Community event author pubkey>:<d-identifier of the community>", "<Optional relay url>"],73 ],74 "content": "Zaps to live streams is beautiful.",75 // other fields...76}77```7879`q` tags MAY be used when citing events in the `.content` with [NIP-21](21.md).8081```json82["q", "<event-id> or <event-address>", "<relay-url>", "<pubkey-if-a-regular-event>"]83```8485Hosts may choose to pin one or more live chat messages by updating the `pinned` tags in the live event kind `30311`.8687### Examples8889#### Live Streaming9091```json92{93 "id": "57f28dbc264990e2c61e80a883862f7c114019804208b14da0bff81371e484d2",94 "pubkey": "1597246ac22f7d1375041054f2a4986bd971d8d196d7997e48973263ac9879ec",95 "created_at": 1687182672,96 "kind": 30311,97 "tags": [98 ["d", "demo-cf-stream"],99 ["title", "Adult Swim Metalocalypse"],100 ["summary", "Live stream from IPTV-ORG collection"],101 ["streaming", "https://adultswim-vodlive.cdn.turner.com/live/metalocalypse/stream.m3u8"],102 ["starts", "1687182672"],103 ["status", "live"],104 ["t", "animation"],105 ["t", "iptv"],106 ["image", "https://i.imgur.com/CaKq6Mt.png"]107 ],108 "content": "",109 "sig": "5bc7a60f5688effa5287244a24768cbe0dcd854436090abc3bef172f7f5db1410af4277508dbafc4f70a754a891c90ce3b966a7bc47e7c1eb71ff57640f3d389"110}111```112113#### Live Streaming chat message114115```json116{117 "id": "97aa81798ee6c5637f7b21a411f89e10244e195aa91cb341bf49f718e36c8188",118 "pubkey": "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24",119 "created_at": 1687286726,120 "kind": 1311,121 "tags": [122 ["a", "30311:1597246ac22f7d1375041054f2a4986bd971d8d196d7997e48973263ac9879ec:demo-cf-stream", "", "root"]123 ],124 "content": "Zaps to live streams is beautiful.",125 "sig": "997f62ddfc0827c121043074d50cfce7a528e978c575722748629a4137c45b75bdbc84170bedc723ef0a5a4c3daebf1fef2e93f5e2ddb98e5d685d022c30b622"126}127```128129## Meeting Spaces130131Meeting spaces contain one or more video/audio rooms where users can join and participate in the streaming.132133### Meeting Space Event (kind:30312)134135A special event with `kind:30312` "Space Host" defines the configuration and properties of a virtual interactive space. Each space has a unique identifier and can host multiple events/meetings.136137```yaml138{139 "kind": 30312,140 "tags": [141 ["d", "<unique identifier>"], // Required: Room identifier142 ["room", "<name of the room>"], // Required: Display name143 ["summary", "<description>"], // Optional: Room description144 ["image", "<preview image url>"], // Optional: Room image145 ["status", "<open, private, closed>"], // Required: Room accessibility146 ["service", "<url>"], // Required: URL to access the room147 ["endpoint", "<url>"], // Optional: API endpoint for status/info148 ["t", "<hashtag>"], // Optional: Multiple hashtags allowed149 ["p", "<pubkey>", "<url>", "<role>", "<proof>"], // Required: At least one provider150 ["relays", "<url>", "<url>", /*...*/] // Optional: Preferred relays151 ],152 "content": "" // Usually empty, may contain additional metadata153}154```155156Space properties:157* MUST be either open, private or closed. Closed means the room is not in operation.158* MAY specify access control policy for private rooms (e.g. invite-only, payment required)159* MAY persist when not in use160* MUST have at least one provider with "Host" role161* MAY have multiple providers with different roles162163Provider roles (p tags):164* Host: Full room management capabilities165* Moderator: Room moderation capabilities166* Speaker: Allowed to present/speak167* Optional proof field for role verification168169### Meeting Room Events (kind:30313)170171A special event with kind:30313 represents a scheduled or ongoing meeting within a room. It MUST reference its parent room using the d tag.172173```yaml174{175 "kind": 30313,176 "tags": [177 ["d", "<event-unique-identifier>"], // Required: Event identifier178 ["a", "30312:<pubkey>:<room-id>", "wss://nostr.example.com"], // Required: Reference to parent space, 'd' from 30312179 ["title", "<meeting-title>"], // Required: Meeting title180 ["summary", "<description>"], // Optional: Meeting description181 ["image", "<preview image url>"], // Optional: Meeting image182 ["starts", "<unix timestamp>"], // Required: Start time183 ["ends", "<unix timestamp>"], // Optional: End time184 ["status", "<planned, live, ended>"], // Required: Meeting status185 ["total_participants", "<number>"], // Optional: Total registered186 ["current_participants", "<number>"], // Optional: Currently active187 ["p", "<pubkey>", "<url>", "<role>"], // Optional: Participant with role188 ],189 "content": "" // Usually empty, may contain additional metadata190}191```192193Event properties:194* MUST reference parent room via d tag195* MUST have a status (planned/live/ended)196* MUST have a start time197* MAY track participant counts198* MAY include participant roles specific to the event199200Event management:201* Clients SHOULD update event status regularly when live202* Events without updates for 1 hour MAY be considered ended203* starts and ends timestamps SHOULD be updated when status changes204205### Examples206207#### Meeting Space (kind:30312)208209```yaml210{211 "kind": 30312,212 "tags": [213 ["d", "main-conference-room"],214 ["room", "Main Conference Hall"],215 ["summary", "Our primary conference space"],216 ["image", "https://example.com/room.jpg"],217 ["status", "open"],218 ["service", "https://meet.example.com/room"],219 ["endpoint", "https://api.example.com/room"],220 ["t", "conference"],221 ["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca", "wss://nostr.example.com/", "Owner"],222 ["p", "14aeb..8dad4", "wss://provider2.com/", "Moderator"],223 ["relays", "wss://relay1.com", "wss://relay2.com"]224 ],225 "content": ""226}227```228229#### Meeting room (kind:30313)230231```yaml232{233 "kind": 30313,234 "tags": [235 ["d", "annual-meeting-2025"],236 ["a", "30312:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:main-conference-room", "wss://nostr.example.com"]237 ["title", "Annual Company Meeting 2025"],238 ["summary", "Yearly company-wide meeting"],239 ["image", "https://example.com/meeting.jpg"],240 ["starts", "1676262123"],241 ["ends", "1676269323"],242 ["status", "live"],243 ["total_participants", "180"],244 ["current_participants", "175"],245 ["p", "91cf9..4e5ca", "wss://provider1.com/", "Speaker"],246 ],247 "content": ""248}249```250### Room Presence251252New `kind: 10312` provides an event which signals presence of a listener.253254The presence event SHOULD be updated at regular intervals and clients SHOULD filter presence events older than255a given time window.256257**This kind `10312` is a regular replaceable event, as such presence can only be indicated in one room at a time.**258259```json260{261 "kind": 10312,262 "tags": [263 ["a" , "<room-a-tag>", "<relay-hint>", "root"],264 ["hand", "1"] // hand raised flag265 ]266}267```