RTSP Simulator

Stream an uploaded video file as a looping RTSP source for testing inference pipelines without a camera.

RTSP Simulator is an edge container service that turns an uploaded video file into a live RTSP stream. Use it to build and test inference pipelines on a device before a physical camera is installed, or to replay a known clip against a Workflow.

You upload an .mp4 file through the web interface or the REST API, the service transcodes it to an RTSP-compatible format, and it publishes the result on a continuous loop until you stop it.

RTSP Simulator is available exclusively for Enterprise customers. Contact the Roboflow sales team to learn more.

Connection Details

Replace <device-ip> with the IP address shown on the device page in Deployment Manager.

PurposeAddress
RTSP streamrtsp://:8554/stream
Web UI, REST API, and Swagger docshttp://:8080
PortProtocolPurpose
8080HTTPWeb UI, REST API, Swagger docs at /docs
8554RTSP (TCP)Video stream output. UDP transport is disabled; clients that prefer UDP negotiate down to TCP-interleaved.

Multiple clients can read the stream at the same time.

Video Format

Only .mp4 files are accepted. Uploads are transcoded automatically so the stream works with any RTSP client:

  • Codec: H.264, Baseline profile
  • Pixel format: yuv420p
  • Audio: stripped, video only
  • Maximum file size: 5 GB by default

Using the Web Interface

Open http://<device-ip>:8080 in a browser.

1

Upload

Drag an .mp4 file onto the page. The file uploads and is converted to the streaming format.

2

Play

Select "Play" to start streaming. The video loops indefinitely and is published to the RTSP server.

3

Connect

Point your inference pipeline, a Deployment Manager stream, or any RTSP client at rtsp://<device-ip>:8554/stream.

4

Stop

Select "Stop" to end the stream and remove the converted files.

To use the simulated stream in a deployment, add it as a stream source on the device the same way you would a camera. See Add a Stream.

Using the CLI

For headless or SSH-only access, the rtsp-cli tool provides an interactive terminal interface on the device.

docker exec -it rtsp-simulator rtsp-cli

To import a video without the web UI, copy it into the input directory first, then launch the CLI and press I.

scp video.mp4 user@<device-ip>:/var/lib/rfdm/rtsp-simulator/data/input/
KeyCommandDescription
IImportSelect and convert a video from /data/input/
PPlayStart RTSP streaming
SStopStop streaming and delete converted files
DDeleteDelete video files
CConfigAdjust stream settings (bitrate, buffer, delay)
RRefreshRefresh the status display
QQuitExit the CLI

Testing the Stream

Connect with any RTSP player to confirm the stream is live.

vlc rtsp://<device-ip>:8554/stream

HTTP API

All endpoints return JSON. Interactive Swagger documentation is served at http://<device-ip>:8080/docs. See Services for the rules shared by all on-device service APIs.

The API is unauthenticated, and it can stop a running stream and delete uploaded video. Anything that can reach port 8080 can do both.

Typical Flow

curl -X POST http://<device-ip>:8080/upload -F "file=@video.mp4"
curl -X POST http://<device-ip>:8080/play
curl http://<device-ip>:8080/status
curl -X POST http://<device-ip>:8080/stop

The rtsp_url returned by /play and /status always names localhost, because the service reports the URL from its own point of view. Only a consumer running on the device can use it verbatim. Anywhere else, substitute the device address: rtsp://<device-ip>:8554/stream.

The port is RTSP_PORT, which defaults to 8554 but is configurable per device. Read rtsp_port from /info rather than assuming the default.

/stop also deletes both the original and converted files to free disk space, so a new upload is required before the next /play.

Upload

Only .mp4 is accepted, and an active stream is stopped before the upload begins. The optional settings part is a JSON string of conversion settings applied during transcoding. Because they are baked into the converted file, changing them later requires re-uploading.

curl -X POST http://<device-ip>:8080/upload \
  -F "file=@video.mp4" \
  -F 'settings={"target_fps": 30, "crf_quality": 23, "max_width": 1920}'

Upload a video file

posthttp://device-ip:8080/upload

Uploads a video and converts it to the RTSP streaming format. Only .mp4 is accepted. An active stream is stopped before the upload begins.

The optional settings part is a JSON string of conversion settings, applied during transcoding. Because they are baked into the converted file, changing them later requires re-uploading.

Bodymultipart/form-data
filestringRequired

Video file to upload. Must be .mp4.

settingsstringOptional

Optional JSON string holding an UploadSettings object. It is a string part rather than a nested object because the service parses it with json.loads before validating, so the UploadSettings schema below documents the shape rather than being referenced here.

Example: {"target_fps": 30, "crf_quality": 23, "max_width": 1920}
Responses
200Upload and conversion succeededapplication/json
successbooleanRequired
messagestringRequired
videoobject · VideoInfoRequired
Show properties
filenamestringRequired

Original filename

sizeintegerRequired

File size in bytes

size_mbnumberRequired

File size in megabytes

extensionstringRequired

File extension

