Python_Virtual_Motion-JPEG_Camera_Simulator

                 565        0          English  简体中文  繁体中文  Tiếng Việt 

Project Design Purpose : This project is designed to create a lightweight, extensible camera-simulation service program that exposes a Motion-JPEG (MJPEG) video stream over HTTP(s) via a Flask web interface for using in the cyber ranges, red/blue exercises, and research where realistic camera endpoints are required without physical hardware.

The simulated video stream can be generated from five different type of source:

  • Local physical camera (embedded webcam or USB camera).
  • External live stream (RTSP/HTTP source).
  • Static or rotating image dataset (images loaded from a directory).
  • OS Screen Recording (full or partial screen screenshot).
  • Application-window capture (Windows-only; capture a running app window).

The simulator intentionally mimics the web UI and behavior of Axis IP cameras so it can also be deployed as a believable camera honeypot or as a drop-in replacement for testing and integration.

# Author:      Yuancheng Liu
# Created:     2025/10/15 
# version:     v_0.0.5
# Copyright:   Copyright (c) 2025 LiuYuancheng
# License:     GNU General Public License V3

Introduction

The IoT/IP cameras are one of the critical sensors in modern IT/OT systems— used for surveillance, safety monitoring, and operational visibility. In digital-twin and simulation environments (where MU, PLCs, RTUs and even physical-world entities like trains or runway lights are modeled in software), realistic camera endpoints are often missing. The Python Virtual Motion-JPEG Camera Simulator is designed for filling that gap by producing believable MJPEG camera streams that can be integrated into the digital twins, cyber ranges, monitoring dashboards, and deception/honeypot deployments.

This project provides a lightweight, portable simulator that can run in VMs or containers and expose MJPEG streams over HTTP(s) with an Axis-style web UI. The system workflow diagram is shown below:

Figure-01: System Workflow Diagram, version v_0.0.3 (2025)

The video streams can be generated by live devices, prerecorded datasets, or on-host captures so the simulator can present contextually appropriate video — for example, showing a landing aircraft on a simulated runway camera when the digital twin indicates a plane is on final approach.

Architecture Overview

The system contents three main components as shown in the below architecture diagram:

Figure-02: System Architecture Diagram, version v_0.0.3 (2025)

  • Virtual Camera Client Library : Converts a variety of video/image sources into a Motion-JPEG (MJPEG) stream with configurable FPS and resolution. Supported sources: local webcams/USB cameras, RTSP/HTTP streams, image datasets, desktop screenshots (full/partial), and application-window captures (Windows only).

  • Flask Camera Server : A management web application that mimics Axis-style camera pages. It exposes camera configuration, stream endpoints, user controls, and logs — making the simulator usable both as a realistic test camera and as a convincing honeypot UI.

  • Multi-Camera View Monitor Dashboard : A dashboard program aggregates multiple virtual camera feeds into a single multi-frame view for monitoring or projection on command-center.

System Design

This section introduces the detailed design and internal structure of the three major components of the system introduced in the Introduction[Architecture Overview] section.

Design of Virtual Camera Client Library

The Virtual Camera Client Library is responsible for transforming various video sources into continuous MJPEG streams that can be served to browsers or other applications. The core of this module is the base class camClient, which defines the streaming pipeline consisting of five main steps:

Step 1: Frame Capture from Source

  • Each subclass implements the camClient interface function getOneFrame() to retrieve one OpenCV (cv2) image frames from its assigned video source. This function ensures consistent frame objects across all source types.

Step 2: Image JPEG Encoding

  • Each captured frame is compressed into JPEG format to reduce bandwidth and enable efficient streaming :

  • _, buffer = cv2.imencode('.jpg', frame)

Step 3: Return HTTP Streaming

  • The Flask generator continuously yields each encoded JPEG frame to the HTTP response stream :

  • yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + buffer.tobytes() + b'\r\n')

Step 4: Multipart MJPEG Response

  • The HTTP response is sent using the MIME type multipart/x-mixed-replace, allowing browsers to interpret it as a continuous stream of JPEG images :

  • mimetype='multipart/x-mixed-replace; boundary=frame'

Step 5: Browser Renders Live Stream

  • In the browser’s <img> element, encodes each incoming JPEG frame in order and displays them — visually creating a video :

  • <img src="{{ url_for('video_feed') }}" width="900" height="500">

Class Structure and Source Inheritance

The camClient base class is extended by several specialized subclasses that handle different input sources:

Figure-04: Class Structure Diagram, version v_0.0.3 (2025)

Each subclass manages its own capture logic while maintaining a unified streaming interface for the Flask server and dashboards.

Design of Flask Camera Server

