Docs / Guides / Ingesting media

Ingesting media

Get source video into open-videocore: from a URL, direct upload, presigned/multipart upload, or an object storage watch-folder.

Every asset starts as a record, then gets its source media attached to it one of four ways. Pick the one that matches where your video already lives.

1. Create the asset record

An asset always starts as a record you create explicitly, or one created for you by the ingest-from-URL shortcut below.

Request
curl -X POST https://<your-instance>/api/v1/assets \
  -H "Content-Type: application/json" \
  -d '{"title": "Keynote recording", "description": "Opening keynote, main stage"}'

See POST /api/v1/assets/ — full field list in the Assets reference.

2. Ingest from a public URL

If the source file is already reachable over HTTP(S), skip the manual create step — this creates the asset and starts the download in one call:

Request
curl -X POST https://<your-instance>/api/v1/assets/ingest-url \
  -H "Content-Type: application/json" \
  -d '{"sourceUrl": "https://example.com/video.mp4", "title": "Keynote recording"}'

This returns a Job of type ingest-url. Poll GET /api/v1/jobs/{id} until status is done; the job's assetId is the asset to work with next.

3. Direct upload (small files)

For files you already have locally and that are small enough to send in one request:

Request
curl -X PUT https://<your-instance>/api/v1/assets/<id>/upload \
  -H "Content-Type: video/mp4" \
  --data-binary @video.mp4

4. Presigned upload (browser / large single-part)

To upload directly to object storage from a browser or client without proxying bytes through the API, get a presigned URL first, upload to it, then tell the API the upload finished:

Request
curl -X POST https://<your-instance>/api/v1/assets/<id>/upload-url
# -> { "url": "https://...", ... } — PUT your file bytes to that URL, then:
curl -X POST https://<your-instance>/api/v1/assets/<id>/upload-complete

5. Multipart upload (large files)

For files too large for a single PUT, initiate a multipart upload, request a presigned URL per part, upload each part directly to storage, then complete:

  1. POST /api/v1/assets/{id}/multipart/initiate
  2. GET /api/v1/assets/{id}/multipart/{uploadId}/part-url — once per part
  3. POST /api/v1/assets/{id}/multipart/{uploadId}/complete
  4. If something goes wrong: DELETE /api/v1/assets/{id}/multipart/{uploadId} — abort

6. Watch-folder ingest

Point open-videocore at an object storage bucket and it will pick up new files dropped straight into that bucket (via mc, rclone, or another system) automatically, without any per-file API call:

Request
curl -X POST https://<your-instance>/api/v1/storage/buckets/<bucket>/watch-folder/toggle \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
Watch-folder ingest is not available on the hosted platform by default. Unlike the other four ingest paths above, it is not supported in the default provisioned (multi-stack) deployment, because there is no single shared source bucket to watch. It requires a deployment configured against one global, directly-reachable object-storage endpoint (see prerequisites below). If you are on the hosted platform and need it, it is pending provisioning work — use URL pull, direct upload, presigned, or multipart ingest in the meantime.

Prerequisites

Watch-folder ingest is only wired up when the deployment is pointed at a single, directly-reachable object-storage endpoint. Two things must both be configured on the API process:

  1. A global object-storage endpoint via the MINIO_URL environment variable (with MINIO_ACCESS_KEY / MINIO_SECRET_KEY). Without this the watch-folder service is never started — the API falls back to the per-request upload and URL-pull routes only.
  2. The opt-in flag WATCH_FOLDER_ENABLED=true. The service is disabled by default even when object storage is configured.

Optionally, tune the polling fallback cadence with WATCH_FOLDER_POLL_INTERVAL_SECONDS (default 30); it is used when the storage backend does not expose bucket-change notifications.

Verify it is active

Confirm the watch-folder is configured and running before you rely on it:

Request
curl https://<your-instance>/api/v1/admin/watch-folder/status

A response of {"enabled": true, "running": true, ...} means the service is configured and watching. "enabled": false means the prerequisites above are not met on this deployment (no global object-storage endpoint, or WATCH_FOLDER_ENABLED is not set) and watch-folder ingest is unavailable there. See the Admin reference for the poller's start/stop controls and the Storage reference for per-bucket listing and toggling.

Every path above ends at the same place: an Asset with status moving from uploading to processing to ready (or failed). Watch that field, or an asset.ready / asset.failed webhook, rather than polling the job directly once the source file has landed.