MediaClip media.clip@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
media
Visibility
first-party
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/media/clip.v1.json

media.clip@1: one clip as OpenVibe.Media's API answers it (server/vod/clips-routes.js clipPublic: GET /api/v1/:app/clips/:id, the list, create, trim and update). Its numeric id, the recording it was cut from, the clipper and the clipped channel, title and status (processing, ready or failed), its window in the source, duration, the file basename, the URL its bytes play from, thumbnail, visibility, whether an automation cut it (auto_generated) and its view counts. watch_id is the id openvibe.video addresses the watch page by (openvibe.video/watch?v=<watch_id>): 11 characters of URL-safe base64 from 8 random bytes, in the same id space as a VOD's, fixed for the row's life, never derived from the numeric id. More fields may be added.

Fields

FieldTypeRequiredDescriptionConstraints
idintegeryesThe clip's numeric id inside Media. Internal: a watch page is addressed by watch_id.
  • minimum 1
watch_idstringThe id of its watch page on openvibe.video (openvibe.video/watch?v=<watch_id>): 8 random bytes as URL-safe base64, 64 bits. One id space across VODs and clips — a watch id never names both a VOD and a clip. Optional: a row written before the ids existed may answer without one until Media's backfill fills it.
  • pattern ^[A-Za-z0-9_-]{11}$
app_idstringyesThe tenant that owns the clip (live, media-hub…).
vod_idinteger | nullThe recording it was cut from, when it has one.
stream_idinteger | null
user_idstring | integer | nullThe clipper's app-local user id; it is not a Network subject id.
channel_user_idstring | integer | nullThe clipped channel's app-local user id (who the clip is of).
titlestringyes
  • maxLength 200
descriptionstring
statusenumyesprocessing while the cut runs, ready when its file is there, failed when the cut failed (cut_error, and will_retry while a retry is queued).
  • one of "processing", "ready", "failed"
cut_errorstring | null
will_retryboolean
start_timenumberThe clip's start in the source recording, seconds.
  • minimum 0
end_timenumber
  • minimum 0
durationnumber
  • minimum 0
duration_secondsnumber
  • minimum 0
file_pathstring | nullThe file's basename only.
playback_urlstringyesThe URL its bytes play from on openvibe.media.
thumbnail_urlstring | null
preview_urlstring | nullThe hover preview of this item: about 6 s, muted, 320 px wide, MP4 H.264, stored beside its thumbnail and served at /t/<name>. Null until the preview.make job has made it (audio-only, private and too-short items never get one).
preview_webm_urlstring | nullThe same moment as preview_url, encoded as WebM (VP9, VP8 where the encoder has no VP9). Null while preview_url is.
storage_providerstring
visibilityenumyespublic: anyone. unlisted: reached only by its exact id, never listed, noindex. private: missing to everyone but its owner and staff.
  • one of "public", "unlisted", "private"
is_publicbooleanyes
auto_generatedbooleanTrue when an automation (Live's AI moments) cut it, not a person. An AI clip is noindex and never in a sitemap.
ai_overviewstring | null
ai_analyzed_atstring | null
view_countinteger
  • minimum 0
unique_viewsinteger
  • minimum 0
readinessobjectThe object's readiness levels when the read asked for them.
readiness.metadataboolean
readiness.bytes_verifiedboolean
readiness.playableboolean
readiness.reasonstring | null
hls_urlstringThe object's master playlist, when it has one.
hls_expires_atstring | integer
created_atstringyesUTC 'YYYY-MM-DD HH:MM:SS' as the store keeps it.

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: ai-clip-before-the-backfill
{
  "id": 495,
  "app_id": "live",
  "vod_id": 6203,
  "stream_id": 912,
  "user_id": 80,
  "channel_user_id": 80,
  "title": "AI clip: the best thirty seconds",
  "description": "",
  "status": "ready",
  "start_time": 3600,
  "end_time": 3630,
  "duration": 30,
  "duration_seconds": 30,
  "file_path": "clip-live-495-1759915000000.webm",
  "playback_url": "https://openvibe.media/c/495",
  "thumbnail_url": null,
  "storage_provider": "local",
  "visibility": "public",
  "is_public": true,
  "auto_generated": true,
  "view_count": 0,
  "unique_views": 0,
  "created_at": "2026-11-06 21:50:00"
}
Valid: person-made-clip-with-watch-id
{
  "id": 494,
  "watch_id": "x7Kp2mQaB9c",
  "app_id": "live",
  "vod_id": 6203,
  "stream_id": 912,
  "user_id": 57,
  "channel_user_id": 80,
  "title": "That landing",
  "description": "",
  "status": "ready",
  "start_time": 1890.5,
  "end_time": 1920.5,
  "duration": 30,
  "duration_seconds": 30,
  "file_path": "clip-live-494-1759914000000.webm",
  "playback_url": "https://openvibe.media/c/494",
  "thumbnail_url": "https://openvibe.media/t/clip-494.jpg",
  "storage_provider": "local",
  "visibility": "public",
  "is_public": true,
  "auto_generated": false,
  "ai_overview": null,
  "ai_analyzed_at": null,
  "view_count": 412,
  "unique_views": 318,
  "created_at": "2026-11-06 21:40:00"
}
Rejected: unknown-visibility
{
  "id": 497,
  "watch_id": "dQw4w9WgXcQ",
  "app_id": "live",
  "title": "A clip with a visibility nobody offers",
  "status": "ready",
  "visibility": "friends",
  "is_public": false,
  "playback_url": "https://openvibe.media/c/497",
  "created_at": "2026-11-06 23:15:00"
}
Rejected: watch-id-not-url-safe
{
  "id": 496,
  "watch_id": "dQw4w9WgXcQ/",
  "app_id": "live",
  "title": "A clip whose watch id has a slash",
  "status": "ready",
  "visibility": "public",
  "is_public": true,
  "playback_url": "https://openvibe.media/c/496",
  "created_at": "2026-11-06 23:10:00"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('media.clip@1', value);   // { valid, errors: [{ path, message }] }