Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIP-5E: Censorship Resistant Live Streams #1790

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions 5E.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# NIP-5E

## Censorship Resistant Live Streams

`draft` `optional`

Describes a way to distribute live video streams via nostr.

**"Live Video" in this context implies segmented video streams like HLS or DASH**

## N94 Stream

A new `kind: 1053` event lists a single live stream.

Example:

```jsonc
{
"kind": 1053,
"tags": [
["title", "<name of the event>"],
["summary", "<description>"],
["image", "<preview image url>"],
[
"variant",
"dim 1920x1080",
"bitrate 5000000",
"m video/mp2t",
"d 1080p"
],
[
"variant",
"dim 1280x720",
"bitrate 3000000",
"m video/mp2t",
"d 720p"
],
[
"variant",
"dim 1920x1080",
"bitrate 6000000",
"m video/mp4",
"d 1080p-fmp4"
],
["t", "hashtag"]
["starts", "<unix timestamp in seconds>"],
["ends", "<unix timestamp in seconds>"],
["relays", "wss://one.com", "wss://two.com", /*...*/],
["pinned", "<event id of pinned live chat message>"],
],
"content": "",
// other fields...
}
```

The `variant` tag works like `imeta` tag from [NIP-92](92.md) and defines a variant stream.

The `d` entry of the `variant` tag is used in the NIP-94 segment event for variant following.

## N94 Segment

Each segment of the stream is a [NIP-94](94.md) event which describes where the file can be found and its hash.

```jsonc
{
"kind": 1063,
"tags": [
["d", "1080p"]
["e", "<id-of-kind-1053>"],
["x", "<sha256>"],
["m", "video/mp2t"],
["dim", "1920x1080"],
["duration", "2.033"],
["index", "1234"],
["url", "https://example.com/1234.ts"],
["fallback", "https://another.com/1234.ts"],
["service", "blossom"],
...
]
// other fields...
}
```

Aside from the standard NIP-94 tags:

- `d`: Variant stream tag.
- `index`: Segment index, a simple counter. Used of ordering.

`service` tag should be used for extended censorship resitance by looking up the appropriate server list (Blossom) of the uploader and checking for files on alternate servers.

## Implementors

### Consumers

Clients wishing to implement a player should use [MSE](https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API) or similar technologies which allow appending data to the player buffer.

Other services MAY provide a compatability layer with [NIP-53](53.md) live streams by producing HLS playlists over a N94 Stream.

Clients SHOULD follow only a single variant by using a filter like this:

`{"kinds":[1063],"#e":["<id-of-kind-5053>"],"#d":["1080p"],"limit":10}`

Leaving the subscription open will allow clients to be notified immediately as segments are published and can fetch those segments and append them to the player buffer.

### Producers

Segment length SHOULD be carefully considered as a trade off between stream delay and total number of NIP-94 events / segment files.

Using `expiration` tags on N94 segments and deleting segment files from servers SHOULD be used to cleanup streams which don't want to persist after the stream is finished.

## Example implementations:

### Player

[zap.stream](https://github.com/v0l/zap.stream/blob/main/src/element/stream/n94-player.tsx)

### Producer

[zap-stream-core](https://github.com/v0l/zap-stream-core/blob/ccb2add6073e5bb68191c42613c34f66583e34fc/crates/zap-stream/src/overseer.rs#L340-L380)