Skip to content

MP4 Recording Plugin

The MP4 plugin provides media stream recording and video-on-demand (VOD) playback. It supports both standard MP4 and fMP4 (Fragmented MP4) formats, allows controlling recording start/stop via HTTP API, and includes built-in auto-cleanup and corruption recovery mechanisms.

Set enable: true in config.yaml (included in official binaries).

Configure the MP4 plugin in config.yaml:

mp4:
enable: true
record_path: "./recordings" # Recording file storage directory
fragment: false # Enable fMP4 format
fragment_duration: 5 # fMP4 fragment duration (seconds)
max_file_size: 0 # Maximum file size in bytes (0 = unlimited)
max_duration: 0 # Maximum recording duration in seconds (0 = unlimited)
before_duration: 10 # Event recording: pre-event buffer duration (seconds)
after_duration: 10 # Event recording: post-event continuation duration (seconds)
expire_days: 0 # Auto-delete recordings older than N days (0 = no deletion)
disk_max_percent: 0 # Maximum disk usage percentage (0 = unlimited)
auto_recovery: true # Auto-recover corrupted recording files
filename_pattern: "{stream}_{date}_{time}.mp4" # File naming template

filename_pattern supports the following variables:

VariableDescriptionExample
{stream}Stream path (/ replaced with _)live_camera01
{date}Date20260318
{time}Time143025
{timestamp}Unix timestamp1742291425

All endpoints are mounted under the /mp4/ route prefix.

POST /mp4/start/{stream_path}

Start recording the specified stream. Returns already_recording status if the stream is already being recorded.

Request example:

Terminal window
curl -X POST http://localhost:8180/mp4/start/live/camera01

Response example:

{
"status": "started",
"stream": "live/camera01"
}
POST /mp4/stop/{stream_path}

Stop recording the specified stream. The recording file is automatically written to disk and (if a database is configured) metadata is saved to the database.

Request example:

Terminal window
curl -X POST http://localhost:8180/mp4/stop/live/camera01

Response example:

{
"status": "stopped",
"stream": "live/camera01"
}
GET /mp4/status/{stream_path}

Query whether the specified stream is currently being recorded.

Response example:

{
"stream": "live/camera01",
"recording": true
}
GET /mp4/list

Returns all currently active recording tasks.

Response example:

{
"recordings": ["live/camera01", "live/camera02"],
"count": 2
}
GET /mp4/records

Query the list of completed recordings (requires database support).

Response example:

{
"status": "success",
"records": [],
"count": 0
}
GET /mp4/vod

List available MP4 files for on-demand playback.

GET /mp4/vod/{filename}

Play a specific MP4 recording file directly. Responds with Content-Type: video/mp4 and supports Accept-Ranges header for resumable downloads.

Request example:

Terminal window
curl http://localhost:8180/mp4/vod/live_camera01_20260318_143025.mp4 -o output.mp4
GET /mp4/

Returns plugin version and list of available endpoints.

Default base URL: http://localhost:8180

POST /mp4/start/{streamPath}
ParameterLocationTypeRequiredDescription
streamPathpathstringYesStream path, e.g. live/camera01

Success response:

{
"status": "started",
"stream": "live/camera01"
}
POST /mp4/stop/{streamPath}
ParameterLocationTypeRequiredDescription
streamPathpathstringYesTarget stream path

Success response:

{
"status": "stopped",
"stream": "live/camera01"
}
GET /mp4/status/{streamPath}

Success response:

{
"stream": "live/camera01",
"recording": true
}
GET /mp4/list

Success response:

{
"recordings": ["live/camera01", "live/camera02"],
"count": 2
}
GET /mp4/config

Success response (example):

{
"enable": true,
"record_path": "./recordings",
"fragment": false,
"fragment_duration": 5,
"expire_days": 0
}
GET /mp4/api/list/{streamPath}

Success response (example):

{
"stream_path": "live/camera01",
"files": [
{
"name": "live_camera01_20260318_143025.mp4",
"size": 104857600,
"created_at": "2026-03-18T14:30:25Z"
}
],
"count": 1
}
GET /mp4/api/catalog

Success response (example):

{
"roots": ["./recordings"],
"total_files": 128
}
DELETE /mp4/api/delete/{streamPath}

Success response (example):

{
"deleted": true,
"stream_path": "live/camera01"
}
GET /mp4/download/{streamPath}

Returns video/mp4 binary stream with Range support.

HTTP StatusScenario
400Missing/invalid path parameter
404Recording file or stream not found
409State conflict (e.g. duplicate start)
500FFmpeg/IO/internal error

When expire_days or disk_max_percent is configured, the MP4 plugin automatically runs a cleanup task every hour:

  • Expiration-based: Deletes recording files older than expire_days days
  • Disk usage-based: When disk usage exceeds disk_max_percent, deletes recording files from oldest to newest

The MP4 plugin obtains DatabaseApi through EngineContext, supporting persistence of recording metadata (stream path, file path, duration, size, start/end time) to a database. Supports SQLite, MySQL, and PostgreSQL backends.

Combined with the crontab plugin, scheduled recording can be achieved:

crontab:
jobs:
- name: "Daily recording"
cron: "0 8 * * *"
action: "record_start"
stream: "live/camera01"
duration: 28800 # Record for 8 hours