The Flask Camera Server is a web host providing user interfaces, video live view, configuration options, and API endpoints for video streaming. It also supports secure access control and linkage with physical-world simulation data in cyber range or digital twin environments. The Flask server’s operational flow / structure is shown below:

Figure-04: Flask Server Workflow Diagram, version v_0.0.3 (2025)

The four modules function detail includes:

  • Video Source Manager Module : The wrapper module imports and Integrates with the Virtual Camera Client Library to manage frame capture from multiple video sources.

  • User and Access Management Module : Handles authentication and authorization, linked to a credential database to manage user logins and MJPEG fetching API access permissions.

  • Data Manager Module : The data manager module interfaces with the cyber range’s physical-world simulator to map operational states (e.g., aircraft position, train movement) to appropriate camera video display feed frames.

  • Flash Web Service Module : The main web service module open a configurable port to handle all the http/https requests.

The Flask-based web server provides four main pages for users as shown below :

[1] Camera Home Page

The default landing page when the user access the camera simulator IP address, prompting user login with valid credentials before accessing the camera system :

Figure-05: IP Camera Home Page Screenshot, version v_0.0.3 (2025)

[2] Camera Video Live View Page

After the user login with the correct credentials, they can access the pages displays the current live MJPEG stream. Users can adjust frame resolution and FPS in real time from the page:

Figure-06: Camera Video Live View Page Screenshot, version v_0.0.3 (2025)

[3] User Configuration Page

Allows different types of user to manage and change the access credential. The current version provides 2 type of users:

  • Normal users can only view the live stream and change their own password.

  • Admin users can add/delete users, reset / check passwords, and manage MJPEG API tokens.

Figure-07: User Configuration Page Screenshot, version v_0.0.3 (2025)

[4] Access Token Configuration Page

Used for generating and managing MJPEG API access tokens for external applications. For other program which use the motion-JPEG API to fetch the frame, a valid access token is required when calling the API url. Only the admin user can access the API token configuration page as shown below:

Figure-08: Access Token Configuration Page Screenshot, version v_0.0.3 (2025)

There are 2 types of API access tokens:

  • Fixed Token : The fixed token is pre-configured in the camera local data base and there is no usage limitation. The Fixed token will not lose if we reboot the camera simulator program.

  • Temporary Token : The temporary tokens are saved in the camera's memory, every time when the admin press the button "Generate a random token", the camera simulator will generate a 16 characters temporary token. The admin can also set the valid period of the temporary token. All the temporary tokens will be lose when the camera simulator is rebooted.

The user access rule and available function are shown in the below table:

Function\User Admin User Normal User
Access the user management page
Change own password
Change and check other user's password
Add and remove normal user
Create new admin user
Remove exist admin user
Access the motion-JPEG token management page
View the fixed and temporary API token
Generate, modify and delete the temporary API token

Design of Multi-Camera View Monitor Dashboard

The Multi-Camera View Monitor Dashboard aggregates multiple virtual camera streams into one unified monitoring interface. It fetches MJPEG video feeds through HTTP API calls and displays them in a configurable multi-view layout. The network topology and configuration of the camera simulators and the dashboard is shown below:

Figure-09: Monitor Dashboard Network Diagram, version v_0.0.3 (2025)

The display dashboard feature includes:

  • Supports simultaneous monitoring of multiple MJPEG feeds.

  • Configurable grid layout (e.g., 2x2, 3x3) for custom display setups.

  • Adjustable stream FPS and resolution for performance tuning.

  • Allows multiple dashboards to subscribe to the same camera stream

Dashboard's Camera Access Configuration File

Each camera feed is defined in a JSON configuration file. Below is an example to add a new camera into the dashboard:

    "Desktop1": {
        "name": "Desktop screenshot 1 virtual Camera",
        "url": "http://127.0.0.1:5000/cgi-bin/mjpg/",
        "token": "motionJPEG",
        "size": [
            640,
            480
        ]
    },    

The dashboard supports flexible layout configuration, adjustable FPS, and can display multiple camera streams in a single window or across multiple displays.

System Configuration and Usage

Development Environment : Python 3.7.4+

Project file list and module function description

Virtual Camera Client Library

Program File Execution Env Description
src/lib/virtualCamera.py python 3 Virtual camera lib module
src/lib/virtualCameraTest.py + templates python 3 + HTML Virtual camera lib test case module

Flask Camera Server