400No file selected, unsupported extension, invalid upload settings, or the file is not a readable videoapplication/json
detailstringRequired

Error message

413File exceeds MAX_FILE_SIZE (5 GB by default)application/json
detailstringRequired

Error message

422Request failed validationapplication/json
detailobject · ValidationError[]Optional

One entry in a request-validation failure.

Show properties
locany[]Required

Path to the offending field, for example ["body", "value"].

msgstringRequired
typestringRequired
500Conversion failedapplication/json
detailstringRequired

Error message

507Not enough free disk space for the uploadapplication/json
detailstringRequired

Error message

post/upload
POST /upload HTTP/1.1
Host: device-ip:8080
Content-Type: multipart/form-data
Accept: application/json

{
  "file": "binary",
  "settings": "{\"target_fps\": 30, \"crf_quality\": 23, \"max_width\": 1920}"
}
200Upload and conversion succeeded
{
  "success": true,
  "message": "Video uploaded successfully",
  "video": {
    "filename": "factory_line.mp4",
    "size": 125000000,
    "size_mb": 119.21,
    "extension": ".mp4"
  }
}

Streaming

Start streaming

posthttp://device-ip:8080/play

Starts publishing the converted video to the RTSP server, looping until stopped. Uses the current stream settings.

Responses
200Streaming startedapplication/json
successbooleanRequired
messagestringRequired
rtsp_urlstringRequired

RTSP stream URL as the service sees it, always naming localhost, on the port set by RTSP_PORT (8554 by default). Consumers off the device must substitute the device address; read rtsp_port from /info rather than assuming 8554.

400Already streaming, or no video has been uploadedapplication/json
detailstringRequired

Error message

500The stream failed to startapplication/json
detailstringRequired

Error message

post/play
POST /play HTTP/1.1
Host: device-ip:8080
Accept: application/json
200Streaming started
{
  "success": true,
  "message": "Streaming started",
  "rtsp_url": "rtsp://localhost:8554/stream"
}

Stop streaming and delete video files

posthttp://device-ip:8080/stop

Stops the stream and deletes both the original and converted files to free disk space. Uploading again is required before the next /play.

Responses
200Streaming stopped and files deletedapplication/json
successbooleanRequired
messagestringRequired
400Not currently streamingapplication/json
detailstringRequired

Error message

500Stop failedapplication/json
detailstringRequired

Error message

post/stop
POST /stop HTTP/1.1
Host: device-ip:8080
Accept: application/json
200Streaming stopped and files deleted
{
  "success": true,
  "message": "text"
}

/delete removes the video files without requiring a stream to be running, stopping one first if it is.

Delete video files

posthttp://device-ip:8080/delete

Deletes the original and converted video files, stopping the stream first if it is running. Unlike /stop, this succeeds whether or not a stream is active.

Responses
200Files deletedapplication/json
successbooleanRequired
messagestringRequired
404No video files found to deleteapplication/json
detailstringRequired

Error message

500Delete failedapplication/json
detailstringRequired

Error message

post/delete
POST /delete HTTP/1.1
Host: device-ip:8080
Accept: application/json
200Files deleted
{
  "success": true,
  "message": "text"
}

Status

streaming is true when components.mediamtx.healthy (the streaming server) and components.ffmpeg_process.running (the transcode and publish process) are both true. The components.stream entry does not gate it: components.stream.source_ready can be false briefly during startup while streaming already reads true, which is normal. The breakdown is the fastest way to localize a failed stream: check components to see which part is unhealthy before restarting anything.

Get streaming status

gethttp://device-ip:8080/status

Returns whether the stream is live, plus the health of each component, which is the fastest way to localize a failure.

streaming is true when components.mediamtx.healthy and components.ffmpeg_process.running are both true; the components.stream entry does not gate it. components.stream.source_ready can be false briefly during startup, which is normal.

Responses
200Current statusapplication/json
streamingbooleanRequired
rtsp_urlstring · nullableOptional

RTSP stream URL as the service sees it, always naming localhost, on the port set by RTSP_PORT (8554 by default). Null when not streaming. Consumers off the device must substitute the device address; read rtsp_port from /info rather than assuming 8554.

videoobject · nullableOptional

Current video, null when nothing is uploaded

Show properties
filenamestringRequired

Original filename

sizeintegerRequired

File size in bytes

size_mbnumberRequired

File size in megabytes

extensionstringRequired

File extension

componentsobject · ComponentStatusRequired
Show properties
mediamtxobject · StreamingServerInfoRequired
Show properties
healthybooleanRequired
errorstring · nullableOptional
ffmpeg_processobject · ProcessInfoRequired
Show properties
existsbooleanRequired

Whether an encoder process record exists

pidinteger · nullableOptional
runningbooleanRequired
exit_codeinteger · nullableOptional

Exit code when the process is no longer running

streamobject · StreamInfoRequired
Show properties
api_availablebooleanRequired

Whether the streaming server's control API is reachable

source_readybooleanRequired

Whether the stream source is ready

readersintegerOptional

Number of clients currently reading the stream

