If they’re seeing this right now here they go

# NIP: Watch Party Implementation

This document describes how this application implements watch parties using NIP-53 (Live Activities).

## Event Kinds

This application uses the following standard NIP-53 event kinds:

### Kind 30311: Live Event (Watch Party)

Used to create and manage watch parties. This is an addressable event that represents a live streaming/watch party session.

**Required Tags:**

- `d`: Unique identifier for the watch party

- `title`: Name of the watch party

- `streaming`: URL to the video/stream to watch

- `status`: Current status (`planned`, `live`, or `ended`)

- `starts`: Unix timestamp when the watch party started/will start

- `p`: Host's pubkey with role "Host"

**Optional Tags:**

- `summary`: Description of the watch party

- `image`: Thumbnail/preview image URL

- `t`: Hashtags for categorization

- `current_participants`: Number of currently active participants

- `total_participants`: Total number of participants who joined

- `ends`: Unix timestamp when the watch party ended/will end

**Example:**

```json

{

"kind": 30311,

"tags": [

["d", "wp-1702234567890-abc123"],

["title", "Movie Night: The Matrix"],

["summary", "Join us for a classic sci-fi movie night!"],

["streaming", "https://youtube.com/watch?v=example%22%5D,

["image", "%22%5D,

["status", "live"],

["starts", "1702234567"],

["p", "host-pubkey-hex", "", "Host"],

["t", "movies"],

["t", "scifi"]

],

"content": ""

}

```

### Kind 1311: Live Chat Message

Used for chat messages within a watch party. Each message references the parent watch party event.

**Required Tags:**

- `a`: Coordinate to the parent watch party event (format: `30311:pubkey:d-tag`, with `root` marker)

**Optional Tags:**

- `e`: Event ID of a message being replied to

- `video-timestamp`: Unix timestamp in seconds of video playback position when message was sent

**Example:**

```json

{

"kind": 1311,

"tags": [

["a", "30311:host-pubkey:wp-1702234567890-abc123", "", "root"],

["video-timestamp", "142"]

],

"content": "This scene is amazing! 🍿"

}

```

### Timestamped Comments

Chat messages can include a `video-timestamp` tag that records the playback position when the comment was made. This enables YouTube-style timestamped comments.

**Features:**

- Comments display clickable timestamp badges (e.g., "2:22")

- Click timestamp to jump to that moment in the video

- Filter toggle to show only messages relevant to current playback position

- Timestamps auto-added when enabled (toggle in chat UI)

- Messages within 30 seconds of current time shown when filtered

**Use Cases:**

- React to specific scenes in real-time

- Leave comments at particular moments for later viewers

- Create discussion threads around key moments

- Build community annotations on content

## Marathons (24/7 Series Streaming)

Marathons are continuous 24/7 watch parties for series collections with 7+ episodes. They enable synchronized viewing of entire series in order with automatic looping.

### Marathon Event Structure

Marathons use the same kind 30311 (Live Event) but with additional metadata:

**Required Tags:**

- All standard kind 30311 tags

- Multiple `streaming` tags, one per episode with optional episode label

- `t` tag with value "marathon" to identify marathon events

- `content` field containing playlist JSON

**Content Field JSON:**

```json

{

"episodes": [

{"episode": 1, "url": "https://..."},

{"episode": 2, "url": "https://..."}

],

"currentEpisode": 0,

"loop": true

}

```

**Example Marathon Event:**

```json

{

"kind": 30311,

"content": "{\"episodes\":[{\"episode\":1,\"url\":\"https://archive.org/ep1%5C%22%7D,%7B%5C%22episode%5C%22:2,%5C%22url%5C%22:%5C%22https://archive.org/ep2%5C%22%7D%5D,%5C%22currentEpisode%5C%22:0,%5C%22loop%5C%22:true%7D%22,

"tags": [

["d", "marathon-abc123"],

["title", "Cowboy Bebop Marathon"],

["summary", "24/7 marathon - 26 episodes playing in order"],

["streaming", "https://archive.org/ep1%22, "Episode 1"],

["streaming", "https://archive.org/ep2%22, "Episode 2"],

["status", "live"],

["t", "marathon"],

["t", "kinostr"],

["e", "original-series-post-id", "", "mention"]

]

}

```

### Marathon Features

- **Episode Navigation**: Users can skip forward/backward or jump to any episode

- **Continuous Playback**: Episodes play in sequence with automatic progression

- **24/7 Looping**: Series loops continuously for always-on viewing

- **Synchronized Viewing**: All participants watch the same episode together

- **Minimum 7 Episodes**: Only series with 7+ episodes qualify for marathons

### Series Detection

Series are automatically detected from kind 1 events containing 7+ video URLs. Each URL represents an episode in the series.

## Movie Libraries

This application includes a feature to browse movie collections curated by Nostr users. The implementation:

1. **Curator Discovery**: Users can browse featured curators or add custom curators by npub

2. **Movie Extraction**: Automatically extracts movie links from kind 1 (text notes) events

3. **Supported Platforms**: Archive.org, YouTube, Vimeo, and direct video links

4. **Quick Watch Parties**: Users can create watch parties directly from any movie in a library

