{"id":"7bf85ca366cc3d388fcf64813fa3328784dbad7047f2e9b17e7ce4366ed6a97b","pubkey":"2b39b4ffe62933df970e19366c22c1e092f953f83fcfed754e0f04d5a3b459f9","created_at":1781353189,"kind":30817,"tags":[["d","nip-71"],["title","NIP-71: Video Events"],["summary","Video events, long and short, carrying the metadata a video client needs around media hosted elsewhere."],["s","draft"],["t","nostr"],["t","nip"],["k","21","Video Event"],["k","22","Short-form Portrait Video Event"],["k","34235","Addressable Video Event"],["k","34236","Addressable Short Video Event"],["alt","A specification: NIP-71: Video Events"],["client","openspecs-import"],["published_at","1701997748"],["proxy","https://github.com/nostr-protocol/nips/blob/656cecc7c0a815b6a2b218d3b5d6f078b3f4dbab/71.md","web"],["x","59c43d025904054490c2e6a4e447c3c6ad6585f7ae7d0163fbfd9531ae35e50f"]],"content":"NIP-71\n======\n\nVideo Events\n------------\n\n`draft` `optional`\n\nThis specification defines _video_ events representing a dedicated post of externally hosted content.\n\nUnlike 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.\n\n## Video Events\n\nThere 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).\n\nNothing 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.\n\n#### Format\n\nThe format uses a _regular event_ kind `21` for _normal_ videos and `22` for _short_ videos.\n\n## Addressable Video Events\n\nFor content that may need updates after publication (such as correcting metadata, descriptions, or handling URL migrations), addressable versions are available:\n\n- Kind `34235` for _addressable normal videos_\n- Kind `34236` for _addressable short videos_\n\nThese 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:\n\n- Metadata corrections (descriptions, titles, tags) without republishing\n- Preservation of imported content IDs from legacy platforms\n- URL migration when hosting changes\n- Platform migration tracking\n\nThe `.content` of these events is a summary or description on the video content.\n\nThe primary source of video information is the `imeta` tags which is defined in [NIP-92](nostr:naddr1qvzqqqrcvypzq2eeknl7v2fnm7tsuxfkds3vrcyjl9fls070a465urcy6k3mgk0eqqrxu6ts95unyxv6xmu)\n\nEach `imeta` tag can be used to specify a variant of the video by the `dim` & `m` properties, as well as multiple audio tracks (languages).\n\nClients should check if audio tracks are available and prefer them over in-video audio \nto allow smooth resolution switching without interrupting audio. The `ov` (original version) flags the original language track.\n\nThis NIP defines the following additional `imeta` properties aside from those listed in [NIP-92](nostr:naddr1qvzqqqrcvypzq2eeknl7v2fnm7tsuxfkds3vrcyjl9fls070a465urcy6k3mgk0eqqrxu6ts95unyxv6xmu) & [NIP-94](nostr:naddr1qvzqqqrcvypzq2eeknl7v2fnm7tsuxfkds3vrcyjl9fls070a465urcy6k3mgk0eqqrxu6ts95unghjuv2m):\n\n* `duration` (recommended) the duration of the video/audio in seconds (floating point number)\n* `bitrate` (recommended) the average bitrate of the video/audio in bits/sec\n* `waveform` (optional, audio only) amplitude values over time, space separated full integers, less than 100 values should be enough to render a nice visual\n\nExample:\n```json\n[\n  [\"imeta\",\n    \"dim 1920x1080\",\n    \"url https://myvideo.com/1080/12345.mp4\",\n    \"x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc\",\n    \"m video/mp4\",\n    \"image https://myvideo.com/1080/12345.jpg\",\n    \"image https://myotherserver.com/1080/12345.jpg\",\n    \"fallback https://myotherserver.com/1080/12345.mp4\",\n    \"fallback https://andanotherserver.com/1080/12345.mp4\",\n    \"service nip96\",\n    \"bitrate 3000000\",\n    \"duration 29.223\"\n  ],\n  [\"imeta\",\n    \"dim 1280x720\",\n    \"url https://myvideo.com/720/12345.mp4\",\n    \"x e1d4f808dae475ed32fb23ce52ef8ac82e3cc760702fca10d62d382d2da3697d\",\n    \"m video/mp4\",\n    \"image https://myvideo.com/720/12345.jpg\",\n    \"image https://myotherserver.com/720/12345.jpg\",\n    \"fallback https://myotherserver.com/720/12345.mp4\",\n    \"fallback https://andanotherserver.com/720/12345.mp4\",\n    \"service nip96\",\n    \"bitrate 2000000\",\n    \"duration 29.24\"\n  ],\n  [\"imeta\",\n    \"dim 1280x720\",\n    \"url https://myvideo.com/720/12345.m3u8\",\n    \"x 704e720af2697f5d6a198ad377789d462054b6e8d790f8a3903afbc1e044014f\",\n    \"m application/x-mpegURL\",\n    \"image https://myvideo.com/720/12345.jpg\",\n    \"image https://myotherserver.com/720/12345.jpg\",\n    \"fallback https://myotherserver.com/720/12345.m3u8\",\n    \"fallback https://andanotherserver.com/720/12345.m3u8\",\n    \"service nip96\",\n    \"duration 29.21\"\n  ],\n  [\"imeta\",\n    \"url https://myaudio.com/audio/en/12345.mp3\",\n    \"x b2e0a7a82ac9f3f3a71f1d9a78c381d5be9d1cf19dce258765c17c8a76287c93\",\n    \"m audio/mp3\",\n    \"waveform 0 7 35 8 100 100 49 8 4 16 8 10 7 2 20 10 100 100 100 100 100 100 15 100 100 100 25 60 5 4 3 1 0 100 100 15 100 29 88 0 33 11 39 100 100 19 4 100 42 35 5 0 1 5 0 0 11 38 100 94 17 11 44 58 5 100 100 100 55 14 72 100 100 57 6 1 14 2 16 100 100 40 16 100 100 6 32 14 13 41 36 16 14 6 3 0 1 2 1 6 0\",\n    \"l en ISO-639-1 ov\",\n    \"fallback https://myotherserver.com/audio/en/12345.mp3\",\n    \"fallback https://andanotherserver.com/audio/en/12345.mp3\",\n    \"service nip96\",\n    \"bitrate  320000\",\n    \"duration 29.24\"\n  ],\n]\n```\n\nWhere `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.\n\nThe `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`.\n\nAdditionally `service nip96` may be included to allow clients to search the authors NIP-96 server list to find the file using the hash.\n\n### Required tags for addressable events:\n* `d` - Unique identifier for this video (user-chosen string, required for kinds 34235, 34236)\n\n### Other tags:\n* `title` (required) title of the video\n* `published_at`, for the timestamp in unix seconds (stringified) of the first time the video was published\n* `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code\n* `content-warning` (optional) warning about content of NSFW video\n* `alt` (optional) description for accessibility\n* `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\n* `t` (optional, repeated) hashtag to categorize video\n* `p` (optional, repeated) 32-bytes hex pubkey of a participant in the video, optional recommended relay URL\n* `r` (optional, repeated) references / links to web pages\n\n### Optional tags for imported content:\n* `origin` - Track original platform and ID: `[\"origin\", \"<platform>\", \"<external-id>\", \"<original-url>\", \"<optional-metadata>\"]`\n\n```yaml\n{\n  \"id\": \"<32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>\",\n  \"pubkey\": \"<32-bytes lowercase hex-encoded public key of the event creator>\",\n  \"created_at\": <Unix timestamp in seconds>,\n  \"kind\": 21 | 22,\n  \"content\": \"<summary / description of video>\",\n  \"tags\": [\n    [\"title\", \"<title of video>\"],\n    [\"published_at\", \"<unix timestamp>\"],\n    [\"alt\", \"<description>\"],\n\n    // video Data\n    [\"imeta\",\n      \"dim 1920x1080\",\n      \"url https://myvideo.com/1080/12345.mp4\",\n      \"x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc\",\n      \"m video/mp4\",\n      \"image https://myvideo.com/1080/12345.jpg\",\n      \"image https://myotherserver.com/1080/12345.jpg\",\n      \"fallback https://myotherserver.com/1080/12345.mp4\",\n      \"fallback https://andanotherserver.com/1080/12345.mp4\",\n      \"service nip96\",\n    ],\n\n    [\"text-track\", \"<encoded `kind 6000` event>\", \"<recommended relay urls>\"],\n    [\"content-warning\", \"<reason>\"],\n    [\"segment\", <start>, <end>, \"<title>\", \"<thumbnail URL>\"],\n\n    // participants\n    [\"p\", \"<32-bytes hex of a pubkey>\", \"<optional recommended relay URL>\"],\n    [\"p\", \"<32-bytes hex of a pubkey>\", \"<optional recommended relay URL>\"],\n\n    // hashtags\n    [\"t\", \"<tag>\"],\n    [\"t\", \"<tag>\"],\n\n    // reference links\n    [\"r\", \"<url>\"],\n    [\"r\", \"<url>\"]\n  ]\n}\n```\n\n## Addressable Event Example\n\n```yaml\n{\n  \"id\": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,\n  \"pubkey\": <32-bytes lowercase hex-encoded public key of the event creator>,\n  \"created_at\": <Unix timestamp in seconds>,\n  \"kind\": 34235 | 34236,\n  \"content\": \"<summary / description of video>\",\n  \"tags\": [\n    [\"d\", \"<unique-identifier>\"],\n    [\"title\", \"<title of video>\"],\n    [\"published_at\", \"<unix timestamp>\"],\n    [\"alt\", \"<description for accessibility>\"],\n\n    // video data\n    [\"imeta\",\n      \"url https://example.com/media.mp4\",\n      \"m video/mp4\",\n      \"dim 480x480\",\n      \"blurhash eVF$^OI:${M{%LRjWBoLoLaeR*\",\n      \"image https://example.com/thumb.jpg\",\n      \"x 3093509d1e0bc604ff60cb9286f4cd7c781553bc8991937befaacfdc28ec5cdc\"\n    ],\n    // audio data\n    [\"imeta\",\n      \"url https://example.com/audio.mp3\",\n      \"x b2e0a7a82ac9f3f3a71f1d9a78c381d5be9d1cf19dce258765c17c8a76287c93\",\n      \"m audio/mp3\",\n      \"l en ISO-639-1 ov\"\n    ],\n\n    [\"duration\", <duration in seconds>],\n    [\"content-warning\", \"<reason>\"],\n\n    // origin tracking for imported content\n    [\"origin\", \"<platform>\", \"<external-id>\", \"<original-url>\", \"<optional-metadata>\"],\n\n    // participants\n    [\"p\", \"<32-bytes hex of a pubkey>\", \"<optional recommended relay URL>\"],\n\n    // hashtags\n    [\"t\", \"<tag>\"],\n    [\"t\", \"<tag>\"],\n\n    // reference links\n    [\"r\", \"<url>\"]\n  ]\n}\n```\n\n## Referencing Addressable Events\n\nTo reference an addressable video:\n\n```\n[\"a\", \"34235:<pubkey>:<d-tag-value>\", \"<relay-url>\"]  // for normal videos\n[\"a\", \"34236:<pubkey>:<d-tag-value>\", \"<relay-url>\"]  // for short videos\n```\n","sig":"f8f6838aeb93b4f31307c055807239fdf24cbd90ebf071b341ffea32c59a810e4de555d0e0c4320e35c368711f5824faa9b18ce2f6299c692db07c1bc959e597"}