Service: Open Videocore - EyevinnOSC/community GitHub Wiki
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.
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.
- An OSC account on a paid plan (sign up at app.osaas.io)
- A Parameter Store instance (required for configuration)
- An OSC Personal Access Token (PAT) — create one at app.osaas.io/dashboard/tokens
| 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 |
ENCORE_PROFILES_URL |
No | URL of a custom Encore profiles index. When set, Encore instances use this instead of the auto-derived PUBLIC_BASE_URL path. |
ENCORE_PROFILES_URL_OVERRIDE |
No | Force all Encore instances to use this profiles URL, overriding the derived PUBLIC_BASE_URL path and any parameter-store value. |
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.
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.
Open Videocore requires a Parameter Store to hold configuration. Create one first:
- Go to My Apps → Parameter Store and click Create parameter store
- Note the store name and API key shown on creation
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>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-videocoreinstanceThe instance URL is shown in the dashboard. It is written as https://<instance-url> in the rest of this guide.
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/mystackBy 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.
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/bootstrapPass ?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.
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 { assetId, jobId } — use assetId (not id) in every subsequent call.
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.
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>.
Preferred path — transcode and package together:
curl -s -X POST https://<instance-url>/api/v1/assets/<asset-id>/execute \
-H "Content-Type: application/json" \
-d '{"pipeline": "abr-vod"}'This returns an executionId. Poll the pipeline until it is done:
curl -s https://<instance-url>/api/v1/pipelines/<executionId>Packaging only (after transcoding):
curl -s -X POST https://<instance-url>/api/v1/assets/<asset-id>/packageWhy the first packaging call may time out with 504
encore-packager is provisioned lazily on the first packaging job (see Token Costs above). On a cold workspace this synchronous provisioning can take 60–90 seconds, which exceeds the 60-second nginx ingress timeout. When this happens the 504 response means the packaging pipeline was still created and is running in the background — poll GET /api/v1/pipelines/<executionId> (for execute) or GET /api/v1/jobs/<job-id> (for package) until the job completes. All subsequent packaging calls are fast because the packager instance is already running.
curl -s https://<instance-url>/api/v1/assets/<asset-id>/deliveryReturns the packaged HLS/DASH manifest URLs, or a presigned download URL for the source.
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>.
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.
| 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/.
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.
| Code | Meaning | What to do |
|---|---|---|
| 501 | Stack not yet provisioned | Run POST /api/v1/provision/ and wait until status is done
|
| 502 | Packager provisioning failed | Check that the PAT stored in config has permission to create service instances |
409 pipeline_running
|
Another pipeline is already running for this asset | Wait for it to complete, then retry |
| 504 | First packaging call timed out while packager was being provisioned | The pipeline was still created — poll GET /api/v1/pipelines/<executionId> or GET /api/v1/jobs/<job-id>
|
-
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
404or an empty profile list on your first transcode almost always means one of them was skipped.
- GitHub repository
- Service page
- SVT Encore — the transcoding engine used internally
- Parameter Store
- Pricing