Default: 0
errorstring · nullableOptional
get/status
GET /status HTTP/1.1
Host: device-ip:8080
Accept: application/json
200Current status
{
  "streaming": true,
  "rtsp_url": "rtsp://localhost:8554/stream",
  "video": {
    "filename": "sample.mp4",
    "size": 1048576,
    "size_mb": 1,
    "extension": ".mp4"
  },
  "components": {
    "mediamtx": {
      "healthy": true,
      "error": null
    },
    "ffmpeg_process": {
      "exists": true,
      "pid": 1234,
      "running": true,
      "exit_code": null
    },
    "stream": {
      "api_available": true,
      "source_ready": true,
      "readers": 1,
      "error": null
    }
  }
}

/info reports the limits the service is running with, including free disk space and the maximum upload size, which is worth checking before pushing a large file.

Get system information

gethttp://device-ip:8080/info

Returns disk space, the upload size limit, accepted extensions, and the RTSP port.

Responses
200System informationapplication/json
disk_spaceobject · DiskSpaceRequired
Show properties
totalintegerRequired

Total disk space in bytes

usedintegerRequired

Used disk space in bytes

freeintegerRequired

Free disk space in bytes

free_gbnumberRequired

Free disk space in GB

max_file_sizeintegerRequired

Maximum upload size in bytes, set by MAX_FILE_SIZE

max_file_size_gbnumberRequired
allowed_extensionsstring[]Required

Accepted file extensions. Only .mp4 today.

rtsp_portintegerRequired

Port the RTSP stream is served on, set by RTSP_PORT

get/info
GET /info HTTP/1.1
Host: device-ip:8080
Accept: application/json
200System information
{
  "disk_space": {
    "total": 1,
    "used": 1,
    "free": 1,
    "free_gb": 1
  },
  "max_file_size": 1,
  "max_file_size_gb": 1,
  "allowed_extensions": [
    "text"
  ],
  "rtsp_port": 1
}

Stream Settings Endpoints

Playback settings differ from upload settings: they apply at streaming time and can be changed between sessions without re-uploading. An update takes effect on the next /play, not the stream currently running.

Get stream settings

gethttp://device-ip:8080/stream-settings

Returns the current playback settings.

Responses
200Current settingsapplication/json
max_bitrate_kbpsintegerOptional

Maximum bitrate in kbps

Default: 5000
buffer_size_kbintegerOptional

Buffer size in KB

Default: 3000
max_delay_msintegerOptional

Maximum delay in milliseconds

Default: 500
get/stream-settings
GET /stream-settings HTTP/1.1
Host: device-ip:8080
Accept: application/json
200Current settings
{
  "max_bitrate_kbps": 5000,
  "buffer_size_kb": 3000,
  "max_delay_ms": 500
}

Update stream settings

posthttp://device-ip:8080/stream-settings

Persists new playback settings. They apply to the next streaming session, not the one currently running.

Bodyapplication/json
max_bitrate_kbpsintegerOptional

Maximum bitrate in kbps

Default: 5000
buffer_size_kbintegerOptional

Buffer size in KB

Default: 3000
max_delay_msintegerOptional

Maximum delay in milliseconds

Default: 500
Responses
200Settings savedapplication/json
successbooleanRequired
messagestringRequired
422Request failed validationapplication/json
detailobject · ValidationError[]Optional

One entry in a request-validation failure.

Show properties
locany[]Required

Path to the offending field, for example ["body", "value"].

msgstringRequired
typestringRequired
500Failed to persist settingsapplication/json
detailstringRequired

Error message

post/stream-settings
POST /stream-settings HTTP/1.1
Host: device-ip:8080
Content-Type: application/json
Accept: application/json

{
  "max_bitrate_kbps": 5000,
  "buffer_size_kb": 3000,
  "max_delay_ms": 500
}
200Settings saved
{
  "success": true,
  "message": "text"
}

Configuration

Environment Variables

Set these on the service in the device's Configuration tab. See Update Device Configuration.

VariableDefaultDescription
MAX_FILE_SIZE5368709120Maximum upload size in bytes (5 GB)
RTSP_PORT8554RTSP server port
WEB_PORT8080Web UI and API port
LOG_LEVELINFOLogging verbosity: DEBUG, INFO, WARNING, or ERROR

Upload Settings

These are applied during conversion, so changing them requires re-uploading the video.

SettingDefaultDescription
target_fpsoriginalTarget frame rate, 1 to 120. Omit to keep the original
crf_quality23Quality level, 0 to 51 (18 is high, 23 is medium, 28 is low)
max_widthoriginalMaximum width for downscaling, 320 to 7680. Omit to keep the original

Stream Settings

These are applied at playback and can be changed between streaming sessions from the CLI config menu or the /stream-settings endpoint.

SettingDefaultDescription
max_bitrate_kbps5000Maximum bitrate in kbps, 100 to 100,000
buffer_size_kb3000Buffer size in KB, 100 to 50,000
max_delay_ms500Maximum delay in milliseconds, 50 to 5,000