Open Videocore

Open Videocore is a headless media asset management (MAM) system from Eyevinn Technology. It stores, transcodes, packages, and delivers video content through a single API. Under the hood it integrates SVT Encore for transcoding, Shaka Packager for packaging, MinIO for object storage, and CouchDB for the asset catalogue.

Getting Started

Deploy an Open Videocore instance at app.osaas.io/dashboard/service/eyevinn-open-videocore.

Getting from a new instance to a playable asset takes five steps: create the instance, provision a media stack, bootstrap the transcoding profiles, ingest a source, and transcode it. Steps 4 and 5 below are required — the ingest call will not work without them.

Prerequisites

Configuration Options

Field Required Description
name Yes Alphanumeric instance name
OscAccessToken Yes OSC PAT used by Open Videocore to spin up Encore transcoding jobs (sensitive)
ParameterStoreApiKey Yes API key for the Parameter Store instance
ParameterStore Yes Name of the Parameter Store instance
MinioRootPassword Yes Root password for the MinIO object storage backend (sensitive)
CouchdbAdminPassword Yes Admin password for the CouchDB asset catalogue (sensitive)
EncoreMaxInstances No Maximum concurrent Encore transcoding instances
EncoreMinInstances No Minimum Encore instances to keep warm
EncoreIdleTimeoutMs No Milliseconds before idle Encore instances are scaled down

The effective values of the three Encore* fields on a running instance are readable from GET /api/v1/scaler/status, and can be changed at runtime without a restart via PATCH /api/v1/scaler/config. See Tuning the Encore auto-scaler.

Token Costs

Short answer: yes, the services Open Videocore provisions are billed in addition to Open Videocore itself, and the on-demand Encore instances are by far the largest component.

Open Videocore is an orchestration layer. Its own service page rate covers only the Open Videocore instance. Everything it provisions on your behalf is a separate OSC service instance with its own token rate, running in your workspace and billed to you.

Always running once you provision a stack:

Service What it does
eyevinn-open-videocore the API and orchestrator itself
minio-minio object storage for sources and packaged output
apache-couchdb the asset catalogue
valkey-io-valkey the job queue

Provisioned on demand, and torn down again:

Service When it appears
encore spun up by the auto-scaler when transcode jobs arrive, torn down after EncoreIdleTimeoutMs of idle time. This is the dominant cost and the one worth tuning.
eyevinn-encore-packager created lazily on the first packaging job, then reused; removed when the stack is deprovisioned
eyevinn-ffmpeg-s3 per-job, for technical metadata extraction

To see the current rate for any of these before you commit to it, ask your MCP-connected agent to estimate the cost, or check each service's page in the dashboard. Rates are quoted per instance-day and are ceilings — the maximum if the instance ran continuously — so a stack whose Encore instances scale to zero between jobs bills well below the ceiling. See Pricing.

The lever that matters. Encore dominates the bill and only runs while it has work. If your jobs arrive in bursts, lowering EncoreIdleTimeoutMs tears instances down sooner between bursts. If they arrive steadily, leaving the timeout higher avoids paying the cold-start on every job. GET /api/v1/scaler/status shows what the pool is doing right now.

Step-by-Step Guide

1. Create a Parameter Store

Open Videocore requires a Parameter Store to hold configuration. Create one first:

  1. Go to My Apps → Parameter Store and click Create parameter store
  2. Note the store name and API key shown on creation

2. Store sensitive credentials as service secrets

osc create-secret miniopwd <your-minio-root-password>
osc create-secret couchdbpwd <your-couchdb-admin-password>
osc create-secret oscpat <your-osc-pat>
osc create-secret paramstorekey <your-parameter-store-api-key>

3. Create the Open Videocore instance

osc create eyevinn-open-videocore myvideocore \
  -o OscAccessToken="{{secrets.oscpat}}" \
  -o ParameterStoreApiKey="{{secrets.paramstorekey}}" \
  -o ParameterStore="my-param-store" \
  -o MinioRootPassword="{{secrets.miniopwd}}" \
  -o CouchdbAdminPassword="{{secrets.couchdbpwd}}"

Via API:

curl -s -X POST \
  -H "x-pat-jwt: Bearer $PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "myvideocore",
    "OscAccessToken": "{{secrets.oscpat}}",
    "ParameterStoreApiKey": "{{secrets.paramstorekey}}",
    "ParameterStore": "my-param-store",
    "MinioRootPassword": "{{secrets.miniopwd}}",
    "CouchdbAdminPassword": "{{secrets.couchdbpwd}}"
  }' \
  https://eyevinn-open-videocore.svc.prod.osaas.io/eyevinn-open-videocoreinstance

The instance URL is shown in the dashboard. It is written as https://<instance-url> in the rest of this guide.

4. Provision a media stack

Required before you can ingest anything. This stands up the backing infrastructure for a workspace: MinIO, CouchDB, and Valkey. Encore is not created here — the auto-scaler spins it up when the first transcode job arrives — and the packager is created lazily on the first packaging job.

curl -s -X POST https://<instance-url>/api/v1/provision/ \
  -H "Content-Type: application/json" \
  -d '{"name": "mystack"}'

Provisioning is asynchronous. The call returns an operationId. Poll it until status is done:

curl -s https://<instance-url>/api/v1/provision/operations/<operationId>

Inspect or tear down stacks later:

