The Recordings section covers the API endpoints used to create, run, monitor, and manage file-based recording jobs in Callaba Engine. This is the layer you use when one live input should be captured to disk as a durable archive, segmented recording, or output-format-specific file workflow.
Compared with Restreams, a recording job ends in stored media rather than another live destination. It still uses a live input pipeline, optional transcoding, optional audio or video modifications, and overlay controls, but the end goal is much more practical: produce the right files, in the right format, on the right schedule.
The operational methods matter because recording is rarely just “save a config and forget it.” Teams need to start and stop capture on time, inspect which files were actually produced, remove the wrong file without deleting the whole job, and check progress when a running recorder is part of a real event.
This module is useful both for setup and for operations. In practice, teams care about whether recording is active, whether the live signal still looks healthy, and whether the expected files are actually being produced while the event is in progress.
If your team starts and stops recording jobs from a live operator position, the create, start, and stop examples below also include ready-to-adapt vMix Script tabs.
When a recording job is fed from an SRT contribution, teams often want one fast visual check before digging into the full job object: is the live source still moving, is bitrate present, and does buffering still look healthy.
The compact demo below reuses the same live SRT statistics stream we expose elsewhere in the docs. It is most helpful when a recording depends on a live SRT contribution and you want a quick operational read before or alongside getStat.
This demo shows the kind of live statistics you can watch during a real contribution: bitrate, buffer delay, packet flow, receive capacity, and active streams. It is connected to the public demo endpoint at demo.callaba.io and updates from the same live event stream used by the product.
The most useful presets for this module are recording workflows rather than transport families alone: one continuous archive, one segmented archive, or one output format selected for playback and storage needs.
These examples keep the input on SRT Stream URL (srt://) for clarity, but the same recording object is also used in the product for SRT server, RTMP server, video call room or participant, and URL-based sources such as HLS, MPEG-DASH, RTSP, RTP, UDP, and RIST.
{
"recording_name": "Main program archive",
"recording_type": "RECORDING_STREAM_TO_FILE",
"input": {
"input_type": "INPUT_TYPE_SRT_URL",
"application": "IO_APPLICATION_FFMPEG",
"input_stream_url": "srt://127.0.0.1:1935",
"input_stream_listen_port": {},
"input_settings": {},
"input_module_id": "",
"input_stream_id": "",
"entity_name": "Main program archive",
"module_name": "MODULE_RECORDINGS"
},
"output_format": "mp4",
"recording_mode": "RECORDING_MODE_INFINITY",
"recording_mode_settings": {
"hours": 0,
"minutes": 0,
"seconds": 0
},
"transcoding": {
"video_transcoding": "Disabled",
"output_video_bitrate": 6000,
"preset": "ultrafast",
"tune": "Disabled",
"crf": "Disabled",
"pix_fmt": "Disabled",
"encoding_rate": "",
"filter_fps": "",
"gop": "Disabled",
"force_key_frames": 2,
"frame_width": "",
"frame_height": "",
"slices": "",
"cores": "",
"xlnx_hwdev": "0",
"audio_transcoding": "aac",
"output_audio_bitrate": 128,
"sample_rate": 44100
},
"modify_audio": {
"type": "DISABLED",
"channel": "1,2",
"track": "0"
},
"modify_video": {
"type": "DISABLED"
},
"overlay": {
"type": "DISABLED",
"position": {
"x": 1,
"y": 1
}
},
"delete_after": 0,
"active": true
}
{
"recording_name": "Program segments every 10 minutes",
"recording_type": "RECORDING_STREAM_TO_FILE",
"input": {
"input_type": "INPUT_TYPE_SRT_URL",
"application": "IO_APPLICATION_FFMPEG",
"input_stream_url": "srt://127.0.0.1:1935",
"input_stream_listen_port": {},
"input_settings": {},
"input_module_id": "",
"input_stream_id": "",
"entity_name": "Program segments every 10 minutes",
"module_name": "MODULE_RECORDINGS"
},
"output_format": "mp4",
"recording_mode": "RECORDING_MODE_SPLIT_BY_TIME",
"recording_mode_settings": {
"hours": 0,
"minutes": 10,
"seconds": 0
},
"transcoding": {
"video_transcoding": "Disabled",
"output_video_bitrate": 6000,
"preset": "ultrafast",
"tune": "Disabled",
"crf": "Disabled",
"pix_fmt": "Disabled",
"encoding_rate": "",
"filter_fps": "",
"gop": "Disabled",
"force_key_frames": 2,
"frame_width": "",
"frame_height": "",
"slices": "",
"cores": "",
"xlnx_hwdev": "0",
"audio_transcoding": "aac",
"output_audio_bitrate": 128,
"sample_rate": 44100
},
"modify_audio": {
"type": "DISABLED",
"channel": "1,2",
"track": "0"
},
"modify_video": {
"type": "DISABLED"
},
"overlay": {
"type": "DISABLED",
"position": {
"x": 1,
"y": 1
}
},
"delete_after": 0,
"active": true
}
{
"recording_name": "HLS archive output",
"recording_type": "RECORDING_STREAM_TO_FILE",
"input": {
"input_type": "INPUT_TYPE_SRT_URL",
"application": "IO_APPLICATION_FFMPEG",
"input_stream_url": "srt://127.0.0.1:1935",
"input_stream_listen_port": {},
"input_settings": {},
"input_module_id": "",
"input_stream_id": "",
"entity_name": "HLS archive output",
"module_name": "MODULE_RECORDINGS"
},
"output_format": "m3u8",
"recording_mode": "RECORDING_MODE_INFINITY",
"recording_mode_settings": {
"hours": 0,
"minutes": 0,
"seconds": 0
},
"transcoding": {
"video_transcoding": "Disabled",
"output_video_bitrate": 6000,
"preset": "ultrafast",
"tune": "Disabled",
"crf": "Disabled",
"pix_fmt": "Disabled",
"encoding_rate": "",
"filter_fps": "",
"gop": "Disabled",
"force_key_frames": 2,
"frame_width": "",
"frame_height": "",
"slices": "",
"cores": "",
"xlnx_hwdev": "0",
"audio_transcoding": "aac",
"output_audio_bitrate": 128,
"sample_rate": 44100
},
"modify_audio": {
"type": "DISABLED",
"channel": "1,2",
"track": "0"
},
"modify_video": {
"type": "DISABLED"
},
"overlay": {
"type": "DISABLED",
"position": {
"x": 1,
"y": 1
}
},
"delete_after": 0,
"active": true
}
These scenarios frame why a recording job exists in a production design, not only how the request body is shaped.
Create a recording when the main goal is to preserve a source stream as a file rather than forward it to another live destination.
Recording mode changes the way files are produced. Some workflows need one continuous file, while others need predictable time-based segments for storage, post-production, or downstream automation.
recording_mode, recording_mode_settings, and output_formatThis matters in production because some teams need one continuous archive while others need predictable clip boundaries they can review, move, or publish quickly after the event.
The module is not only about creating files. It also has lifecycle controls and file cleanup actions through start, stop, getStat, and removeFile.
That same workflow also includes auto deletion after N days and a product-facing seamless recording feature for maintaining one continuous recording even when a source is interrupted and resumed.
Creates a new recording job in Callaba Engine.
This method creates one managed recording job. In practice, that means choosing the live source, the file shape you need at the end, and the recording behavior that fits the event you are trying to capture.
The payload is intentionally broad because recording decisions are rarely just about starting capture. Teams also decide file format, clip strategy, optional processing, and how much they want the stored output shaped before it lands.
The key production decisions here are easy to state even if the payload is large: what file should come out, whether capture should run continuously or in clips, and how long the result should stay around afterward.
Although the examples below keep the source on SRT Stream URL (srt://) for readability, the same method also supports product-facing inputs such as SRT server, RTMP server, video call room or participant, and URL-driven inputs like HLS, MPEG-DASH, RTSP, RTP, UDP, and RIST.
Authentication uses the dashboard-issued JWT token in the x-access-token header.
The examples below are grouped by recording presets rather than by one oversized payload. That makes them easier to reuse for real archive and capture workflows.
Use a recording job when the destination should be stored media, not another live endpoint.
Restreams or a stable ingest boundary like SRT servers.Once the job is running, operators usually care about three things first: whether recording is active, what bitrate and FPS the process is reporting, and how many files have already been produced.
Use this preset when the main goal is one stable archive file from a live SRT contribution.
This is the most common recording shape: preserve the incoming stream as one continuous archive and keep the processing layer minimal.
curl --request POST \--url http://localhost/api/recording/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": {"input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"},"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true}'
Use this preset when long captures should be cut into predictable time windows for storage, automation, or post-production.
The recording mode changes from one continuous file to rolling segments while keeping the rest of the capture pipeline largely the same.
curl --request POST \--url http://localhost/api/recording/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"recording_name": "Program segments every 10 minutes","recording_type": "RECORDING_STREAM_TO_FILE","input": {"input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Program segments every 10 minutes","module_name": "MODULE_RECORDINGS"},"output_format": "mp4","recording_mode": "RECORDING_MODE_SPLIT_BY_TIME","recording_mode_settings": {"hours": 0,"minutes": 10,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true}'
Use this preset when the output side should be written as HLS-style media instead of one classic archive container.
This is useful when the stored output format matters for later playback or downstream delivery tooling.
curl --request POST \--url http://localhost/api/recording/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"recording_name": "HLS archive output","recording_type": "RECORDING_STREAM_TO_FILE","input": {"input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "HLS archive output","module_name": "MODULE_RECORDINGS"},"output_format": "m3u8","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true}'
Dashboard label: Name.
Human-readable job name. The dashboard validates this as a required field and uses the same character guidance shown in the UI: A-Z, a-z, 0-9, and -.
The current recording flow uses RECORDING_STREAM_TO_FILE.
Input definition built from the source form. It determines which live source is being captured.
Dashboard label: Output format.
Real product options include mp4, avi, flv, mp3, m3u8, mpegts, and mkv, depending on the selected input protocol.
Dashboard label: Auto Clip Mode.
Controls whether the recorder writes one continuous file or splits output by time. The real modes are RECORDING_MODE_INFINITY and RECORDING_MODE_SPLIT_BY_TIME.
Used with split-by-time mode. The dashboard sends hours, minutes, and seconds, and presents this as a drag-and-drop timing control.
Optional transcoding profile for the FFmpeg worker. The dashboard still sends this block when transcoding is disabled.
Optional audio modification settings. Disabled-state objects are still part of the normal payload shape.
Optional video modification settings.
Optional overlay settings for branded or annotated recordings.
Dashboard label: Auto deletion after.
Optional auto-deletion horizon in days. 0 means no automatic deletion, and the default UI guidance keeps 0 as the normal disabled state.
Dashboard label: Enable once created.
Controls whether the recording worker should be active after provisioning.
curl --request POST \--url http://localhost/api/recording/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": {"input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"},"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true}'
Mongo-style identifier of the recording job.
Convenience alias for _id.
Name stored for the recording job.
Recording type returned by the backend.
Linked input object or objects used by the capture pipeline.
Stored output format for the recording.
Recording mode and any split-by-time settings stored on the job object.
Processing settings attached to the recording job.
Recorded files already linked to the job. This becomes especially important for finished or segmented captures.
Auto-deletion setting in days.
Current running-state flag for the recording job.
Timestamps managed by the backend.
The model exposes success: true as a virtual field in successful responses.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T12:00:00.000Z","success": true}
Returns the number of recording jobs visible to the authenticated user.
This is the lightweight companion to getAll when the dashboard or your integration needs pagination, list counters, or filtered archive counts.
curl --request POST \--url http://localhost/api/recording/getCount \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{}'
Total number of recording jobs currently visible to the authenticated user.
{"count": 1}
Returns the list of recording jobs visible to the authenticated user.
The backend populates related recordedFiles, so this method is useful when you need a list view that includes the file lifecycle rather than only job ids and names.
This is the natural companion to the dashboard listing, where teams scan job name, current live bitrate, current FPS, creation time, and the number of files already attached to each recording.
Optional page size for the list query.
Optional offset for paginated listing.
Optional sort descriptor. The dashboard store defaults to { created: 1 }.
Optional filter object forwarded to the backend query.
curl --request POST \--url http://localhost/api/recording/getAll \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"limit": 10,"skip": 0,"sort": {"created": 1},"filter": {}}'
The backend returns a bare array of recording jobs, not a wrapped object.
[{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T12:00:00.000Z","success": true}]
Returns one recording job with its linked input object and recorded files populated.
This is the method to use when you need the fully expanded job shape before editing, troubleshooting, or cleaning up one file from the recording output.
Identifier of the recording job you want to load.
curl --request POST \--url http://localhost/api/recording/getById \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "66004d2997300f9385d32b00"}'
The backend returns the populated recording job object with linked input and recorded files.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T12:00:00.000Z","success": true}
Updates an existing recording job by id.
The backend reuses the same validation path as create, so the update payload mirrors the create payload with the addition of id.
Identifier of the recording job being updated.
The update contract mirrors create and reuses the same validation plus worker-regeneration path.
curl --request POST \--url http://localhost/api/recording/update \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"recording_name": "Main program archive updated","recording_type": "RECORDING_STREAM_TO_FILE","input": {"input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"},"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": false,"id": "66004d2997300f9385d32b00"}'
The backend returns the updated job object together with success: true.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive updated","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": false,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T13:00:00.000Z","success": true}
Starts a recording job by id.
The service marks the job as active, stops any previous worker for the same recording id, and then runs the recording pipeline again using the current input, format, and processing configuration.
Identifier of the recording job to start.
curl --request POST \--url http://localhost/api/recording/start \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "66004d2997300f9385d32b00"}'
The backend marks the job as active and returns the recording object.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T12:00:00.000Z","success": true}
Stops a recording job by id.
The backend marks the job as inactive and stops the running recording worker. This is the operational counterpart to start.
Identifier of the recording job to stop.
curl --request POST \--url http://localhost/api/recording/stop \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "66004d2997300f9385d32b00"}'
The backend marks the job as inactive and returns the recording object.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": false,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T13:10:00.000Z","success": true}
Removes a recording job by id.
This operation also stops the worker, removes the linked input object, and deletes the files produced by the recording process.
Identifier of the recording job to delete.
curl --request DELETE \--url http://localhost/api/recording/remove \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "66004d2997300f9385d32b00"}'
The backend stops the worker, removes linked input and file records, and returns the previously loaded recording object.
{"_id": "66004d2997300f9385d32b00","id": "66004d2997300f9385d32b00","recording_name": "Main program archive","recording_type": "RECORDING_STREAM_TO_FILE","input": [{"_id": "66004d2997300f9385d32b01","id": "66004d2997300f9385d32b01","input_type": "INPUT_TYPE_SRT_URL","application": "IO_APPLICATION_FFMPEG","input_stream_url": "srt://127.0.0.1:1935","input_stream_listen_port": {},"input_settings": {},"input_module_id": "","input_stream_id": "","entity_name": "Main program archive","module_name": "MODULE_RECORDINGS"}],"output_format": "mp4","recording_mode": "RECORDING_MODE_INFINITY","recording_mode_settings": {"hours": 0,"minutes": 0,"seconds": 0},"transcoding": {"video_transcoding": "Disabled","output_video_bitrate": 6000,"preset": "ultrafast","tune": "Disabled","crf": "Disabled","pix_fmt": "Disabled","encoding_rate": "","filter_fps": "","gop": "Disabled","force_key_frames": 2,"frame_width": "","frame_height": "","slices": "","cores": "","xlnx_hwdev": "0","audio_transcoding": "aac","output_audio_bitrate": 128,"sample_rate": 44100},"modify_audio": {"type": "DISABLED","channel": "1,2","track": "0"},"modify_video": {"type": "DISABLED"},"overlay": {"type": "DISABLED","position": {"x": 1,"y": 1}},"delete_after": 0,"active": true,"recordedFiles": [{"_id": "66004d2997300f9385d32b10","id": "66004d2997300f9385d32b10","file_name": "main-program-archive-2026-03-24_12-00-00.mp4","file_path": "/recordings/main-program-archive-2026-03-24_12-00-00.mp4","module_name": "MODULE_RECORDINGS","file_visibility": "FILE_VISIBILITY_PUBLIC","output_format": "mp4","entity_name": "Main program archive","entity_id": "66004d2997300f9385d32b00","size_bytes": 184320000,"duration_ms": 1800000,"created": "2026-03-24T12:30:00.000Z"}],"created": "2026-03-24T12:00:00.000Z","modified": "2026-03-24T12:00:00.000Z","success": true}
Removes one recorded file from a recording job.
Use this when you want to keep the recording job itself but delete a specific file that was produced by it.
Identifier of the parent recording job.
Identifier of the recorded file that should be deleted.
curl --request POST \--url http://localhost/api/recording/removeFile \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"record_id": "66004d2997300f9385d32b00","file_id": "66004d2997300f9385d32b10"}'
The backend returns { success: true } when the file was removed from storage and detached from the recording job.
{"success": true}
Returns current process statistics for active recording jobs.
The dashboard uses this method to poll live FFmpeg progress data every 3 seconds. Depending on the worker state, the response can include fields such as bitrate, bitrate_kbits, fps, out_time_ms, speed, and progress.
In practice, this is the method behind the operator-facing live recording indicators: current bitrate, current FPS, and whether the worker is still progressing through output time as expected.
curl --request POST \--url http://localhost/api/recording/getStat \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{}'
Current per-process statistics used by the dashboard polling layer.
Current FFmpeg-reported bitrate and a normalized integer bitrate_kbits field.
Current frames-per-second progress value when FFmpeg reports it.
Current processed output time in milliseconds.
Current FFmpeg processing speed, for example 1.00x.
FFmpeg progress status such as continue or end.
[{"processData": {"id": "66004d2997300f9385d32b00","frame": "1532","fps": "25.0","bitrate": "1842.1kbits/s","bitrate_kbits": 1842,"total_size": "414832640","out_time_ms": "61200000","speed": "1.00x","progress": "continue"}}]