SourceAudit

rendered, live
the wire — click a line to scrub
the contract — SourceAudit in catalog.json
{
  "type": "object",
  "properties": {
    "component": {
      "const": "SourceAudit"
    },
    "label": {
      "$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DynamicString",
      "description": "What this recording is, e.g. 'Support call — Acme Corp, 14 Aug'. Required — the accessible name."
    },
    "mediaUrl": {
      "type": "string",
      "description": "URL of the recording (host-signed, short-lived is fine). Required. Never autoplays."
    },
    "mediaKind": {
      "enum": [
        "video",
        "audio"
      ],
      "description": "Which player to render. Required."
    },
    "posterUrl": {
      "type": "string",
      "description": "Poster image for video, shown before load."
    },
    "durationSeconds": {
      "type": "number",
      "description": "Raw duration. Supplying it lets the player reserve its scrubber layout before media metadata arrives — zero CLS."
    },
    "captionsUrl": {
      "type": "string",
      "description": "WebVTT captions URL. Captions are the requirement; the transcript is an enhancement."
    },
    "transcript": {
      "oneOf": [
        {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "startSeconds": {
                "type": "number",
                "description": "Raw offset into the media."
              },
              "speaker": {
                "type": "string",
                "description": "Who is talking, e.g. 'Customer'."
              },
              "text": {
                "type": "string"
              }
            },
            "required": [
              "startSeconds",
              "text"
            ],
            "additionalProperties": false
          }
        },
        {
          "$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/DataBinding"
        }
      ],
      "description": "Time-synced lines. Bind with {\"path\": ...} — transcription runs async, so an empty transcript is a common, designed state ('transcript still processing'), not an error."
    },
    "seekAction": {
      "$ref": "https://a2ui.org/specification/v1_0/common_types.json#/$defs/Action",
      "description": "Optional: fired when the user seeks via a transcript line; startSeconds is merged into its context automatically."
    }
  },
  "required": [
    "label",
    "mediaUrl",
    "mediaKind"
  ]
}
the prompt-pack — paste into your agent
### SourceAudit — the recording and its time-synced transcript

The terminus of every drill path: the customer saying it in their own words. Never autoplays.
Transcript lines seek the media on activation.

| prop              | type                           | notes                                                            |
| ----------------- | ------------------------------ | ---------------------------------------------------------------- |
| `label`           | string, required               | what this recording is                                           |
| `mediaUrl`        | string, required               | host-signed URL is fine                                          |
| `mediaKind`       | `"video" \| "audio"`, required |                                                                  |
| `posterUrl`       | string                         | video poster                                                     |
| `durationSeconds` | number                         | lets the player reserve layout before metadata — zero CLS        |
| `captionsUrl`     | string                         | WebVTT; captions are the requirement, transcript the enhancement |
| `transcript`      | line[] \| `{"path"}`           | bind it — transcription is async; empty means "still processing" |
| `seekAction`      | action                         | optional; `startSeconds` merged automatically                    |

Transcript line shape — `startSeconds` and `text` required:

```
{"startSeconds":124,"speaker":"Customer","text":"The export says 1.2 million but the screen says 1.4."}
```

```
{"id":"audit","component":"SourceAudit","label":"Support call — Acme Corp, 14 Aug","mediaUrl":"https://media.example.com/calls/ac-2214.mp4","mediaKind":"video","durationSeconds":847,"captionsUrl":"https://media.example.com/calls/ac-2214.vtt","transcript":{"path":"/call/transcript"}}
```