Media Domain
Manages media assets stored in SeaweedFS β video, image, audio, document. Full lifecycle: upload token β TUS upload β background processing (normalize/transcode/optimize/rasterize) β asset serving.
See also: Architecture (serving, storage layout, upload flow, status lifecycle, NATS events) and Transcoding (data model, pipelines, passthrough, seeded profiles).
Handles:
- TUS resumable upload (prepare β upload β post-finish webhook)
- Video normalize (AV trim, mdat defrag, EBU R128 loudnorm)
- Video transcode (CMAF ladder), image optimize (webp), document rasterize (per-page JPEG + slide metadata) β one shared, category-discriminated
TranscodingProfile - Passthrough per category (skip pipeline, serve as-is)
- Thumbnail generation (video/image/pdf/office)
- CRUD, soft delete with S3 purge (default on), storage audit
- NATS events on processing milestones
- Batch upload
- Cache purge on rename/delete/reprocess (cproxy purge not wired to media mutations)
- Real CDN/GSLB hostname (currently a bucket-qualified local URL)
Domain Structure
domain/media/
βββ config.go env config
βββ helper.go response shaping, media-type inference, ffprobe wrappers
βββ models.go GORM models β Media, TranscodingProfile(+Version), MediaSlide, MediaPlaylist(+Item), UploadToken
βββ validation.go ValidatePrepare
β
βββ handlers/
β βββ handler_media.go CRUD, asset serving/presign, delete+purge
β βββ handler_upload.go prepare token, tusd post-finish webhook
β βββ handler_process.go pipeline orchestration, thumbnails, dedup
β βββ handler_normalize.go video normalize (remux + loudnorm)
β βββ handler_image.go image optimize (webp)
β βββ handler_document.go document rasterize + slides
β βββ handler_transcode.go video CMAF ladder
β βββ handler_transcoding_profiles.go profile/version CRUD
β βββ handler_playlist.go media playlists (SMIL/CMAF)
β βββ handler_query.go folders/tenants/tags/stats
β βββ handler_nats.go NATS subscribers
β βββ handler_storage_audit.go orphan/missing audit
β βββ handler_pdf.go legacy PDF path β see To-do, not part of the real pipeline
β
βββ repositories/media_repository.go MediaRepository
βββ routes/ wire.go (Setup) + routes.go
Mount point: media's own routes (/media/...) sit under /api/v1;
/assets/* and /hooks/tusd are mounted on the app root instead (see
Architecture).
Testing
An in-page upload form isn't practical here β this is a static docs site, and the upload path is TUS (a resumable-upload protocol), not a plain HTTP form Swagger's "try it" can drive.
- The embedded spec below can exercise every JSON endpoint directly
against a running server (
/media/prepare,/media/transcoding-profilesCRUD,/media/:id, etc. β see theservers:list in the spec). - The file upload step itself still needs a real TUS client β either drive it through PlayoutAdmin's own "Add content" UI, or see guide.md for a curl-based walkthrough per pipeline (profile lookup β prepare β verify).
To-do / known gaps
- Auth: media routes aren't gated by the RS256 JWT middleware at registration (unlike identity/tenancy) β confirm whether that's intentional before wiring tenant/org derivation from the token.
- Tenant/folder still hardcoded on the frontend β see the
Media Upload capability app
for the concrete to-do (derive from AuthAPI's
orgs[]claim). -
/hooks/tusdhas no signature/secret check β only the opaqueuploadTokenmetadata value gates it. Anyone who can reach CoreAPI can POST a fabricated post-finish payload. -
handler_pdf.go(GET /media/convert-pdf/:key) is a legacy, parallel PDF-rasterization path with hardcoded staging hostnames (stg.filer.castis.io,stg.api.castis.io) and its own local disk cache β unrelated to and duplicatinghandler_document.go's realrasterizeDocumentpipeline. Candidate for removal. - Dead code:
validation.go'sValidateDirectUpload,handler_playlist_helpers.go's two error constructors,handler_playlist.go'sconcatAndNormalizeβ none have any caller. -
/assets/*is bypassed in the local/Quickstart topology β nginx routes it straight to cproxyβSeaweedFS, not to CoreAPI's ownServeAsset/PresignAsset. Don't assume a browser client ever hits CoreAPI directly for asset bytes; see Architecture. - Batch upload, cache invalidation on mutation, real CDN hostname β as above.