Media metering operations
This guide is for private-deployment operators. Tenant prices and top-ups are described in Audio/video billing. Standard-duration charging requires actual reception-layer metering, signed reports and persistent retries. Upgrading only the business backend while retaining unmodified LiveKit does not complete the billing path.
Architecture
Client SDK → Metered LiveKit → Persistent report spool
↓ signed report
Backend usage API
↓ transaction
Receipt + Monthly total + App walletThe enhanced image uses pinned LiveKit v1.13.1. Measurement is server-side, not a browser/app self-reported bill. Calls and channels share a metering protocol. Keep the media API Secret only on the backend and media servers, never on clients.
Configuration and persistence
| Setting | Requirement |
|---|---|
| Media image | Enhanced LiveKit with the im-standard-duration-v1 adapter |
IM_BILLING_URL | Complete backend /rtc/v1/usage/<service_id> URL reachable from the media container |
IM_BILLING_SECRET | API Secret registered for this media service |
IM_BILLING_SPOOL | Persistent container directory, default /var/lib/im-billing |
IM_BILLING_TIMEZONE | Backend statistics timezone, normally Asia/Shanghai |
LiveKit keys and Webhook | Retain service credentials and working event callbacks; usage does not replace Webhook |
Mount the spool on persistent host storage or a volume. Each media node needs its own reliable directory; do not place multiple writers in one uncoordinated shared directory. Enhanced LiveKit has local accounting data that must survive container replacement. It is not disposable cache.
The backend receives usage. Media /im/billing-health verifies the protocol and target service ID. Updating an image does not require creating a new service identity; callbacks and usage must reference the existing service ID.
Build and overlay example
Build the enhanced image from the repository root:
docker build -f deploy/livekit-billing/Dockerfile -t im/livekit-billing:1.13.1 .Add an overlay to the existing LiveKit service. This example shows additions only; retain actual keys, ports, Redis, Webhook and public media addresses:
services:
livekit:
image: im/livekit-billing:1.13.1
environment:
IM_BILLING_URL: ${IM_MEDIA_USAGE_URL:?Set the backend usage URL}
IM_BILLING_SECRET: ${LIVEKIT_API_SECRET:?Set the existing service secret}
IM_BILLING_SPOOL: /var/lib/im-billing
IM_BILLING_TIMEZONE: Asia/Shanghai
volumes:
- ./data/livekit-billing:/var/lib/im-billingSet deployment IM_MEDIA_USAGE_URL to the complete reachable backend endpoint, for example http://backend:8080/rtc/v1/usage/<service_id>. Replace the address and service ID rather than copying placeholders. The Secret must match the platform service record. Append this overlay to the existing Compose list, validate merged configuration, and update within the planned media window. Distribute the image to every media host.
Local development can use make livekit-billing-up after setting IM_DEV_LIVEKIT_BILLING_URL. It uses development Compose and a separate persistent volume; do not apply it directly over an existing production cluster.
Upgrade sequence
- Record node images, service IDs, timezone and effective configuration. Back up the database, configuration and old images, plus existing report spools. Preserve runtime configuration, not only repository templates.
- Plan a transition date and a window without active media rooms. Apply
billing/0008_app_walletsand other actual pending migrations once for a shared database. - Verify
media_billing_from. Migration initialization uses UTC, while business days follow the configured timezone. Align the planned date before activation; do not casually move the boundary after funds or receipts exist. - Upgrade all backend and media nodes. Configure signed usage, existing event callbacks and persistent storage. Retain all cluster Compose overlays rather than starting only the base file.
- Verify each
/readyz, protocol, service ID, signature checks and spool access. Enable the rules after all nodes are compatible. The backend rejects new media resources when metering is absent or its service ID mismatches. - Fund an isolated acceptance application and test known audio, single-video, multi-stream reception and midnight cases. Reconcile standard duration and ledgers; duplicate reports must not duplicate debits.
A successful deployment, an HTTP 200 and verified real-call charging are different findings. Record the actual validation scope; anonymous-page checks cannot replace payments and media tests.
Reports and retries
- Metering starts with a media connection and stops at its end. Actual forwarded spatial layers determine one tier per second.
- Cumulative snapshots are atomically saved every five seconds and immediately on disconnection. Sending is retried every five seconds. Failed requests retain snapshots; confirmed final snapshots are deleted.
- Restart replays saved seconds, not downtime. Persistent snapshots cannot recover every sample that was not yet saved; compare the last successful snapshot after abnormal termination.
- Signatures use
HMAC-SHA256(API Secret, timestamp + "." + raw JSON)withX-IM-Usage-TimeandX-IM-Usage-Signature. The allowed clock skew is five minutes; synchronize host clocks. - Backend room/service bindings identify the application. Client-supplied application IDs do not replace these bindings. Receipts, monthly totals, balances and ledgers commit together. Conflicting same-version reports are rejected, older ones ignored, and newer ones settle only the difference.
Health and alerts
| Check | Interpretation and action |
|---|---|
| Backend readiness | Each /readyz is healthy; check dependencies and migrations |
| Media protocol | /im/billing-health returns im-standard-duration-v1 with the correct service ID in the usage path |
| Retry backlog | Watch file count, oldest snapshot and send errors; sustained growth after calls end requires investigation |
| Disk and permissions | Writable directory, sufficient capacity and persistent mount after replacement |
| Clock and authentication | For 401, check Secret, raw JSON, timestamp and clock skew |
| Room binding | For 404, check service ID and durable room mapping; do not bypass with fabricated application fields |
| Accounting | Reconcile balance = purchased − consumed, monthly standard duration/charged minutes, duplicates and corrections |
Retain service, room/receipt ID, version, request ID, time and HTTP status for troubleshooting. Do not include Secrets, user tokens or notification credentials in logs or tickets. Unknown-room probes can test signature boundaries but are not real usage tests.
Backup, recovery and rollback
The database holds wallets, ledgers, receipts and monthly totals; the persistent spool holds unconfirmed snapshots; runtime configuration holds signing and routing identity. Recovery must consider all three.
When replacing one media container, retain its volume, service identity and Secret, then observe retries draining after connectivity returns. Old snapshots restored against a newer database are subject to idempotency, but this is not a reason to delete unconfirmed newer snapshots. Preserve backup permissions and protect configuration under deployment credential policies.
Before rolling back business or media images, check whether the new mode has created top-ups or usage ledgers and whether the old code understands them. Do not roll back by overwriting the database or deleting ledger history. During a sustained metering failure, restrict new media admission, preserve data, repair reporting and reconcile confirmed receipts before admitting new unaccountable usage.