curl -s https://<instance-url>/api/v1/provision/            # list stacks
curl -s https://<instance-url>/api/v1/provision/mystack     # inspect one
curl -s -X DELETE https://<instance-url>/api/v1/provision/mystack

By default the stack provisions its own MinIO instance and buckets, and no storage configuration is needed. To point the source or packaged-output roles at an existing AWS-region or S3-compatible bucket instead, pass the optional sourceStorage and packagedStorage blocks. The provisioning with external S3-compatible storage guide documents every field, including the CDN-origin pattern.

5. Bootstrap the transcoding profiles

Also required. This seeds the profile store from the default Encore profile index. Without it there are no profiles for a transcode job to reference.

curl -s -X POST https://<instance-url>/api/v1/profiles/bootstrap

Pass ?force=true to re-seed. Profiles are stored in CouchDB and can be listed, created, replaced, and deleted through /api/v1/profiles, or managed in the Profiles tab of the ops dashboard.

6. Ingest a source video

curl -s -X POST https://<instance-url>/api/v1/assets/ingest-url \
  -H "Content-Type: application/json" \
  -d '{"sourceUrl": "https://example.com/source.mp4", "name": "My first asset"}'

Only sourceUrl is required; name, description, title, and tags are optional. The response contains the asset ID used in every call below.

Other ingest routes are available for media you are not pulling from a URL: PUT /api/v1/assets/:id/upload for a direct upload, POST /api/v1/assets/:id/upload-url for a presigned single-part upload, and the POST /api/v1/assets/:id/multipart/initiate family for large files. Watch-folder ingest from a bucket is available through /api/v1/storage/buckets/:bucket/watch-folder/toggle.

7. Transcode

curl -s -X POST https://<instance-url>/api/v1/assets/<asset-id>/transcode \
  -H "Content-Type: application/json" \
  -d '{"profile": "program"}'

All body fields are optional: profile names a bootstrapped profile, customProfile supplies profile YAML inline, and profileParams passes parameters to a parametrised profile.

This is the first call that causes an Encore instance to be created, so the first job on a cold pool takes noticeably longer than later ones. Track progress with GET /api/v1/jobs/ and GET /api/v1/jobs/<job-id>.

To package for adaptive streaming, POST /api/v1/assets/<asset-id>/package. POST /api/v1/assets/<asset-id>/execute runs transcode and packaging as one pipeline execution.

8. Get playback URLs

curl -s https://<instance-url>/api/v1/assets/<asset-id>/delivery

Returns the packaged HLS/DASH manifest URLs, or a presigned download URL for the source.

Webhooks

Rather than polling /api/v1/jobs/, register a webhook and Open Videocore will notify you on asset and job lifecycle events.

curl -s -X POST https://<instance-url>/api/v1/webhooks/ \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/videocore",
    "events": ["transcode.complete", "transcode.failed"],
    "secret": "<shared-secret-for-signature-verification>"
  }'

url and events are required, secret is optional. Available events:

Event Fires when
asset.ready an ingested asset is ready
asset.failed ingest failed
transcode.complete a transcode job finished
transcode.failed a transcode job failed
package.complete a packaging job finished
package.failed a packaging job failed

List with GET /api/v1/webhooks/ and remove with DELETE /api/v1/webhooks/<id>.

Ops dashboard

Every instance serves a built-in dashboard at https://<instance-url>/ui for managing assets, jobs, profiles, and buckets. Interactive API documentation is at https://<instance-url>/api-docs, and a generated openapi.json is committed in the repository if you prefer to read the contract without a running instance.

Other capabilities

Capability Endpoint
Thumbnails / poster frames POST and GET /api/v1/assets/:id/thumbnails
Clip and trim into a new asset POST /api/v1/assets/:id/clip
Container re-wrap without re-encode POST /api/v1/assets/:id/export
Technical metadata extraction POST /api/v1/assets/:id/extract-metadata
Audio and subtitle track management /api/v1/assets/:id/tracks, /audio-tracks, /subtitle-tracks
Collections /api/v1/collections
Full-text and metadata search GET /api/v1/search/
Object storage and buckets /api/v1/storage/buckets

Note that GET /api/v1/assets/search is a deprecated free-text-only alias kept for backward compatibility. New integrations should use GET /api/v1/search/.

Tuning the Encore auto-scaler

curl -s https://<instance-url>/api/v1/scaler/status
curl -s https://<instance-url>/api/v1/scaler/config

curl -s -X PATCH https://<instance-url>/api/v1/scaler/config \
  -H "Content-Type: application/json" \
  -d '{"maxInstances": 3, "idleTimeoutMs": 120000}'

maxInstances, minInstances, and idleTimeoutMs can all be changed at runtime without restarting the instance. idleTimeoutMs must be at least 10000.

scalerActive reads false until a stack is provisioned. The auto-scaler activates against the provisioned stack's Valkey immediately after POST /api/v1/provision/ completes, with no restart needed.

Important Notes

  • Configuration updates not supported. Open Videocore does not support in-place configuration updates via update-service-instance. To change the fields in the table above, delete the instance and create a new one. The auto-scaler settings are the exception and are changeable at runtime, as described above.
  • Data persistence. Asset data is stored in MinIO and CouchDB within the instance. Deleting the instance will delete all stored assets and the asset catalogue.
  • Provisioning and profile bootstrap are one-time per stack, but both are required before the first ingest. A 404 or an empty profile list on your first transcode almost always means one of them was skipped.

Resources