Program File Execution Env Description
src/VirtualCam/static/* CSS, JS,Image All the web CSS, JavaScript and image
src/VirtualCam/templates/* HTML All the html pages of the web.
src/VirtualCam/Config_templat.txt   The configuration template file for user to build own config file.
src/VirtualCam/users_template.json JSON The user credential data base file template.
src/VirtualCam/webCamGlobal.py python 3 Global parameter module.
src/VirtualCam/webCamDataMgr.py python 3 Optional module to linked to the cyber range physical world simulation module.
src/VirtualCam/webCamAuth.py python 3 Flask user authorization module.
src/VirtualCam/webCamApp.py python 3 Main Flask web host execution module.

Multi-Camera View Monitor Dashboard

Program File Execution Env Description
src/MultiCamViewDashboard/camDashboardConfig_template.txt   Dashboard configuration template file.
src/MultiCamViewDashboard/camDashboardDataMgr.py python 3 Sub-thread module to fetch MJPEG image from all cameras
src/MultiCamViewDashboard/camDashboardGlobal.py python 3 Global parameter module.
src/MultiCamViewDashboard/camDashboardPanel.py python 3 Dashboard display panel module.
src/MultiCamViewDashboard/cameraConfig_template.json JSON Camera access configuration file template.
src/MultiCamViewDashboard/camDashboardRun.py python 3 Dashboard main execution module.

System Pre-Setup

Before configure the system, install the additional lib/software in the below table:

Lib Module Version Installation Lib link
Flask 1.1.2 pip install Flask https://flask.palletsprojects.com/en/stable/
Flask_Login 0.6.2 pip install Flask-Login https://pypi.org/project/Flask-Login/
numpy 1.21.6 pip install numpy https://pypi.org/project/numpy/
opencv_python 4.5.1.48 pip install opencv-python https://pypi.org/project/opencv-python/
PyAutoGUI 0.9.53 pip install PyAutoGUI https://pyautogui.readthedocs.io/en/latest/
pywin32 305 pip install pywin32 https://pypi.org/project/pywin32/
requests 2.28.1 pip install requests https://pypi.org/project/requests/
win32gui 221.6 pip install win32gui https://pypi.org/project/win32gui/
wxPython 4.1.0 pip install wxPython https://pypi.org/project/wxPython/

Usage of Virtual Camera

Work Folder : src/VirtualCam

Step 1: Setup the web configuration file.

Rename the configuration file template Config_template.txt to Config.txt and set the parameter as shown below :

# This is the config file template for the module <webCamApp.py>
# Setup the parameter with below format (every line follows <key>:<val> format, the
# key can not be changed):
#-----------------------------------------------------------------------------
# Camera mode flag, 
CAM_MD:2
#-----------------------------------------------------------------------------
# Camera Admin user config and user record file. 
USERS_RCD:users.json
#-----------------------------------------------------------------------------
# Define physical world simulator IP
RW_IP:127.0.0.1
# Define physical world simulator connection port
RW_PORT:3001
RW_REFRESH_TIME:1
# Physical world reconnection time 
RW_RECONN_TIME:10
#-----------------------------------------------------------------------------
# Camera video source parameter:
# Simulated camera report to RW ID:
CAM_ID:RW_CAM_REAL
# Physical camera ID
CAM_IDX:0
CAM_FPS:6
# Simulated camera data set parameters:
CAM_DATA_DIR:takeoff
CAM_DATA_PREFIX:takeoff-
CAM_DATA_START_IDX:6
CAM_DATA_END_IDX:53
#-----------------------------------------------------------------------------
# Init the Flask app parameters
FLASK_SER_PORT:5000
FLASK_DEBUG_MD:False
FLASK_MULTI_TH:True
FLASK_FIXED_TOKEN:motionJPEG

Step 2: Setup the video source

Set the camera mode flag parameter in the configuration file:

  • CAM_MD:1 - From real camera

  • CAM_MD:2 - From image data set

  • CAM_MD:3 - From desktop screen recording

  • CAM_MD:4 - From Windows application.

In the webCamApp.py, configure the video source as shown below:

if gv.gCamMode == 0:
    gv.iCamMgr = cam.camClientReal(gv.gCamSrc, fps=gv.gCamFps)
elif gv.gCamMode == 1:
    gv.iCamMgr = cam.camClientSimu(gv.gCamDir, gv.gCamFilePrefix, fps=gv.gCamFps)
    gv.iCamMgr.setShowTimestamp(True)
    gv.iCamMgr.setTestMode(56)
elif gv.gCamMode == 2:
    gv.iCamMgr = cam.camClientScreen(fps=gv.gCamFps)
else:
    windowName = "templates - File Explorer"
    #windowName = "2D Airport CAT-II Runway Light System Simulation"
    #windowName = "Microsoft Edge"
    gv.iCamMgr = cam.camClientWinApp(windowName)

To find the entire application window name, move mouse to the Windows tasks bar then click the small top-up window to show the window name as shown below:

When capture from the windows App, the application must not be minimized.

Step 3: Setup the user authorization file

Rename the users_template.json to users.json and add the user name and password as shown below:

    "admin": {
        "username": "admin",
        "password": "admin",
        "usertype": "admin"
    },

Step4: Run the virtual camera program

Run the flask web host and open the URL: http://<camera ip>:<camera port>

python webCamApp.py

To call the motion JPEG API with the GET request, copy the fix or temporary token from the token page as shown below:

Then use the http GET request for the url http://<camera ip>:<camera port>/cgi-bin/mjpg/<Access Token> to get on frame for the virtual camera as shown below:

response = requests.get(http://<camera ip>:<camera port>/cgi-bin/mjpg/<Access Token>, timeout=1)

Usage of Camera View Dashboard

Step 1: Setup the dashboard configuration file.

Rename the configuration file template camDashboardConfig_template.txt to `camDashboardConfig.txt and set the parameter as shown below:

# This is the config file template for the module <camDashboardRun.py>
# Setup the parameter with below format (every line follows <key>:<value> format, the
# key can not be changed):
#-----------------------------------------------------------------------------
# Test mode:
# - True: run the UI with out connect to the cameras.
# - False: connect to the cameras and fetch the vide stream.
#TEST_MD:True
TEST_MD:False
#-----------------------------------------------------------------------------
# Define all the HMI UI config parameters
# define UI title name 
UI_TITLE: Multi-Camera View Monitor Dashboard
# Define update clock interval
CLK_INT:0.5
#-----------------------------------------------------------------------------
# camera connection configuration file.
CAM_CONFIG_FILE:cameraConfig.json

Step2: Setup the cameras connection configuration file

Rename the configuration file template cameraConfig_template.json to cameraConfig.txt , copy the access token (Fixed/Temporary) from the related camera's token page and add the camera you want to access in the file as shown below:

    "Desktop1": {
        "name": "Desktop screenshot 1 virtual Camera",
        "url": "http://127.0.0.1:5000/cgi-bin/mjpg/",
        "token": "motionJPEG",
        "size": [
            640,
            480
        ]
    },   

Step3: Run the dashboard

Make sure all the virtual camera are running and run the dashboard with cmd:

python camDashboardRun

Then the dashboard will shown below:

The un-configured or un-connected camera will show "no video".

Program Typical Use Cases

The system is design for using in build the OT cyber ranges and supporting the cyber exercise, the possible use cases include:

  • Provide instrumented camera endpoints for blue/red team exercises and cyber ranges.

  • Deploy believable camera honeypots to capture attacker behavior and build datasets.

  • Integrate camera feeds into digital-twin scenarios (e.g., show state-dependent video based on simulated operations).

  • Test and validate surveillance clients, analytics pipelines, and dashboards without physical cameras.

  • Aggregate diverse video sources from virtual machines and host applications for demonstrations, QA, or ML dataset generation.

We will also show two use cases of how this project is used to simulate 4 different cameras in the aviation runway cyber range and monitor the railway cyber range HMI(s) in cyber exercise.

Usage Case as Cyber Range Surveillance System

The system is used in the Aviation runway light management system cyber range to simulate a tower operator's surveillance camera monitoring system to display four cameras shown below. The four cameras include :

  1. Airport runway landing area surveillance camera

  2. Airport runway takeoff area surveillance camera

  3. Tower operational room surveillance camera

  4. Cyber range physical world simulator view display camera

Figure-10: Cyber Range Surveillance System Dashboard, version v_0.0.3 (2025)

Usage Case as Cyber Exercise Main Projection Screen

The system is used in to monitor all the UI program running on different VMs of the Land Based Railway IT-OT System Cyber Security Cyber Range System in the cyber exercise and project on the big TV as shown below. The 4 monitored program includes:

  1. Railway cyber range physical world simulator

  2. HQ railway track signaling system monitor HMI

  3. HQ railway trains monitor and control system HMI

  4. HQ railway management HMI

Figure-11: Cyber Exercise Main Projection Screen, version v_0.0.3 (2025)

GitHub Link: 

https://github.com/LiuYuancheng/Python_Virtual_MotionJPEG_Camera

Thanks for spending time to check the article detail, if you have any question and suggestion or find any program bug, please feel free to message me. Many thanks if you can give some comments and share any of the improvement advice so we can make our work better ~

Last edit by LiuYuancheng ([email protected]) at 03/11/2025, if you have any problem please free to message me.

           

  RELATED


No related programming articles found. Browse all programming tutorials and articles.

  0 COMMENTS


No comment for this article.



  PROGRAMMER HUMOR

VS Code is the one


  SUPPORT US