upleb.uk

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

summaryrefslogtreecommitdiff
path: root/71.md
blob: 2097c7e1241653eb99fd9d67940c38016e363d50 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
NIP-71
======

Video Events
------------

`draft` `optional`

This specification defines _video_ events representing a dedicated post of externally hosted content.

Unlike a `kind:1` event with a video attached, video events are meant to contain all additional metadata concerning the subject media and to be surfaced in video-specific clients rather than general micro-blogging clients. The thought is for events of this kind to be referenced in a Netflix, YouTube, or TikTok like nostr client where the video itself is at the center of the experience.

## Video Events

There are two types of video events represented by different kinds: _normal_ and _short_ video events. This is meant to allow clients to cater to each as the viewing experience for longer, mostly horizontal (landscape) videos is often different than that of short-form, mostly vertical (portrait), videos ("stories", "reels", "shorts" etc).

Nothing except cavaliership and common sense prevents a _short_ video from being long, or a _normal_ video from being vertical, and that may or may not be justified, it's mostly a stylistic qualitative difference, not a question of actual raw size.

#### Format

The format uses a _regular event_ kind `21` for _normal_ videos and `22` for _short_ videos.

## Addressable Video Events

For content that may need updates after publication (such as correcting metadata, descriptions, or handling URL migrations), addressable versions are available:

- Kind `32221` for _addressable normal videos_
- Kind `32222` for _addressable short videos_

These addressable events follow the same format as their regular counterparts but include a `d` tag as a unique identifier and can be updated while maintaining the same addressable reference. This is particularly useful for:

- Metadata corrections (descriptions, titles, tags) without republishing
- Preservation of imported content IDs from legacy platforms
- URL migration when hosting changes
- Platform migration tracking

The `.content` of these events is a summary or description on the video content.

The primary source of video information is the `imeta` tags which is defined in [NIP-92](92.md)

Each `imeta` tag can be used to specify a variant of the video by the `dim` & `m` properties.

Example:
```json
[
  ["imeta",
    "dim 1920x1080",
    "url https://myvideo.com/1080/12345.mp4",
    "x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc",
    "m video/mp4",
    "image https://myvideo.com/1080/12345.jpg",
    "image https://myotherserver.com/1080/12345.jpg",
    "fallback https://myotherserver.com/1080/12345.mp4",
    "fallback https://andanotherserver.com/1080/12345.mp4",
    "service nip96",
  ],
  ["imeta",
    "dim 1280x720",
    "url https://myvideo.com/720/12345.mp4",
    "x e1d4f808dae475ed32fb23ce52ef8ac82e3cc760702fca10d62d382d2da3697d",
    "m video/mp4",
    "image https://myvideo.com/720/12345.jpg",
    "image https://myotherserver.com/720/12345.jpg",
    "fallback https://myotherserver.com/720/12345.mp4",
    "fallback https://andanotherserver.com/720/12345.mp4",
    "service nip96",
  ],
  ["imeta",
    "dim 1280x720",
    "url https://myvideo.com/720/12345.m3u8",
    "x 704e720af2697f5d6a198ad377789d462054b6e8d790f8a3903afbc1e044014f",
    "m application/x-mpegURL",
    "image https://myvideo.com/720/12345.jpg",
    "image https://myotherserver.com/720/12345.jpg",
    "fallback https://myotherserver.com/720/12345.m3u8",
    "fallback https://andanotherserver.com/720/12345.m3u8",
    "service nip96",
  ],
]
```

Where `url` is the primary server url and `fallback` are other servers hosting the same file, both `url` and `fallback` should be weighted equally and clients are recommended to use any of the provided video urls.

The `image` tag contains a preview image (at the same resolution). Multiple `image` tags may be used to specify fallback copies in the same way `fallback` is used for `url`.

Additionally `service nip96` may be included to allow clients to search the authors NIP-96 server list to find the file using the hash.

### Required tags for addressable events:
* `d` - Unique identifier for this video (user-chosen string, required for kinds 32221, 32222)

### Other tags:
* `title` (required) title of the video
* `published_at`, for the timestamp in unix seconds (stringified) of the first time the video was published
* `duration` (optional) video duration in seconds
* `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code
* `content-warning` (optional) warning about content of NSFW video
* `alt` (optional) description for accessibility
* `segment` (optional, repeated) start timestamp in format `HH:MM:SS.sss`, end timestamp in format `HH:MM:SS.sss`, chapter/segment title, chapter thumbnail-url
* `t` (optional, repeated) hashtag to categorize video
* `p` (optional, repeated) 32-bytes hex pubkey of a participant in the video, optional recommended relay URL
* `r` (optional, repeated) references / links to web pages

### Optional tags for imported content:
* `origin` - Track original platform and ID: `["origin", "<platform>", "<external-id>", "<original-url>", "<optional-metadata>"]`

```jsonc
{
  "id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
  "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
  "created_at": <Unix timestamp in seconds>,
  "kind": 21 | 22,
  "content": "<summary / description of video>",
  "tags": [
    ["title", "<title of video>"],
    ["published_at", "<unix timestamp>"],
    ["alt", <description>],

    // video Data
    ["imeta",
      "dim 1920x1080",
      "url https://myvideo.com/1080/12345.mp4",
      "x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc",
      "m video/mp4",
      "image https://myvideo.com/1080/12345.jpg",
      "image https://myotherserver.com/1080/12345.jpg",
      "fallback https://myotherserver.com/1080/12345.mp4",
      "fallback https://andanotherserver.com/1080/12345.mp4",
      "service nip96",
    ],

    ["duration", <duration of video in seconds>],
    ["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"],
    ["content-warning", "<reason>"],
    ["segment", <start>, <end>, "<title>", "<thumbnail URL>"],

    // participants
    ["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>"],
    ["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>"],

    // hashtags
    ["t", "<tag>"],
    ["t", "<tag>"],

    // reference links
    ["r", "<url>"],
    ["r", "<url>"]
  ]
}
```

## Addressable Event Example

```jsonc
{
  "id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
  "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
  "created_at": <Unix timestamp in seconds>,
  "kind": 32221 | 32222,
  "content": "<summary / description of video>",
  "tags": [
    ["d", "<unique-identifier>"],
    ["title", "<title of video>"],
    ["published_at", "<unix timestamp>"],
    ["alt", "<description for accessibility>"],

    // video data
    ["imeta",
      "url https://example.com/media.mp4",
      "m video/mp4",
      "dim 480x480",
      "blurhash eVF$^OI:${M{%LRjWBoLoLaeR*",
      "image https://example.com/thumb.jpg",
      "x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc"
    ],

    ["duration", <duration in seconds>],
    ["content-warning", "<reason>"],

    // origin tracking for imported content
    ["origin", "<platform>", "<external-id>", "<original-url>", "<optional-metadata>"],

    // participants
    ["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>"],

    // hashtags
    ["t", "<tag>"],
    ["t", "<tag>"],

    // reference links
    ["r", "<url>"]
  ]
}
```

## Referencing Addressable Events

To reference an addressable video:

```
["a", "32221:<pubkey>:<d-tag-value>", "<relay-url>"]  // for normal videos
["a", "32222:<pubkey>:<d-tag-value>", "<relay-url>"]  // for short videos
```