Compare commits
13 Commits
37ddc594ed
...
07aa0db973
Author | SHA1 | Date |
---|---|---|
|
07aa0db973 | |
|
7dec812f99 | |
|
739f3c5263 | |
|
8830525250 | |
|
f5ce18a686 | |
|
3ec79b5baf | |
|
5a94e5ea45 | |
|
b4e7f21446 | |
|
9dbc3e6cbe | |
|
15f81522a9 | |
|
371fffeea4 | |
|
e1a3228486 | |
|
cbae73be9c |
2
21.md
2
21.md
|
@ -21,7 +21,7 @@ The identifiers that come after are expected to be the same as those defined in
|
|||
|
||||
### Linking HTML pages to Nostr entities
|
||||
|
||||
`<link>` tags with `rel="alternate"` can be used to associate webpages to Nostr events, in cases where the same content is served via the two mediums (for example, a web server that exposes Markdown articles both as HTML pages and as `kind:30023' events served under itself as a relay or through some other relay). For example:
|
||||
`<link>` tags with `rel="alternate"` can be used to associate webpages to Nostr events, in cases where the same content is served via the two mediums (for example, a web server that exposes Markdown articles both as HTML pages and as `kind:30023` events served under itself as a relay or through some other relay). For example:
|
||||
|
||||
```
|
||||
<head>
|
||||
|
|
8
22.md
8
22.md
|
@ -143,13 +143,13 @@ A comment on a website's url looks like this:
|
|||
"tags": [
|
||||
// referencing the root url
|
||||
["I", "https://abc.com/articles/1"],
|
||||
// the root "kind": for an url, the kind is its domain
|
||||
["K", "https://abc.com"],
|
||||
// the root "kind": for an url
|
||||
["K", "web"],
|
||||
|
||||
// the parent reference (same as root for top-level comments)
|
||||
["i", "https://abc.com/articles/1"],
|
||||
// the parent "kind": for an url, the kind is its domain
|
||||
["k", "https://abc.com"]
|
||||
// the parent "kind": for an url
|
||||
["k", "web"]
|
||||
]
|
||||
// other fields
|
||||
}
|
||||
|
|
13
24.md
13
24.md
|
@ -8,8 +8,7 @@ Extra metadata fields and tags
|
|||
|
||||
This NIP keeps track of extra optional fields that can added to events which are not defined anywhere else but have become _de facto_ standards and other minor implementation possibilities that do not deserve their own NIP and do not have a place in other NIPs.
|
||||
|
||||
kind 0
|
||||
======
|
||||
### kind 0
|
||||
|
||||
These are extra fields not specified in NIP-01 that may be present in the stringified JSON of metadata events:
|
||||
|
||||
|
@ -19,24 +18,22 @@ These are extra fields not specified in NIP-01 that may be present in the string
|
|||
- `bot`: a boolean to clarify that the content is entirely or partially the result of automation, such as with chatbots or newsfeeds.
|
||||
- `birthday`: an object representing the author's birth date. The format is { "year": number, "month": number, "day": number }. Each field MAY be omitted.
|
||||
|
||||
### Deprecated fields
|
||||
#### Deprecated fields
|
||||
|
||||
These are fields that should be ignored or removed when found in the wild:
|
||||
|
||||
- `displayName`: use `display_name` instead.
|
||||
- `username`: use `name` instead.
|
||||
|
||||
kind 3
|
||||
======
|
||||
### kind 3
|
||||
|
||||
These are extra fields not specified in NIP-02 that may be present in the stringified JSON of follow events:
|
||||
|
||||
### Deprecated fields
|
||||
#### Deprecated fields
|
||||
|
||||
- `{<relay-url>: {"read": <true|false>, "write": <true|false>}, ...}`: an object of relays used by a user to read/write. [NIP-65](65.md) should be used instead.
|
||||
|
||||
tags
|
||||
====
|
||||
### tags
|
||||
|
||||
These tags may be present in multiple event kinds. Whenever a different meaning is not specified by some more specific NIP, they have the following meanings:
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
# 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.
|
||||
|
||||
## 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": "<JSON metadata>",
|
||||
"tags": [
|
||||
["d", "<station-identifier>"],
|
||||
["name", "<station-name>"],
|
||||
["t", "<genre>"],
|
||||
["l", "<ISO-639-1-code>"],
|
||||
["countryCode", "<ISO-3166-2-code>"],
|
||||
["location", "<human-readable-location>"],
|
||||
["g", "<geohash>"],
|
||||
["thumbnail", "<image-url>"],
|
||||
["website", "<station-website>"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 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)
|
||||
- `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
|
||||
|
||||
### 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", "a7f9d2e1b8c3"],
|
||||
["name", "FIP Radio"],
|
||||
["t", "jazz"],
|
||||
["t", "world"],
|
||||
["t", "electronic"],
|
||||
["l", "fr"],
|
||||
["countryCode", "FR"],
|
||||
["location", "Paris, France"],
|
||||
["g", "u09tvw0"],
|
||||
["thumbnail", "https://example.com/fip-logo.png"],
|
||||
["website", "https://www.radiofrance.fr/fip"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 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-22](22.md). Comments should reference the radio station event to create threaded discussions about stations.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Station Identification
|
||||
|
||||
- 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
|
||||
|
||||
### 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 `l` tags for internationalization
|
||||
- Add `g` tags with geohash for precise geographical discovery
|
||||
|
||||
## Reference Implementation
|
||||
|
||||
A reference implementation is available at [WaveFunc](https://github.com/zeSchlausKwab/wavefunc), demonstrating station publishing, favorites management, and social features.
|
Loading…
Reference in New Issue