upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/5E.md
blob: badecae3dd7e84db90b3186f91b3ae40cd4af5b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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)