5. Running a flow from your code¶
The MuseBox Client runs a pipeline exported from the editor without the browser. It reads the .json
file, sends the frames of a camera, video or image to the board and draws the results. Use it as a ready
program, or as the starting point of your own application.
It exists in Python and in C++, and both read the same .json files.
Download¶
Download the client you need into the musebox folder of chapter 4: ~/musebox on Linux / macOS,
C:\Users\<your-user>\musebox on Windows.
On your PC, Linux / macOS:
pc$ mkdir -p ~/musebox
pc$ curl -L https://s3.eu-central-1.wasabisys.com/musebox/SDK-RELEASES/MUSEBOX_CLIENT/PYTHON/musebox-client-python-latest.tar.gz | tar -xz -C ~/musebox
pc$ curl -L https://s3.eu-central-1.wasabisys.com/musebox/SDK-RELEASES/MUSEBOX_CLIENT/CPP/musebox-client-cpp-latest.tar.gz | tar -xz -C ~/musebox
On your PC, Windows 10 / 11 (Command Prompt or PowerShell):
pc$ cd C:\Users\<your-user>\musebox
pc$ curl.exe -LO https://s3.eu-central-1.wasabisys.com/musebox/SDK-RELEASES/MUSEBOX_CLIENT/PYTHON/musebox-client-python-latest.tar.gz
pc$ tar -xzf musebox-client-python-latest.tar.gz
pc$ curl.exe -LO https://s3.eu-central-1.wasabisys.com/musebox/SDK-RELEASES/MUSEBOX_CLIENT/CPP/musebox-client-cpp-latest.tar.gz
pc$ tar -xzf musebox-client-cpp-latest.tar.gz
They create musebox-client/python, musebox-client/cpp and musebox-common, the shared files both
clients need: keep musebox-common next to musebox-client.
Download only the one you need, if you like. On Windows you can also download
musebox-client-python-latest.tar.gz or
musebox-client-cpp-latest.tar.gz with the
browser into C:\Users\<your-user>\musebox and run only the cd and tar lines.
Python¶
Install it in its own Python environment (a venv), once:
On your PC, Linux / macOS:
pc$ cd ~/musebox/musebox-client/python
pc$ python3 -m venv .venv
pc$ source .venv/bin/activate
pc$ pip install -r requirements.txt
On your PC, Windows 10 / 11 (Command Prompt or PowerShell):
pc$ cd C:\Users\<your-user>\musebox\musebox-client\python
pc$ python -m venv .venv
pc$ .venv\Scripts\activate
pc$ pip install -r requirements.txt
On Debian / Ubuntu, if venv says ensurepip is not available, install it once with
sudo apt install python3-venv and run the command again. If PowerShell refuses to run activate because
running scripts is disabled, allow it once with Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, or
use Command Prompt.
The client runs a pipeline you exported from the editor (chapter 4, Manage → export). The browser saved
it in your Downloads folder as <name>.json, for example face_detection_pipeline.json. In the commands of
this chapter, my_pipeline.json stands for that file: copy it into the client's folder
(~/musebox/musebox-client/python, C:\Users\<your-user>\musebox\musebox-client\python on Windows), or
give its full path, for example --json ~/Downloads/face_detection_pipeline.json.
Make sure the AI server is running on the board, then run the pipeline with the venv active (activate it again in every new terminal, as above):
Stop the pipeline in the editor first
A camera works with one program at a time. Before you start the client, turn off the pipeline in the No-Code Flow Editor, so that it frees the camera:
- press Stop in the editor's toolbar: the browser releases the PC webcam, and the board ends the editor's board camera stream;
- if the pipeline is still playing, the client cannot open the PC webcam, and with the board camera in
streammode the editor and the client keep taking the stream from each other (the board runs one stream at a time).
If the client still cannot open the PC webcam, your editor is an older version that keeps it after Stop: close the editor's tab, and update the editor (chapter 4).
On your PC:
pc$ python main.py --json my_pipeline.json
A window shows the video with the results. To stop, click the window and press Q or Esc. With
--no-show there is no window: press Ctrl+C in the terminal on your PC where main.py runs.
The server address and the board come from the configuration node of the pipeline. Pass --url to
override the address:
On your PC:
pc$ python main.py --json my_pipeline.json --url ws://<board-ip>:8080
Useful options¶
| Option | Meaning |
|---|---|
--source 0 |
camera index, video file or image (default: the one in the pipeline, else the webcam 0) |
--source board-camera |
the camera attached to the board; only a preview comes back |
--source board-stream |
the board runs the whole pipeline on its camera and sends the results (fastest) |
--save out.mp4 |
write the annotated video |
--no-show |
no window (servers, scripts) |
--raw-frames |
send uncompressed frames: faster on a wired network |
--zmq, --mqtt, --rabbitmq, --ros2 |
use another protocol instead of WebSocket |
All the options (python main.py --help)
usage: main.py [-h] --json JSON [--source SOURCE]
[--preview-max-side PREVIEW_MAX_SIDE] [--max-frames MAX_FRAMES]
[--url URL] [--board BOARD] [--client-id CLIENT_ID] [--no-show]
[--save SAVE] [--image-size IMAGE_SIZE] [--flip] [--raw-frames]
[--zmq] [--zmq-url ZMQ_URL] [--mqtt] [--mqtt-host MQTT_HOST]
[--mqtt-port MQTT_PORT]
[--mqtt-request-topic MQTT_REQUEST_TOPIC]
[--mqtt-response-topic MQTT_RESPONSE_TOPIC] [--mqtt-raw]
[--mqtt-username MQTT_USERNAME] [--mqtt-password MQTT_PASSWORD]
[--rabbitmq] [--rabbitmq-host RABBITMQ_HOST]
[--rabbitmq-port RABBITMQ_PORT]
[--rabbitmq-vhost RABBITMQ_VHOST]
[--rabbitmq-username RABBITMQ_USERNAME]
[--rabbitmq-password RABBITMQ_PASSWORD]
[--rabbitmq-request-queue RABBITMQ_REQUEST_QUEUE]
[--rabbitmq-exchange RABBITMQ_EXCHANGE] [--rabbitmq-raw]
[--ros2] [--ros2-node-name ROS2_NODE_NAME]
[--ros2-request-topic ROS2_REQUEST_TOPIC]
[--ros2-response-topic ROS2_RESPONSE_TOPIC]
[--ros2-domain-id ROS2_DOMAIN_ID]
[--ros2-qos {default,sensor_data,reliable,best_effort}]
MuseBox Python Client - load a no-code flow JSON, query the MuseBox AI server
and run the real-time pipeline.
options:
-h, --help show this help message and exit
--json JSON, -j JSON Flow JSON exported from the no-code-flow-editor
--source SOURCE, -s SOURCE
Camera index, video file, image file, 'board-camera'
(grab frames on the board per tick) or 'board-stream'
(the board runs the whole pipeline and pushes results;
WebSocket only) (default: from JSON or 0)
--preview-max-side PREVIEW_MAX_SIDE
Board camera only: longest side of the preview JPEG
sent back for display (default: 320)
--max-frames MAX_FRAMES
Stop after N frames (0 = run until the stream ends)
--url URL, -u URL Override server URL: ws://, tcp:// (ZeroMQ), mqtt://,
amqp:// (RabbitMQ) or ros2://domain/<id>
--board BOARD, -b BOARD
Override the board profile name (default: from JSON)
--client-id CLIENT_ID
Client identifier sent with every request
--no-show Disable the GUI window (headless)
--save SAVE Save the annotated video to this file (e.g.
output.mp4)
--image-size IMAGE_SIZE
Override the resize resolution (WxH, e.g. 640x480)
--flip, --flip-camera
Flip the input horizontally
--raw-frames Send uncompressed BGR frames (WebSocket / ZeroMQ
multipart): no JPEG decode on the board; best on a
wired LAN
ZeroMQ:
--zmq Use ZeroMQ instead of WebSocket
--zmq-url ZMQ_URL ZeroMQ endpoint (default: tcp://<flow server
host>:5555)
MQTT:
--mqtt Use MQTT instead of WebSocket
--mqtt-host MQTT_HOST
MQTT broker host (default: the flow's server host)
--mqtt-port MQTT_PORT
--mqtt-request-topic MQTT_REQUEST_TOPIC
--mqtt-response-topic MQTT_RESPONSE_TOPIC
--mqtt-raw Send raw JPEG frames instead of JSON/base64
--mqtt-username MQTT_USERNAME
MQTT broker user (default: anonymous)
--mqtt-password MQTT_PASSWORD
MQTT broker password
RabbitMQ:
--rabbitmq Use RabbitMQ instead of WebSocket
--rabbitmq-host RABBITMQ_HOST
RabbitMQ broker host (default: the flow's server host)
--rabbitmq-port RABBITMQ_PORT
--rabbitmq-vhost RABBITMQ_VHOST
--rabbitmq-username RABBITMQ_USERNAME
--rabbitmq-password RABBITMQ_PASSWORD
--rabbitmq-request-queue RABBITMQ_REQUEST_QUEUE
--rabbitmq-exchange RABBITMQ_EXCHANGE
--rabbitmq-raw Send raw JPEG frames instead of JSON/base64
ROS 2:
--ros2 Use ROS 2 instead of WebSocket
--ros2-node-name ROS2_NODE_NAME
--ros2-request-topic ROS2_REQUEST_TOPIC
--ros2-response-topic ROS2_RESPONSE_TOPIC
--ros2-domain-id ROS2_DOMAIN_ID
--ros2-qos {default,sensor_data,reliable,best_effort}
MQTT, RabbitMQ, ROS 2¶
What to install¶
| Protocol | On the board | On your PC |
|---|---|---|
| MQTT | nothing: the server has MQTT built in, and the board has its own broker (mosquitto) | nothing: the Python client's requirements.txt installs paho-mqtt |
| RabbitMQ | nothing: the server has RabbitMQ built in, but the board has no broker | a RabbitMQ broker, on your PC or on another computer that the board and the PC both reach (the Python client's requirements.txt installs pika) |
| ROS 2 | nothing: the board has ROS 2 Humble | ROS 2 Humble, the same version as the board |
The C++ client also needs the MQTT and RabbitMQ libraries to build, whatever protocol you use: see C++.
RabbitMQ broker. Install it and create the user the server and the client log in with
(musebox / musebox, from config/rabbitmq.json). RabbitMQ's own guest user only works from the
broker's computer, so the board cannot use it.
On your PC, Linux / macOS:
pc$ sudo apt install rabbitmq-server
pc$ sudo rabbitmqctl add_user musebox musebox
pc$ sudo rabbitmqctl set_permissions -p / musebox ".*" ".*" ".*"
The first line is for Debian / Ubuntu, and it also starts the broker. On macOS, with Homebrew, run instead
(without sudo):
pc$ brew install rabbitmq
pc$ brew services start rabbitmq
pc$ rabbitmqctl add_user musebox musebox
pc$ rabbitmqctl set_permissions -p / musebox ".*" ".*" ".*"
On your PC, Windows 10 / 11: install Erlang and RabbitMQ with the installer from rabbitmq.com (it starts RabbitMQ as a Windows service), then open RabbitMQ Command Prompt (sbin dir) from the Start menu as administrator and run:
pc$ rabbitmqctl add_user musebox musebox
pc$ rabbitmqctl set_permissions -p / musebox ".*" ".*" ".*"
The broker listens on port 5672: allow it in the PC's firewall, so that the board can connect.
ROS 2 Humble. Follow the official guide, docs.ros.org/en/humble/Installation.html:
binary packages exist for Ubuntu 22.04 and Windows 10; on macOS ROS 2 has to be built from source. The
board and the PC must use the same ROS domain (domain_id in config/ros2.json, 0 by default, and the
ROS_DOMAIN_ID variable on the PC, also 0 when not set) and be on the same network.
Using them¶
These protocols are off on the board by default. Start the server with the matching option (for example
/root/musebox-ai-servers/musebox-ai-server-cpp/musebox-ai-server --mqtt --mqtt-host <broker-ip>), or set them in
config/mqtt.json, config/rabbitmq.json or config/ros2.json. Then run the client with the same option.
MQTT and RabbitMQ go through a broker: the board and your PC must both reach it, so give its network address
(not localhost) to the server and to the client:
On your PC:
pc$ python main.py --json my_pipeline.json --mqtt --mqtt-host <broker-ip>
pc$ python main.py --json my_pipeline.json --rabbitmq --rabbitmq-host <broker-ip>
RabbitMQ: the server and the client log in as musebox / musebox, the user created above. To use
another user, set it in config/rabbitmq.json on the board and pass it to the client with
--rabbitmq-username and --rabbitmq-password.
The board has its own MQTT broker (mosquitto), but it only accepts connections from the board itself. To
use it from your PC, open it to the network: add these two lines at the end of /etc/mosquitto/mosquitto.conf
on the board, then restart it:
listener 1883
allow_anonymous true
On the board:
board$ systemctl restart mosquitto
Then use --mqtt-host <board-ip> on the client. Both lines are needed: listener 1883 accepts
connections from the network, and allow_anonymous true lets in the server and the client, which connect
without a user name. Anyone on your network can then send requests to the board and read the results. On
a shared network, protect the broker with a user and password instead of allow_anonymous true
(mosquitto's password_file), and give them to the server (--mqtt-username, --mqtt-password, or
username / password in config/mqtt.json) and to the client (--mqtt-username, --mqtt-password).
For --ros2, the client uses the ROS 2 Python packages (rclpy) of your ROS 2 installation, which a venv
does not see. Load ROS 2 first and create the venv with access to them (in place of the venv of
Python):
On your PC, Linux / macOS:
pc$ cd ~/musebox/musebox-client/python
pc$ source /opt/ros/humble/setup.bash
pc$ python3 -m venv --system-site-packages .venv
pc$ source .venv/bin/activate
pc$ pip install -r requirements.txt
On your PC, Windows 10 / 11 (Command Prompt only, with ROS 2 installed in C:\dev\ros2_humble as in the
ROS 2 guide):
pc$ cd C:\Users\<your-user>\musebox\musebox-client\python
pc$ call C:\dev\ros2_humble\local_setup.bat
pc$ python -m venv --system-site-packages .venv
pc$ .venv\Scripts\activate
pc$ pip install -r requirements.txt
Load ROS 2 again (source /opt/ros/humble/setup.bash, or call C:\dev\ros2_humble\local_setup.bat) in
every new terminal, before activating the venv.
ZeroMQ is on by default, on port 5555:
On your PC:
pc$ python main.py --json my_pipeline.json --zmq --zmq-url tcp://<board-ip>:5555
With the C++ client the options are the same. Here the server runs with --mqtt, --rabbitmq and --ros2,
and the client runs the face detection pipeline over each protocol in turn:
C++¶
The C++ client needs a C++17 compiler, CMake 3.16 or newer, OpenCV 4, Boost 1.74 or newer, and the ZeroMQ,
MQTT (mosquitto) and RabbitMQ (rabbitmq-c) libraries. All of them are needed to build, even if you only use
WebSocket. ROS 2 is optional: the --ros2 option is built in only when ROS 2 is loaded before cmake.
Install the libraries, once.
On your PC, Linux / macOS:
pc$ sudo apt install build-essential cmake libopencv-dev libboost-system-dev libboost-thread-dev libzmq3-dev libmosquitto-dev librabbitmq-dev # Debian / Ubuntu
pc$ brew install cmake opencv boost zeromq mosquitto rabbitmq-c # macOS (Homebrew)
On your PC, Windows 10 / 11: install Visual Studio 2022 (Community, or the Build Tools) with the Desktop development with C++ workload, which includes the compiler and CMake, and Git for Windows. Then open x64 Native Tools Command Prompt for VS 2022 from the Start menu and install the libraries with vcpkg. vcpkg compiles them, so the last command takes about an hour the first time:
pc$ git clone https://github.com/microsoft/vcpkg C:\vcpkg
pc$ C:\vcpkg\bootstrap-vcpkg.bat
pc$ C:\vcpkg\vcpkg install opencv4 boost-beast boost-system boost-thread zeromq mosquitto librabbitmq nlohmann-json --triplet x64-windows
Build and run it. As for the Python client, first stop the pipeline in the editor (Stop), so that the camera is free.
On your PC, Linux / macOS:
pc$ cd ~/musebox/musebox-client/cpp
pc$ cmake -B build && cmake --build build -j
pc$ ./build/musebox-client-cpp --json my_pipeline.json
On your PC, Windows 10 / 11 (x64 Native Tools Command Prompt for VS 2022):
pc$ cd C:\Users\<your-user>\musebox\musebox-client\cpp
pc$ cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake
pc$ cmake --build build --config Release
pc$ build\Release\musebox-client-cpp.exe --json my_pipeline.json
my_pipeline.json is the pipeline exported from the editor, as for the Python client: copy it into the
cpp folder or give its full path. For --ros2, load ROS 2 before cmake
(source /opt/ros/humble/setup.bash, or call C:\dev\ros2_humble\local_setup.bat on Windows): without it the
client is built without ROS 2.
The build copies the libraries' DLLs next to musebox-client-cpp.exe: run it from there, or copy the whole
build\Release folder.
As with the Python client, to stop click the window and press Q or Esc. With --no-show, press
Ctrl+C in the terminal on your PC where musebox-client-cpp runs.
The options are those of the Python client, except --raw-frames,
--max-frames and the board-camera / board-stream sources, which only the Python client has.
All the options (musebox-client-cpp --help)
MuseBox C++ Client v1.1.4
Usage: ./build/musebox-client-cpp --json <flow.json> [options]
Options:
--json, -j <path> Path to flow JSON file exported by the no-code-flow-editor (required)
--source, -s <src> Video source: camera index (e.g. 0), video or image file path
--url, -u <url> Override server URL (ws://, tcp://, mqtt://, amqp://, ros2://domain/<id>)
--client-id <id> Client identifier sent with every request (default: 1)
--ros2 Use ROS 2 protocol interface instead of WebSocket
--ros2-node-name <name> ROS 2 client node name
--ros2-request-topic <t> ROS 2 request topic (default: musebox/request)
--ros2-response-topic <t> ROS 2 response topic (default: musebox/response)
--ros2-domain-id <id> ROS 2 domain ID (default: 0)
--ros2-qos <profile> QoS profile: default, sensor_data, reliable, best_effort
--zmq Use ZeroMQ protocol interface instead of WebSocket
--zmq-url <endpoint> ZeroMQ server endpoint (default: tcp://127.0.0.1:5555)
--mqtt Use MQTT protocol interface instead of WebSocket
--mqtt-host <host> MQTT broker host (default: 127.0.0.1)
--mqtt-port <port> MQTT broker port (default: 1883)
--mqtt-request-topic <t> MQTT request topic (default: musebox/request)
--mqtt-response-topic <t> MQTT response topic (default: musebox/response)
--mqtt-raw Publish raw JPEG binary frames over MQTT
--mqtt-username <usr> MQTT broker user (default: anonymous)
--mqtt-password <pwd> MQTT broker password
--rabbitmq Use RabbitMQ protocol interface instead of WebSocket
--rabbitmq-host <host> RabbitMQ broker host (default: 127.0.0.1)
--rabbitmq-port <port> RabbitMQ broker port (default: 5672)
--rabbitmq-vhost <vhost> RabbitMQ virtual host (default: /)
--rabbitmq-username <usr> RabbitMQ username (default: musebox)
--rabbitmq-password <pwd> RabbitMQ password (default: musebox)
--rabbitmq-request-queue RabbitMQ request queue (default: musebox_requests)
--rabbitmq-exchange <ex> RabbitMQ exchange name (default: '')
--rabbitmq-raw Publish raw JPEG binary frames over RabbitMQ
--board, -b <board> Override board hardware profile (e.g. MP1 ST1)
--no-show Disable visual GUI window
--save <path.mp4> Save annotated video output file
--image-size <WxH> Override image resize resolution (e.g. 640x480)
--flip, --flip-camera Flip input frame horizontally
--help, -h Show this help
The messages, for your own application¶
Every protocol carries the same JSON.
A request:
{"topic": "FaceDetection", "clientId": "1", "board": "Mercury+ PE3 Hailo",
"imageWidth": 640, "imageHeight": 480, "image": "<base64 JPEG>"}
The answer:
{"status": "success", "topic": "FaceDetection", "data": [...], "execution_time": 12.3, "board": "pluto-hailo"}
board in the answer is the board name set on the board in config/models.json.
or, on error:
{"status": "error", "error": "..."}
topic is the task. The tasks your board offers are listed at http://<board-ip>:8080/models.
Next: 6. Your own models