{"id":13704961,"url":"https://github.com/robmarkcole/mqtt-camera-streamer","last_synced_at":"2025-04-07T05:11:29.174Z","repository":{"id":47096336,"uuid":"198009047","full_name":"robmarkcole/mqtt-camera-streamer","owner":"robmarkcole","description":"Stream images from a connected camera over MQTT, view using Streamlit, record to file and sqlite","archived":false,"fork":false,"pushed_at":"2024-08-12T19:17:40.000Z","size":2565,"stargazers_count":246,"open_issues_count":16,"forks_count":55,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-30T21:09:25.535Z","etag":null,"topics":["camera","home-automation","mqtt","sqlite","streamlit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robmarkcole.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"robmarkcole"}},"created_at":"2019-07-21T03:48:41.000Z","updated_at":"2025-03-20T01:01:38.000Z","dependencies_parsed_at":"2024-01-14T20:52:37.757Z","dependency_job_id":"ca270ce8-fa7c-4bd6-8a62-da965dcc0f7d","html_url":"https://github.com/robmarkcole/mqtt-camera-streamer","commit_stats":{"total_commits":71,"total_committers":2,"mean_commits":35.5,"dds":"0.028169014084507005","last_synced_commit":"1d0cbab1a9457266421d524d6e9f6dee2e2e1f08"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robmarkcole%2Fmqtt-camera-streamer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robmarkcole%2Fmqtt-camera-streamer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robmarkcole%2Fmqtt-camera-streamer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robmarkcole%2Fmqtt-camera-streamer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robmarkcole","download_url":"https://codeload.github.com/robmarkcole/mqtt-camera-streamer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595335,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["camera","home-automation","mqtt","sqlite","streamlit"],"created_at":"2024-08-02T22:00:28.540Z","updated_at":"2025-04-07T05:11:29.125Z","avatar_url":"https://github.com/robmarkcole.png","language":"Python","funding_links":["https://github.com/sponsors/robmarkcole"],"categories":["Interfaces","Awesome Resources"],"sub_categories":["Misc","App"],"readme":"# mqtt-camera-streamer\n**Summary:** Publish frames from a connected camera or MJPEG/RTSP stream to an MQTT topic, and view the feed in a browser on another computer with [Streamlit](https://github.com/streamlit/streamlit).\n\n**Long introduction:** A typical task in IOT/science is that you have a camera connected to one computer and you want to view the camera feed on a second computer, and maybe preprocess the images before saving them to disk. I have always found this to be way more effort than expected. In particular, working with camera streams can get quite complicated and may lead you to experiment with tools like Gstreamer and ffmpeg that have a steep learning curve. In contrast, working with [MQTT](http://mqtt.org/) is very straightforward and is often familiar to anyone with an interest in IOT. This repo, `mqtt-camera-streamer` uses MQTT to send frames from a camera over a network at low frames-per-second (FPS). A viewer is provided for viewing the camera stream on any computer on the network. Frames can be saved to disk for further processing. Also it is possible to setup an image processing pipeline by linking MQTT topics together, using an `on_message(topic)` to do some processing and send the processed image downstream on another topic.\n\n**Note** that this is not a high FPS solution, and in practice I achieve around 1 FPS which is practical for IOT experiments and tasks such as preprocessing (cropping, rotating) images prior to viewing them. This code is written for simplicity and ease of use, not high performance.\n\n## Installation\nInstall system wide on an RPi, or on other OS use a venv to isolate your environment, and install the required dependencies:\n```\n$ (base) python3 -m venv venv\n$ (base) source venv/bin/activate\n$ (venv) pip3 install -r requirements.txt\n```\n\n## Listing cameras with OpenCV\nThe `check-opencv-cameras.py` script assists in discovering which cameras OpenCV can connect to on your computer (does not work with RPi camera). If your laptop has a built-in webcam this will generally be listed as `VIDEO_SOURCE = 0`. If you plug in an external USB webcam this takes precedence over the built-in webcam, with the external camera becoming `VIDEO_SOURCE = 0` and the built-in webcam becoming `VIDEO_SOURCE = 1`.\n\nTo check which OpenCV cameras are detected run:\n```\n$ (venv) python3 scripts/check-opencv-cameras.py\n```\n\n## Configuration using `config.yml`\nUse the `config.yml` file in the `config` directory to configure your system. If your desired camera is listed as source 0 you will configure `video_source: 0`. Alternatively you can configure the video source as an MJPEG or RTSP stream. For example in `config.yml` you may configure something like `video_source: \"rtsp://admin:password@192.168.1.94:554/11\"` for a commercial RTSP camera. To configure a RPi camera running the `web_streaming.py` example you configure `video_source: http://pi_ip:8000/stream.mjpg`\n\nValidate the config can be loaded by running:\n```\n$ (venv) python3 scripts/validate-config.py\n```\n\n**Note** that this script does not check the accuracy of any of the values in `config.yml`, just that the file path is correct and the file structure is OK.\n\nBy default `scripts/opencv-camera.py` will look for the config file at `./config/config.yml` but an alternative path can be specified using the environment variable `MQTT_CAMERA_CONFIG`. You can set this using `export MQTT_CAMERA_CONFIG=/home/pi/github/mqtt-camera-streamer/config/config.yml`\n\n## Publish camera frames\nTo publish camera frames with OpenCV over MQTT:\n```\n$ (venv) python3 scripts/opencv-camera-publish.py\n```\n\n## Camera display\nTo view the camera stream with Streamlit:\n```\n$ (venv) streamlit run scripts/viewer.py\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/robmarkcole/mqtt-camera-streamer/blob/master/docs/images/viewer_usage.png\" width=\"500\"\u003e\n\u003c/p\u003e\n\n**Note:** if Streamlit becomes unresponsive, `ctrl-z` to pause Streamlit then `kill -9 %%`. Also note that the viewer can be run on any machine on your network.\n\n## Save frames\nTo save frames to disk:\n```\n$ (venv) python3 scripts/save-captures.py\n```\n\n## Save frames to db\nAs `save-captures.py` but in addition saving the frame thumbnail to a sqlite db:\n```\n$ (venv) python3 scripts/db-recorder.py\n```\n\nThe images can be viewed using [sqlite browser](https://sqlitebrowser.org/)\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/robmarkcole/mqtt-camera-streamer/blob/master/docs/images/sqlite-browser.jpg\" width=\"800\"\u003e\n\u003c/p\u003e\n\nIf you wish to run a server with UI for browsing the images then [datasette](https://datasette.io/) with the [datasette-render-images](https://datasette.io/plugins/datasette-render-images) plugin can be used.\n\n```\n$ (venv) pip install datasette\n$ (venv) pip install datasette-render-images\n$ (venv) datasette captures/records.db\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/robmarkcole/mqtt-camera-streamer/blob/master/docs/images/datasette.jpg\" width=\"800\"\u003e\n\u003c/p\u003e\n\n\n## Image processing pipeline\nTo process a camera stream (the example rotates the image):\n```\n$ (venv) python3 scripts/processing.py\n```\n\n## Home Assistant\nYou can view the camera feed using [Home Assistant](https://www.home-assistant.io/) and configuring an [MQTT camera](https://www.home-assistant.io/components/camera.mqtt/). Add to your `configuration.yaml`:\n```yaml\ncamera:\n  - platform: mqtt\n    topic: homie/mac_webcam/capture\n    name: mqtt_camera\n  - platform: mqtt\n    topic: homie/mac_webcam/capture/rotated\n    name: mqtt_camera_rotated\n  - platform: mjpeg # the raw mjpeg feed if using picamera\n    name: picamera\n    mjpeg_url: http://192.168.1.134:8000/stream.mjpg\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/robmarkcole/mqtt-camera-streamer/blob/master/docs/images/ha_usage.png\" width=\"500\"\u003e\n\u003c/p\u003e\n\n## MQTT\nNeed an MQTT broker? If you have Docker installed I recommend [eclipse-mosquitto](https://hub.docker.com/_/eclipse-mosquitto). A basic broker can be run with:\n```\ndocker run -p 1883:1883 -d eclipse-mosquitto\n```\nNote that I have structured the MQTT topics following the homie MQTT convention, linked in the references. This is not necessary but is best practice IMO.\n\n## OpenCV \u0026 streamlit on RPi\nOpenCV is used to read the images from a connected camera or MJPEG/RTSP stream. On a Raspberry pi (RPi) installing OpenCV can be troublesome, and I found it necessary to first `sudo apt-get install libatlas-base-dev libjasper-dev libqtgui4 python3-pyqt5 libqt4-test libilmbase-dev libopenexr-dev libgstreamer1.0-dev libavcodec58 libavformat58 libswscale5` before installing opencv using the instructions below. Likewise Streamlit can be challenging to install on an RPi, and if you dont need it then remove it from `requirements.txt`. If you do wish to install Streamlit on the RPi see [this thread](https://discuss.streamlit.io/t/raspberry-pi-streamlit/2900) for latest guidance. On 24/3/2021 I was able to install `opencv-python==4.5.1.48` but not streamlit on an RPi4 32bit.\n\n## RPi camera\nUse an official RPi camera and ensure [picamera](https://picamera.readthedocs.io/en/release-1.13/) is installed with `pip3 install picamera`. If you use the RPi in desktop mode you can check the camera feed using `raspistill -o image.jpg`. Use the official [web_streaming](https://github.com/waveform80/picamera/blob/master/docs/examples/web_streaming.py) example which creates an mjpeg stream on `http://pi_ip:8000/stream.mjpg`. This mjpeg stream can be configured as a source with `mqtt-camera-streamer` to translate the mjepg stream to an mqtt stream.\n\n## RPi service\nYou can run any of the scripts as a [service](https://www.raspberrypi.org/documentation/linux/usage/systemd.md), which means they will automatically start on RPi boot, and can be easily started \u0026 stopped. Create the service file in the appropriate location on the RPi using:\n\n```sudo nano /etc/systemd/system/my_script.service```\n\nEntering the following (adapted for your `script.py` file location and args, assumes you are using system python3):\n```\n[Unit]\nDescription=Service for mqtt-camera-publish\nAfter=network.target\n\n[Service]\nExecStart=/usr/bin/python3 -u opencv-camera-publish.py\nWorkingDirectory=/home/pi/github/mqtt-camera-streamer/scripts\nStandardOutput=inherit\nStandardError=inherit\nRestart=always\nUser=pi\n\n[Install]\nWantedBy=multi-user.target\n```\n\nOnce this file has been created you can to start the service using:\n```sudo systemctl start my_script.service```\n\nView the status and logs with:\n```sudo systemctl status my_script.service```\n\nStop the service with:\n```sudo systemctl stop my_script.service```\n\nRestart the service with:\n```sudo systemctl restart my_script.service```\n\nYou can have the service auto-start on rpi boot by using:\n```sudo systemctl enable my_script.service```\n\nYou can disable auto-start using:\n```sudo systemctl disable my_script.service```\n\n### References\n* [imageZMQ](https://github.com/jeffbass/imagezmq) -\u003e inspired this project, but uses ZMQ. [Discussion on ZMQ vs MQTT here](https://github.com/jeffbass/imagezmq/issues/5)\n* [homie MQTT convention](https://homieiot.github.io/) -\u003e convention for structuring MQTT topics\n* [yolocam_mqtt](https://github.com/LarsAC/yolocam_mqtt/blob/master/yolo_mqtt_server.py) -\u003e another source of ideas\n* [In-depth review and comparison of the Raspberry Pi High Quality Camera](https://medium.com/@alexellisuk/in-depth-review-and-comparison-of-the-raspberry-pi-high-quality-camera-806490c4aeb7)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobmarkcole%2Fmqtt-camera-streamer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobmarkcole%2Fmqtt-camera-streamer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobmarkcole%2Fmqtt-camera-streamer/lists"}