Complete guide to deploying the BrightSign Python CV Extension to players.
Prerequisites: Extension packages built (see getting-started.md)
- Package Types
- Player Preparation
- Development Deployment
- Production Deployment
- User Initialization Scripts
- Verification & Testing
- Updates & Maintenance
- Troubleshooting
Characteristics:
- Size: ~420MB
- Location:
/usr/local/pydev/ - Persistence: Volatile (lost on reboot)
- Auto-start: No (manual activation)
- Installation: Simple unzip, no system integration
- Deployment time: ~2 minutes
Use When:
- Iterating on code/configuration
- Testing new packages
- Debugging issues
- Development/testing environments
- Need quick deployment cycles
Advantages:
- Fast deployment (no reboot needed)
- Easy to remove (just delete directory)
- Multiple versions can coexist
- No system modifications
Disadvantages:
- Lost on player reboot
- Must manually activate
- Not suitable for production
Characteristics:
- Size: ~370MB (smaller due to squashfs compression)
- Location:
/var/volatile/bsext/ext_pydev/ - Persistence: Persistent (survives reboots)
- Auto-start: Yes (systemd service)
- Installation: System extension via LVM
- Deployment time: ~5 minutes + reboot
Use When:
- Production deployments
- Long-term installations
- Need auto-start on boot
- Appliance/kiosk scenarios
- Final release
Advantages:
- Survives reboots
- Auto-starts on boot
- System service integration
- Professional deployment
Disadvantages:
- Requires reboot to activate
- More complex to update/remove
- System-level installation
| Scenario | Package Type |
|---|---|
| Development/testing | Development (pydev-*.zip) |
| QA validation | Development initially, then Production |
| Production deployment | Production (ext_pydev-*.zip) |
| Demo/proof-of-concept | Development (faster iteration) |
| Customer delivery | Production (professional) |
Before deploying, ensure:
- Firmware: OS 9.1.79.3 or later
- Network: Player accessible from dev host
- DWS: Diagnostic Web Server enabled
- SSH: SSH access enabled
- Security: Player unsecured (
SECURE_CHECKS=0) - Space: Adequate storage (~500MB free)
Why required: OS 9.1.79.3+ includes librknnrt.so system library for NPU support.
Check current version:
ssh brightsign@<player-ip>
cat /etc/versionIf < 9.1.79.3, update:
-
Download firmware:
- XT-5: OS 9.1.79.3
-
Update via DWS:
- Extract
.bsfwfile from downloaded zip - Navigate to
http://<player-ip>:8080 - Click "Software Updates" tab
- Click "Choose File" and select
.bsfw - Click "Upload"
- Wait for update to complete
- Player will reboot automatically
- Extract
-
Verify:
ssh brightsign@<player-ip> cat /etc/version # Should show 9.1.79.3 or later
Alternative: Serial Console Update:
# Connect serial cable (115200 bps, n-8-1)
# Follow on-screen firmware update instructionsWarning: Only unsecure development/test players, NEVER production units in the field.
Via Serial Console (required for first-time unsecure):
-
Connect serial cable (115200 bps, n-8-1)
-
Interrupt boot:
# Press Ctrl-C within 3 seconds of power-on BrightSign> console on BrightSign> reboot -
On next boot, interrupt again:
BrightSign> setenv SECURE_CHECKS 0 BrightSign> envsave BrightSign> reboot -
Verify SSH access:
ssh brightsign@<player-ip> # Should connect successfully
Via Existing SSH (if player already unsecured but needs reset):
ssh brightsign@<player-ip>
# At BrightSign prompt
setenv SECURE_CHECKS 0
envsave
rebootIn BrightAuthor:connected:
- Open or create setup files
- Go to Advanced tab
- Enable "Diagnostic Web Server"
- Publish to player
Verify:
- Open browser to
http://<player-ip>:8080 - Should see DWS interface
Fast, volatile deployment for testing and iteration.
Method 1: Via DWS (recommended):
- Open
http://<player-ip>:8080in browser - Click "SD" tab
- Click "Choose File" button
- Select
pydev-YYYYMMDD-HHMMSS.zip - Click "Upload"
- Wait for upload to complete (shows progress bar)
Method 2: Via SCP:
export PLAYER_IP=192.168.1.100 # Your player IP
scp pydev-*.zip brightsign@${PLAYER_IP}:/storage/sd/Method 3: Via HTTP:
# On player
cd /storage/sd
wget http://<dev-host-ip>/<path>/pydev-*.zipVia SSH:
# Connect to player
ssh brightsign@${PLAYER_IP}
# Exit BrightScript debugger to Linux shell
# If at BrightScript prompt (>), type:
exit
exit
# Create installation directory
mkdir -p /usr/local/pydev
# Extract package
cd /usr/local/pydev
unzip /storage/sd/pydev-*.zip
# List extracted files
ls -laExpected directory structure:
/usr/local/pydev/
├── bsext_init # Service control script
├── uninstall.sh # Uninstall script
├── usr/ # Python runtime and libraries
│ ├── bin/python3
│ └── lib/python3.8/
├── sh/ # Helper scripts
│ ├── setup_python_env
│ └── test_python_imports
└── examples/ # Example scripts
├── test_yolox_npu.py
└── py_utils/
Source Python environment:
source /usr/local/pydev/sh/setup_python_envWhat this does:
- Sets
PATHto include Python - Sets
PYTHONPATHfor libraries - Sets
LD_LIBRARY_PATHfor shared libraries - Activates the extension environment
Verify activation:
which python3
# Should show: /usr/local/pydev/usr/bin/python3
python3 --version
# Should show: Python 3.8.xQuick test:
python3 -c "import cv2, torch, numpy; print('Success!')"Comprehensive test:
cd /usr/local/pydev
sh/test_python_imports --verboseNPU test:
python3 -c "from rknnlite.api import RKNNLite; r = RKNNLite(); print('NPU ready!')"To avoid sourcing environment every login:
Add to .profile:
echo 'source /usr/local/pydev/sh/setup_python_env' >> ~/.profileOr use convenience script:
source /usr/local/pydev/sh/pydev-env
# Shorter form that auto-detects locationTypical iteration cycle:
- Modify code on dev host
- Rebuild specific package:
./build --clean python3-mypackage ./build python3-mypackage
- Repackage:
./package --dev-only
- Transfer new package to player
- Extract over existing installation:
cd /usr/local/pydev unzip -o /storage/sd/pydev-*.zip
- Test changes immediately (no reboot)
Time per cycle: 10-20 minutes
Persistent, auto-starting deployment for production use.
Same as development deployment (via DWS, SCP, or HTTP):
# Via SCP
scp ext_pydev-*.zip brightsign@${PLAYER_IP}:/storage/sd/
# Verify transfer
ssh brightsign@${PLAYER_IP}
ls -lh /storage/sd/ext_pydev-*.zipCheck available space:
ssh brightsign@${PLAYER_IP}
df -h /usr/local
# Need ~500MB freeCreate installation directory:
mkdir -p /usr/local
cd /usr/localunzip /storage/sd/ext_pydev-*.zipExtracted files:
/usr/local/
├── ext_pydev.squashfs # Compressed filesystem image (~370MB)
├── ext_pydev_install-lvm.sh # Installation script
└── ext_pydev_install-loop.sh # Alternative installer (loop device)
Verify integrity:
ls -lh ext_pydev.squashfs
# Should be ~370MBExecute installation script:
bash ./ext_pydev_install-lvm.shWhat the installer does:
- Creates LVM volume (
/dev/mapper/bsos-ext_pydev) - Copies squashfs image to volume
- Configures auto-mount at
/var/volatile/bsext/ext_pydev - Sets up systemd service for auto-start
- Registers extension with BrightSign OS
Expected output:
Creating LVM volume for extension...
Copying extension image...
Configuring auto-mount...
Installation complete. Reboot required.
Time: ~2-3 minutes
rebootAfter reboot:
- Extension auto-mounts at
/var/volatile/bsext/ext_pydev/ - Service starts automatically
- Available immediately after boot
After reboot, SSH back in:
ssh brightsign@${PLAYER_IP}
# Check extension is mounted
df -h /var/volatile/bsext/ext_pydev
# Check service status
/var/volatile/bsext/ext_pydev/bsext_init status
# Test Python environment
source /var/volatile/bsext/ext_pydev/sh/setup_python_env
python3 -c "import cv2, torch; print('Production ready!')"Updating production extension:
- Build new version on dev host
- Test with development package first
- Create production package:
./package --ext-only
- Transfer to player
- Uninstall old version:
/var/volatile/bsext/ext_pydev/uninstall.sh reboot
- Install new version (follow Step 2-5 above)
Time per update: 10-15 minutes
Deploy custom initialization scripts for automatic package installation and configuration.
Enable user scripts (disabled by default for security):
- Access DWS:
http://<player-ip>:8080 - Go to "Registry" tab
- Enter command:
registry write extension bsext-pydev-enable-user-scripts true - Click "Submit"
- Reboot player for changes to take effect
Why disabled by default: User scripts run as root. Explicit enablement required.
Quick deployment (recommended):
cd user-init/tools
export PLAYER_IP=192.168.1.100
export PASSWORD=password
./deploy-to-player.sh ${PLAYER_IP} ${PASSWORD}Manual deployment:
# Copy files to player
scp user-init/examples/* brightsign@${PLAYER_IP}:/storage/sd/python-init/
# Make scripts executable
ssh brightsign@${PLAYER_IP}
chmod +x /storage/sd/python-init/*.shrequirements.txt (auto-installs Python packages):
# /storage/sd/python-init/requirements.txt
opencv-contrib-python
scikit-learn==1.3.0
requests
Shell scripts (custom initialization):
# /storage/sd/python-init/01_setup_models.sh
#!/bin/bash
mkdir -p /usr/local/models
wget -O /usr/local/models/yolox.rknn https://example.com/yolox.rknnExecution order:
requirements.txt→ auto-install packages*.shscripts → run in alphabetical order
Restart extension (development):
cd /usr/local/pydev
./bsext_init restartReboot player (production):
rebootCheck logs:
# Extension log
cat /var/log/bsext-pydev.log
# Requirements install log
cat /storage/sd/python-init/requirements-install.log
# Custom script logs (if scripts redirect output)
cat /storage/sd/python-init/*.logSee: user-init/README.md for complete guide.
Check if running (production):
/var/volatile/bsext/ext_pydev/bsext_init statusExpected output:
Extension is running (PID: xxxxx)
Start/stop/restart (production):
/var/volatile/bsext/ext_pydev/bsext_init start
/var/volatile/bsext/ext_pydev/bsext_init stop
/var/volatile/bsext/ext_pydev/bsext_init restartRun in foreground (debugging):
/var/volatile/bsext/ext_pydev/bsext_init run
# Ctrl-C to stopQuick validation:
source /var/volatile/bsext/ext_pydev/sh/setup_python_env
# Test Python version
python3 --version
# Test key packages
python3 << 'EOF'
import cv2
import torch
import numpy as np
from rknnlite.api import RKNNLite
print(f"OpenCV: {cv2.__version__}")
print(f"PyTorch: {torch.__version__}")
print(f"NumPy: {np.__version__}")
print("RKNNLite: Available")
print("\nAll packages imported successfully!")
EOFRun test script:
source /var/volatile/bsext/ext_pydev/sh/setup_python_env
/var/volatile/bsext/ext_pydev/sh/test_python_imports --verboseOr Python test:
python3 /var/volatile/bsext/ext_pydev/examples/test_cv_packages.pyTest NPU initialization:
source /var/volatile/bsext/ext_pydev/sh/setup_python_env
python3 << 'EOF'
from rknnlite.api import RKNNLite
rknn = RKNNLite()
print("RKNNLite object created successfully")
# This will show error about model not loaded (expected)
# But proves NPU runtime is accessible
try:
rknn.init_runtime()
except Exception as e:
if "Model is not loaded" in str(e):
print("NPU runtime accessible (model not loaded error is expected)")
else:
print(f"Unexpected error: {e}")
EOFRun complete NPU test (requires model):
# Download test model first
wget https://github.com/airockchip/rknn_model_zoo/releases/download/v2.3.2/yolox_s_rk3588.rknn -O /tmp/test.rknn
# Run test
python3 /var/volatile/bsext/ext_pydev/examples/test_yolox_npu.py /tmp/test.rknn /path/to/image.jpgSimple overwrite:
# Build new package on dev host
./build --extract-sdk
./package --dev-only
# Transfer and extract
scp pydev-*.zip brightsign@${PLAYER_IP}:/storage/sd/
ssh brightsign@${PLAYER_IP}
cd /usr/local/pydev
unzip -o /storage/sd/pydev-*.zip # -o to overwrite
source sh/setup_python_envFull reinstall (recommended):
-
Uninstall old version:
# Copy uninstall script to safe location cp /var/volatile/bsext/ext_pydev/uninstall.sh /tmp/ chmod +x /tmp/uninstall.sh # Run uninstall /tmp/uninstall.sh # Reboot reboot
-
Install new version (after reboot):
cd /usr/local unzip /storage/sd/ext_pydev-NEW.zip bash ./ext_pydev_install-lvm.sh reboot
Method 1: Runtime install (volatile):
source /var/volatile/bsext/ext_pydev/sh/setup_python_env
pip3 install --break-system-packages <package>
# Lost on rebootMethod 2: requirements.txt (auto-install):
echo "<package>==<version>" >> /storage/sd/python-init/requirements.txt
# Installs on next rebootMethod 3: Rebuild SDK (permanent):
# On dev host
# Add recipe to bsoe-recipes/meta-bs/recipes-devtools/python/
./build python3-<package>
./build --extract-sdk
./package
# Deploy new packageSymptoms: ext_pydev_install-lvm.sh fails
Common causes:
-
Player is secured:
# Check ssh brightsign@<player-ip> # If fails, player is secured # Fix: Unsecure via serial console
-
Insufficient space:
df -h /usr/local # Need 500MB+ free # Fix: Remove old files, clear cache
-
LVM volume exists (from previous install):
# Check lvs | grep ext_pydev # Fix: Remove old volume /tmp/uninstall.sh
Symptoms: bsext_init status shows not running
Check logs:
tail -f /var/log/bsext-pydev.logCommon causes:
-
Missing dependencies:
- Check log for import errors
- Verify OS version 9.1.79.3+
-
Permissions:
ls -la /var/volatile/bsext/ext_pydev/bsext_init # Should be executable chmod +x /var/volatile/bsext/ext_pydev/bsext_init -
Mount failed:
mount | grep ext_pydev # Should show mount at /var/volatile/bsext/ext_pydev # Remount mount -a
Symptoms: ModuleNotFoundError
Checklist:
-
Environment sourced:
source /var/volatile/bsext/ext_pydev/sh/setup_python_env echo $PYTHONPATH # Should include extension path
-
Using correct Python:
which python3 # Should show: /var/volatile/bsext/ext_pydev/usr/bin/python3 -
Package in SDK:
ls /var/volatile/bsext/ext_pydev/usr/lib/python3.8/site-packages/ # Check if package directory exists
Symptoms: Scripts in /storage/sd/python-init/ don't execute
Checklist:
-
User scripts enabled:
# Via DWS Registry tab registry read extension bsext-pydev-enable-user-scripts # Should show: true
-
Scripts executable:
ls -la /storage/sd/python-init/*.sh # Should have +x permission chmod +x /storage/sd/python-init/*.sh
-
Check logs:
cat /var/log/bsext-pydev.log # Shows which scripts ran and any errors
Symptoms: Exception: Can not find dynamic library
Causes:
-
OS version too old:
cat /etc/version # Must be 9.1.79.3+ # Fix: Update firmware
-
Library missing:
ls -la /usr/lib/librknnrt.so # Should exist on 9.1.79.3+
See: FAQ.md for more troubleshooting.
- Package transferred to player
- Extracted to
/usr/local/pydev/ - Environment sourced
- Python imports tested
- NPU initialized successfully
- Player unsecured
- Firmware 9.1.79.3+
- Package transferred
- Installer executed successfully
- Player rebooted
- Extension mounted and running
- Service status confirmed
- Python environment tested
- User scripts enabled in registry
- Files deployed to
/storage/sd/python-init/ - Scripts made executable
- Extension restarted
- Logs checked for errors
Next Steps:
- Model Zoo Examples - Run NPU-accelerated inference
- User Init Guide - Custom initialization
- Troubleshooting - Solve common issues