# space.remanso.recording

> Published by [apoena.dev](https://lexicon.garden/identity/did:plc:4m3kouplb7s7xozjd3whinvl)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:4m3kouplb7s7xozjd3whinvl/space.remanso.recording)
- [Documentation](https://lexicon.garden/lexicon/did:plc:4m3kouplb7s7xozjd3whinvl/space.remanso.recording/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:4m3kouplb7s7xozjd3whinvl/space.remanso.recording/examples)

## Definitions

### `space.remanso.recording`

**Type**: `record`

An audio recording — a past stream, a podcast episode, a voice note. A recording at rkey R is the recording of the space.remanso.note at rkey R in the same repo: one note, at most one recording, paired by convention rather than by a field, so a reader that knows the note's did and rkey reaches the audio with a single getRecord. A recording whose rkey matches no note stands alone and belongs to nobody. Legacy path: a recording is also referenced from a note by at-uri embedded in the note's content.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `audio` | `blob` | Yes | The recording itself. video/mp4 and video/webm are accepted alongside audio/* because a PDS sniffs the container rather than trusting the upload's Content-Type: an audio-only MP4 or M4A sniffs as video/mp4, and a sniffer that reads no further than the EBML magic calls an audio-only WebM video/webm. |
| `title` | `string` | No |  |
| `credits` | `array` | No | Attribution for openly licensed music mixed into the recording. Only licences that require it are listed — a CC0 track is deliberately absent, because CC0 asks for nothing and an entry here would imply otherwise. |
| `language` | `string` | No | The language spoken in the recording. ISO 639-3, the same code space as space.remanso.note's `language`, so a note and its recording agree on how a language is spelled. A recording whose speech was never identified simply omits this. |
| `createdAt` | `string` (datetime) | Yes |  |
| `recordedAt` | `string` (datetime) | No | When the audio was originally captured — a past stream's air date, not the upload time. |
| `transcript` | `ref` → `#transcript` | No |  |
| `durationSec` | `integer` | No | Playback length in seconds. |

### `space.remanso.recording#credit`

**Type**: `object`

One openly licensed work used in the recording, and where its terms live.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `title` | `string` | Yes |  |
| `creator` | `string` | Yes |  |
| `license` | `string` | Yes | The licence's short id, e.g. "by". |
| `sourceUrl` | `string` (uri) | Yes | The work's landing page at its provider. |
| `licenseUrl` | `string` (uri) | Yes |  |

### `space.remanso.recording#transcript`

**Type**: `object`

What was said, as text. A recording is published before anything has transcribed it, so audio with no transcript is the normal starting state rather than an incomplete record — which is why this is optional and written by a later putRecord. `text` is the whole transcript in reading order and is always present; `segments` is that same text cut into timestamped spans. The two never disagree: a client renders either one without reconciling them, and a writer that edits one rewrites both.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `text` | `string` | Yes | The transcript in reading order, paragraphs separated by a blank line. Equal to `segments` joined the same way, when segments are present. |
| `segments` | `array` | No | The transcript cut into timestamped spans, one paragraph each — the granularity a reader scans and seeks by, not the two-second slivers a speech model emits. Absent when the audio yielded no usable timestamps, which happens on very short clips. |
| `createdAt` | `string` (datetime) | Yes | When this transcript was written, which is later than the recording's own createdAt, and is bumped on every correction. |

### `space.remanso.recording#transcriptSegment`

**Type**: `object`

One timestamped span of the transcript. Offsets are milliseconds from the start of the audio: the lexicon data model has no float, and rounding to whole seconds would land a seek target after the words the timestamp labels.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `text` | `string` | Yes |  |
| `endMs` | `integer` | Yes | Offset from the start of the audio, in milliseconds. Never before `startMs`. |
| `startMs` | `integer` | Yes | Offset from the start of the audio, in milliseconds. |

## Raw Schema

```json
{
  "id": "space.remanso.recording",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "audio",
          "createdAt"
        ],
        "properties": {
          "audio": {
            "type": "blob",
            "accept": [
              "audio/*",
              "video/mp4",
              "video/webm"
            ],
            "maxSize": 50000000,
            "description": "The recording itself. video/mp4 and video/webm are accepted alongside audio/* because a PDS sniffs the container rather than trusting the upload's Content-Type: an audio-only MP4 or M4A sniffs as video/mp4, and a sniffer that reads no further than the EBML magic calls an audio-only WebM video/webm."
          },
          "title": {
            "type": "string",
            "maxLength": 1000
          },
          "credits": {
            "type": "array",
            "items": {
              "ref": "#credit",
              "type": "ref"
            },
            "maxLength": 64,
            "description": "Attribution for openly licensed music mixed into the recording. Only licences that require it are listed — a CC0 track is deliberately absent, because CC0 asks for nothing and an entry here would imply otherwise."
          },
          "language": {
            "type": "string",
            "maxLength": 10,
            "description": "The language spoken in the recording. ISO 639-3, the same code space as space.remanso.note's `language`, so a note and its recording agree on how a language is spelled. A recording whose speech was never identified simply omits this.",
            "knownValues": [
              "afr",
              "ara",
              "aze",
              "bel",
              "ben",
              "bul",
              "cat",
              "ces",
              "ckb",
              "cmn",
              "dan",
              "deu",
              "ell",
              "eng",
              "est",
              "eus",
              "fin",
              "fra",
              "hau",
              "heb",
              "hin",
              "hrv",
              "hun",
              "hye",
              "ind",
              "isl",
              "ita",
              "jpn",
              "kat",
              "kaz",
              "kor",
              "lit",
              "mar",
              "mkd",
              "nld",
              "nob",
              "pes",
              "pol",
              "por",
              "ron",
              "run",
              "rus",
              "slk",
              "spa",
              "srp",
              "swe",
              "tgl",
              "tur",
              "ukr",
              "vie"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "datetime"
          },
          "recordedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the audio was originally captured — a past stream's air date, not the upload time."
          },
          "transcript": {
            "ref": "#transcript",
            "type": "ref"
          },
          "durationSec": {
            "type": "integer",
            "description": "Playback length in seconds."
          }
        }
      },
      "description": "An audio recording — a past stream, a podcast episode, a voice note. A recording at rkey R is the recording of the space.remanso.note at rkey R in the same repo: one note, at most one recording, paired by convention rather than by a field, so a reader that knows the note's did and rkey reaches the audio with a single getRecord. A recording whose rkey matches no note stands alone and belongs to nobody. Legacy path: a recording is also referenced from a note by at-uri embedded in the note's content."
    },
    "credit": {
      "type": "object",
      "required": [
        "title",
        "creator",
        "license",
        "licenseUrl",
        "sourceUrl"
      ],
      "properties": {
        "title": {
          "type": "string",
          "maxLength": 1000
        },
        "creator": {
          "type": "string",
          "maxLength": 1000
        },
        "license": {
          "type": "string",
          "maxLength": 64,
          "description": "The licence's short id, e.g. \"by\"."
        },
        "sourceUrl": {
          "type": "string",
          "format": "uri",
          "description": "The work's landing page at its provider."
        },
        "licenseUrl": {
          "type": "string",
          "format": "uri"
        }
      },
      "description": "One openly licensed work used in the recording, and where its terms live."
    },
    "transcript": {
      "type": "object",
      "required": [
        "text",
        "createdAt"
      ],
      "properties": {
        "text": {
          "type": "string",
          "maxLength": 100000,
          "description": "The transcript in reading order, paragraphs separated by a blank line. Equal to `segments` joined the same way, when segments are present."
        },
        "segments": {
          "type": "array",
          "items": {
            "ref": "#transcriptSegment",
            "type": "ref"
          },
          "maxLength": 4096,
          "description": "The transcript cut into timestamped spans, one paragraph each — the granularity a reader scans and seeks by, not the two-second slivers a speech model emits. Absent when the audio yielded no usable timestamps, which happens on very short clips."
        },
        "createdAt": {
          "type": "string",
          "format": "datetime",
          "description": "When this transcript was written, which is later than the recording's own createdAt, and is bumped on every correction."
        }
      },
      "description": "What was said, as text. A recording is published before anything has transcribed it, so audio with no transcript is the normal starting state rather than an incomplete record — which is why this is optional and written by a later putRecord. `text` is the whole transcript in reading order and is always present; `segments` is that same text cut into timestamped spans. The two never disagree: a client renders either one without reconciling them, and a writer that edits one rewrites both."
    },
    "transcriptSegment": {
      "type": "object",
      "required": [
        "startMs",
        "endMs",
        "text"
      ],
      "properties": {
        "text": {
          "type": "string",
          "maxLength": 10000
        },
        "endMs": {
          "type": "integer",
          "minimum": 0,
          "description": "Offset from the start of the audio, in milliseconds. Never before `startMs`."
        },
        "startMs": {
          "type": "integer",
          "minimum": 0,
          "description": "Offset from the start of the audio, in milliseconds."
        }
      },
      "description": "One timestamped span of the transcript. Offsets are milliseconds from the start of the audio: the lexicon data model has no float, and rounding to whole seconds would land a seek target after the words the timestamp labels."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
