From cbae73be9c2895daf62ad48f00b40a5c93ea80b2 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Thu, 17 Jul 2025 18:19:34 +0200 Subject: [PATCH 1/9] nostr internet radio --- XX.md | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 XX.md diff --git a/XX.md b/XX.md new file mode 100644 index 00000000..e249b63e --- /dev/null +++ b/XX.md @@ -0,0 +1,197 @@ +# NIP-XX + +## Internet Radio + +`draft` `optional` + +This NIP defines a standard for publishing and discovering internet radio stations on Nostr, enabling decentralized radio station directories, streaming metadata, social features, and interoperability between radio applications. + +## Rationale + +Traditional internet radio directories are centralized services controlled by single entities, making them vulnerable to censorship, takedowns, and service discontinuation. Radio stations and listeners lack data portability between different platforms and applications. + +This specification leverages Nostr's decentralized infrastructure to create an open, censorship-resistant radio ecosystem where: + +- Radio stations can publish their metadata and streaming information directly +- Users maintain portable favorites lists across applications +- Developers can build interoperable radio clients without vendor lock-in +- Communities can engage around stations through comments and live chat +- Discovery happens through the network rather than centralized algorithms +- Organic, decentralized maintenance of station entries helps keep quality high and mitigate broken links +- Direct listener-to-station monetization becomes possible through Nostr's native micropayment capabilities + +## Overview + +This specification defines radio station events and describes how existing Nostr protocols can be used to create a complete radio ecosystem: + +- **Radio Station Events** (`kind:31237`) - Station metadata and streaming information (defined in this NIP) +- **Live Chat Messages** - Real-time chat during streaming using existing live chat protocols +- **Station Comments** - Persistent discussion threads using existing comment protocols +- **Favorites Management** - Personal and curated station collections using [NIP-78](78.md) +- **Application Discovery** - Handler registration using [NIP-89](89.md) + +## Radio Station Events + +Radio stations are published as addressable events of `kind:31237`. These events contain streaming URLs, metadata, and technical specifications needed for playback. + +### Event Structure + +```json +{ + "kind": 31237, + "content": "", + "tags": [ + ["d", ""], + ["name", ""], + ["t", ""], + ["language", ""], + ["countryCode", ""], + ["location", ""], + ["thumbnail", ""], + ["website", ""], + ["client", "", "", ""] + ] +} +``` + +### Content Format + +The `content` field MUST contain a JSON string with the following structure: + +```json +{ + "description": "Station description with **markdown** support", + "streams": [ + { + "url": "https://stream.example.com/radio.mp3", + "format": "audio/mpeg", + "quality": { + "bitrate": 128000, + "codec": "mp3", + "sampleRate": 44100 + }, + "primary": true + } + ], + "streamingServerUrl": "https://server.example.com" +} +``` + +#### Required Fields + +- `description`: Human-readable description (markdown supported) +- `streams`: Array of stream objects (minimum one required) + +#### Optional Fields + +- `streamingServerUrl`: Base URL of the streaming server (needed for metadata endpoints when using typical streaming servers like Icecast that provide `/status-json.xsl`, `/admin/stats`, or similar metadata APIs) + +#### Stream Object + +Each stream object MUST include: + +- `url`: Direct URL to the audio stream +- `format`: MIME type (e.g., "audio/mpeg", "audio/aac") +- `quality`: Object with `bitrate`, `codec`, and `sampleRate` +- `primary`: Boolean indicating the default stream (optional) + +### Required Tags + +- `d`: Unique identifier for the station (used for addressability) +- `name`: Human-readable station name + +### Recommended Tags + +- `t`: Genre/category tags (multiple allowed) +- `language`: ISO 639-1 language codes (multiple allowed) +- `countryCode`: ISO 3166-2 country code +- `location`: Human-readable location string +- `thumbnail`: Station logo/image URL +- `website`: Station's official website +- `client`: Client that published the event (format: `["client", "ClientName", "HandlerId", "RelayURL"]`) + +### Example + +```json +{ + "kind": 31237, + "pubkey": "a1b2c3d4...", + "created_at": 1690000000, + "content": "{\"description\":\"Eclectic mix of jazz, world music, and electronic sounds from France.\",\"streams\":[{\"url\":\"https://icecast.radiofrance.fr/fiprock-hifi.aac\",\"format\":\"audio/aac\",\"quality\":{\"bitrate\":128000,\"codec\":\"aac\",\"sampleRate\":44100},\"primary\":true}]}", + "tags": [ + ["d", "fip-radio-paris"], + ["name", "FIP Radio"], + ["t", "jazz"], + ["t", "world"], + ["t", "electronic"], + ["language", "fr"], + ["countryCode", "FR"], + ["location", "Paris, France"], + ["thumbnail", "https://example.com/fip-logo.png"], + ["website", "https://www.radiofrance.fr/fip"], + [ + "client", + "NostrRadio", + "31990:pubkey:handler123", + "wss://relay.example.com" + ] + ] +} +``` + +## Social Features + +Radio stations can leverage existing Nostr social protocols: + +### Live Chat Messages + +Real-time chat during radio streaming uses existing live chat protocols such as [NIP-53](53.md). Messages should reference the radio station via `a` tag to associate chat with the specific station. + +### Station Comments + +Persistent discussion threads use existing comment protocols such as [NIP-25](25.md). Comments should reference the radio station event to create threaded discussions about stations. + +## Implementation Notes + +### Station Identification + +- The `d` tag value SHOULD be descriptive and stable for the station +- Multiple stations can be published by the same pubkey using different `d` tags +- Clients SHOULD use the station name as a fallback identifier + +### Streaming Compatibility + +- Support multiple stream formats for broader client compatibility +- Include quality metadata to enable adaptive streaming +- Mark one stream as `primary` for default selection + +### Content Indexing + +- Use `t` tags for genre/category filtering +- Include `language` tags for internationalization +- Add `location` for geographical discovery + +### Privacy Considerations + +- The `client` tag has privacy implications - clients SHOULD allow opt-out +- Station owners can moderate chat/comments by maintaining block lists +- Consider rate limiting for chat messages to prevent spam + +## Security Considerations + +- Validate stream URLs before playback to prevent malicious redirects +- Sanitize station descriptions when rendering markdown content +- Implement reasonable limits on metadata size to prevent DoS attacks +- Verify signatures on all events before processing + +## Backwards Compatibility + +This specification introduces new event kinds that do not conflict with existing NIPs. Clients that don't understand `kind:31237` can safely ignore these events without affecting other functionality. + +## Reference Implementation + +A reference implementation is available at [WaveFunc](https://github.com/zeSchlausKwab/wavefunc), demonstrating station publishing, favorites management, and social features. + +## Conclusion + +This specification enables a decentralized internet radio ecosystem built on Nostr's foundation of censorship resistance and data portability. By standardizing station metadata, social features, and application discovery, it creates interoperability between radio clients while preserving user autonomy and freedom of choice. From e1a3228486ae139d275cd06fe9ad787232addad6 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:18:15 +0200 Subject: [PATCH 2/9] Remove 'client' tag from stream object requirements in XX.md for clarity and privacy considerations. --- XX.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/XX.md b/XX.md index e249b63e..e80f78f4 100644 --- a/XX.md +++ b/XX.md @@ -48,8 +48,7 @@ Radio stations are published as addressable events of `kind:31237`. These events ["countryCode", ""], ["location", ""], ["thumbnail", ""], - ["website", ""], - ["client", "", "", ""] + ["website", ""] ] } ``` @@ -108,7 +107,6 @@ Each stream object MUST include: - `location`: Human-readable location string - `thumbnail`: Station logo/image URL - `website`: Station's official website -- `client`: Client that published the event (format: `["client", "ClientName", "HandlerId", "RelayURL"]`) ### Example @@ -128,13 +126,7 @@ Each stream object MUST include: ["countryCode", "FR"], ["location", "Paris, France"], ["thumbnail", "https://example.com/fip-logo.png"], - ["website", "https://www.radiofrance.fr/fip"], - [ - "client", - "NostrRadio", - "31990:pubkey:handler123", - "wss://relay.example.com" - ] + ["website", "https://www.radiofrance.fr/fip"] ] } ``` @@ -173,7 +165,6 @@ Persistent discussion threads use existing comment protocols such as [NIP-25](25 ### Privacy Considerations -- The `client` tag has privacy implications - clients SHOULD allow opt-out - Station owners can moderate chat/comments by maintaining block lists - Consider rate limiting for chat messages to prevent spam From 371fffeea43eb90384c389fa44340b70b6774008 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:19:48 +0200 Subject: [PATCH 3/9] Remove privacy, security, backwards compatibility sections, and conclusion from XX.md to streamline content and focus on essential specifications. --- XX.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/XX.md b/XX.md index e80f78f4..3c026c87 100644 --- a/XX.md +++ b/XX.md @@ -163,26 +163,6 @@ Persistent discussion threads use existing comment protocols such as [NIP-25](25 - Include `language` tags for internationalization - Add `location` for geographical discovery -### Privacy Considerations - -- Station owners can moderate chat/comments by maintaining block lists -- Consider rate limiting for chat messages to prevent spam - -## Security Considerations - -- Validate stream URLs before playback to prevent malicious redirects -- Sanitize station descriptions when rendering markdown content -- Implement reasonable limits on metadata size to prevent DoS attacks -- Verify signatures on all events before processing - -## Backwards Compatibility - -This specification introduces new event kinds that do not conflict with existing NIPs. Clients that don't understand `kind:31237` can safely ignore these events without affecting other functionality. - ## Reference Implementation A reference implementation is available at [WaveFunc](https://github.com/zeSchlausKwab/wavefunc), demonstrating station publishing, favorites management, and social features. - -## Conclusion - -This specification enables a decentralized internet radio ecosystem built on Nostr's foundation of censorship resistance and data portability. By standardizing station metadata, social features, and application discovery, it creates interoperability between radio clients while preserving user autonomy and freedom of choice. From 15f81522a9fe836c68e1f666cece88bf7a492c36 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:24:40 +0200 Subject: [PATCH 4/9] Update 'd' tag requirements in XX.md for improved stability and clarity; change example value to a random identifier and clarify default behavior. --- XX.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/XX.md b/XX.md index 3c026c87..e5513464 100644 --- a/XX.md +++ b/XX.md @@ -117,7 +117,7 @@ Each stream object MUST include: "created_at": 1690000000, "content": "{\"description\":\"Eclectic mix of jazz, world music, and electronic sounds from France.\",\"streams\":[{\"url\":\"https://icecast.radiofrance.fr/fiprock-hifi.aac\",\"format\":\"audio/aac\",\"quality\":{\"bitrate\":128000,\"codec\":\"aac\",\"sampleRate\":44100},\"primary\":true}]}", "tags": [ - ["d", "fip-radio-paris"], + ["d", "a7f9d2e1b8c3"], ["name", "FIP Radio"], ["t", "jazz"], ["t", "world"], @@ -147,9 +147,9 @@ Persistent discussion threads use existing comment protocols such as [NIP-25](25 ### Station Identification -- The `d` tag value SHOULD be descriptive and stable for the station +- The `d` tag value SHOULD be a random identifier to ensure stability over time +- If no `d` tag is present, it defaults to an empty string - Multiple stations can be published by the same pubkey using different `d` tags -- Clients SHOULD use the station name as a fallback identifier ### Streaming Compatibility From 9dbc3e6cbec89c55058fa56a028ce2839b63703c Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:26:10 +0200 Subject: [PATCH 5/9] Update reference from NIP-25 to NIP-22 in XX.md for accurate comment protocol documentation. --- XX.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XX.md b/XX.md index e5513464..69d6abfa 100644 --- a/XX.md +++ b/XX.md @@ -141,7 +141,7 @@ Real-time chat during radio streaming uses existing live chat protocols such as ### Station Comments -Persistent discussion threads use existing comment protocols such as [NIP-25](25.md). Comments should reference the radio station event to create threaded discussions about stations. +Persistent discussion threads use existing comment protocols such as [NIP-22](22.md). Comments should reference the radio station event to create threaded discussions about stations. ## Implementation Notes From b4e7f21446c102b15924e1d0ac1c87dca39efed6 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:28:50 +0200 Subject: [PATCH 6/9] Update language tag in XX.md from 'language' to 'l' for consistency and clarity in stream object specifications. --- XX.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XX.md b/XX.md index 69d6abfa..b2c7124a 100644 --- a/XX.md +++ b/XX.md @@ -44,7 +44,7 @@ Radio stations are published as addressable events of `kind:31237`. These events ["d", ""], ["name", ""], ["t", ""], - ["language", ""], + ["l", ""], ["countryCode", ""], ["location", ""], ["thumbnail", ""], @@ -102,7 +102,7 @@ Each stream object MUST include: ### Recommended Tags - `t`: Genre/category tags (multiple allowed) -- `language`: ISO 639-1 language codes (multiple allowed) +- `l`: ISO 639-1 language codes (multiple allowed) - `countryCode`: ISO 3166-2 country code - `location`: Human-readable location string - `thumbnail`: Station logo/image URL @@ -122,7 +122,7 @@ Each stream object MUST include: ["t", "jazz"], ["t", "world"], ["t", "electronic"], - ["language", "fr"], + ["l", "fr"], ["countryCode", "FR"], ["location", "Paris, France"], ["thumbnail", "https://example.com/fip-logo.png"], @@ -160,7 +160,7 @@ Persistent discussion threads use existing comment protocols such as [NIP-22](22 ### Content Indexing - Use `t` tags for genre/category filtering -- Include `language` tags for internationalization +- Include `l` tags for internationalization - Add `location` for geographical discovery ## Reference Implementation From 5a94e5ea4569abeb76be87514bf1dbe563f0c862 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:34:50 +0200 Subject: [PATCH 7/9] Remove rationale and overview sections from XX.md to streamline the document and focus on the core specifications of the radio station events. --- XX.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/XX.md b/XX.md index b2c7124a..3c064add 100644 --- a/XX.md +++ b/XX.md @@ -6,30 +6,6 @@ This NIP defines a standard for publishing and discovering internet radio stations on Nostr, enabling decentralized radio station directories, streaming metadata, social features, and interoperability between radio applications. -## Rationale - -Traditional internet radio directories are centralized services controlled by single entities, making them vulnerable to censorship, takedowns, and service discontinuation. Radio stations and listeners lack data portability between different platforms and applications. - -This specification leverages Nostr's decentralized infrastructure to create an open, censorship-resistant radio ecosystem where: - -- Radio stations can publish their metadata and streaming information directly -- Users maintain portable favorites lists across applications -- Developers can build interoperable radio clients without vendor lock-in -- Communities can engage around stations through comments and live chat -- Discovery happens through the network rather than centralized algorithms -- Organic, decentralized maintenance of station entries helps keep quality high and mitigate broken links -- Direct listener-to-station monetization becomes possible through Nostr's native micropayment capabilities - -## Overview - -This specification defines radio station events and describes how existing Nostr protocols can be used to create a complete radio ecosystem: - -- **Radio Station Events** (`kind:31237`) - Station metadata and streaming information (defined in this NIP) -- **Live Chat Messages** - Real-time chat during streaming using existing live chat protocols -- **Station Comments** - Persistent discussion threads using existing comment protocols -- **Favorites Management** - Personal and curated station collections using [NIP-78](78.md) -- **Application Discovery** - Handler registration using [NIP-89](89.md) - ## Radio Station Events Radio stations are published as addressable events of `kind:31237`. These events contain streaming URLs, metadata, and technical specifications needed for playback. From 3ec79b5baf49806d6418b6ffaa43e5ad68fe546d Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:36:58 +0200 Subject: [PATCH 8/9] Remove 'location' tag from XX.md to simplify geographical discovery requirements and enhance document clarity. --- XX.md | 1 - 1 file changed, 1 deletion(-) diff --git a/XX.md b/XX.md index 3c064add..ea5240cb 100644 --- a/XX.md +++ b/XX.md @@ -137,7 +137,6 @@ Persistent discussion threads use existing comment protocols such as [NIP-22](22 - Use `t` tags for genre/category filtering - Include `l` tags for internationalization -- Add `location` for geographical discovery ## Reference Implementation From f5ce18a6862dc66121d756d58e1da2fb6b9832f0 Mon Sep 17 00:00:00 2001 From: zeSchlausKwab Date: Fri, 18 Jul 2025 14:38:44 +0200 Subject: [PATCH 9/9] Add 'g' tag for geohash in XX.md to enhance geographical precision in stream object specifications and discovery requirements. --- XX.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/XX.md b/XX.md index ea5240cb..f111d74c 100644 --- a/XX.md +++ b/XX.md @@ -23,6 +23,7 @@ Radio stations are published as addressable events of `kind:31237`. These events ["l", ""], ["countryCode", ""], ["location", ""], + ["g", ""], ["thumbnail", ""], ["website", ""] ] @@ -81,6 +82,7 @@ Each stream object MUST include: - `l`: ISO 639-1 language codes (multiple allowed) - `countryCode`: ISO 3166-2 country code - `location`: Human-readable location string +- `g`: Geohash for precise geographical coordinates - `thumbnail`: Station logo/image URL - `website`: Station's official website @@ -101,6 +103,7 @@ Each stream object MUST include: ["l", "fr"], ["countryCode", "FR"], ["location", "Paris, France"], + ["g", "u09tvw0"], ["thumbnail", "https://example.com/fip-logo.png"], ["website", "https://www.radiofrance.fr/fip"] ] @@ -137,6 +140,7 @@ Persistent discussion threads use existing comment protocols such as [NIP-22](22 - Use `t` tags for genre/category filtering - Include `l` tags for internationalization +- Add `g` tags with geohash for precise geographical discovery ## Reference Implementation