5. **Attribution**: Watch parties created from library movies include an `e` tag referencing the original post

### Movie Detection

The application scans kind 1 events for URLs matching:

- `archive.org` domains

- YouTube URLs (`youtube.com`, `youtu.be`)

- Vimeo URLs (`vimeo.com`)

- Direct video files (`.mp4`, `.webm`, `.ogg`, `.m3u8`)

### Watch Party Tags for Library Movies

When creating a watch party from a library movie, additional tags are added:

```json

{

"kind": 30311,

"tags": [

["d", "unique-identifier"],

["title", "Movie Title"],

["streaming", "movie-url"],

["e", "original-post-event-id", "", "mention"],

["t", "kinostr"]

]

}

```

The `e` tag references the original movie post, and the `kinostr` tag categorizes it as movie-related content.

## Implementation Notes

### Video Platform Support

The video player component supports embedding from:

- YouTube (youtube.com, youtu.be)

- Vimeo (vimeo.com)

- Twitch (twitch.tv)

- Direct video files (.mp4, .webm, .ogg, .m3u8)

- Generic iframe embeds for other platforms

### Screen Sharing / Live Streaming

Users can create watch parties that stream their own content (mobile games, desktop screen, etc.) using RTMP:

**Setup:**

1. Create a screen share watch party with a custom stream key

2. Use any RTMP streaming app (Larix Broadcaster, Streamlabs, OBS)

3. Configure RTMP settings:

- **Server**: `rtmp://stream.watchparty.nostr/`

- **Stream Key**: Your custom key

4. Start streaming!

**Supported Apps:**

- **Mobile (iOS/Android)**: Larix Broadcaster (Free), Streamlabs Mobile

- **Desktop**: OBS Studio, Streamlabs Desktop, XSplit

**Implementation:**

- RTMP streams are tagged with `t: screenshare`

- Streams are converted to HLS for browser playback

- Live badge animates on screen share watch parties

### Real-time Updates

- Watch party list refreshes every 30 seconds to show new parties and status changes

- Chat messages refresh every 5 seconds to show new messages

- Auto-scroll to bottom when new chat messages arrive

### Synchronized Viewing Mode

Watch parties can be created with synchronized viewing enabled, where all participants watch at the same timestamp in real-time.

**Sync Mode Tags:**

- `t` tag with value "sync" identifies synchronized watch parties

- `playback-start`: Unix timestamp when playback began (used to calculate current position)

**Behavior:**

- **Sync Mode ON**: All viewers see the same moment in the video. New joiners start at the current playback position (like joining a TV broadcast)

- **Sync Mode OFF** (default): Each viewer controls their own playback independently. New joiners start from the beginning

**Example with Sync Mode:**

```json

{

"kind": 30311,

"tags": [

["d", "wp-123"],

["title", "Movie Night"],

["streaming", "https://..."],

["playback-start", "1702234567"],

["t", "sync"]

]

}

```

**Use Cases:**

- **Sync Mode**: Live events, premieres, marathons, communal viewing experiences

- **Independent Mode**: Evergreen content, educational videos, watch-anytime parties

**Technical Implementation:**

- Client calculates elapsed time: `current_time = now - playback_start`

- For direct video: Sets `currentTime` property on video element

- For HLS streams: Appends `#t={elapsed}` to URL

- Updates every second to maintain sync

### Anonymous Viewing

Users can view watch parties and read chat without logging in. Authentication is only required to:

- Create a watch party

- Send chat messages

### NIP-19 Identifiers

Watch parties are identified using `naddr` (addressable event coordinates) which includes:

- Kind: 30311

- Pubkey: Host's public key

- Identifier: The `d` tag value

Format: `/watch/naddr1...`

## Zap Splits (NIP-57)

This application implements automatic zap splits to reward content curators when their movies or series are used in watch parties.

### Split Configuration

When a watch party is created from a library movie or series:

- **Host (Watch Party Creator)**: 70% of zaps

- **Curator (Original Content Poster)**: 30% of zaps

### Implementation

Watch parties created from library content include `zap` tags following NIP-57:

```json

{

"kind": 30311,

"tags": [

["zap", "host-pubkey-hex", "", "70"],

["zap", "curator-pubkey-hex", "", "30"],

["e", "original-post-event-id", "", "mention"]

]

}

```

### User Interface

- **Creation Dialogs**: Show zap split information before creating

- **Watch Party Page**: Display zap split recipients and percentages in sidebar

- **Transparency**: Users can see exactly how their zaps will be distributed

### Benefits

- **Curator Rewards**: Content curators earn passive income when their collections are used

- **Content Discovery**: Incentivizes high-quality content curation

- **Fair Distribution**: Hosts create the experience, curators provide the content

- **Automated**: Splits happen automatically through NIP-57 protocol

## Compliance

This implementation fully complies with:

- **NIP-53**: Live Activities specification

- **NIP-57**: Lightning Zaps with split payments

- **NIP-01**: Basic protocol flow

- **NIP-19**: bech32-encoded entity identifiers

Reply to this note

Please Login to reply.

Discussion

No replies yet.