LOAD MP4 on an OUTPUT_DIR file copies it into UPLOAD_DIR (chunked, progress via /api/copy-progress) before spawning RECOUNT_CMD; collision in UPLOAD_DIR fails with 400. New read-only folder-grouped browser mirrors recounting_dashboard.py. Docs updated.
198 lines
8.5 KiB
Bash
198 lines
8.5 KiB
Bash
# =============================================================================
|
||
# Edge RK3588 production counter + dashboard
|
||
# Shared config for: counter_live_rknn_bytetrack.py + counter_dashboard.py
|
||
# Copy to .env on device: cp config.env.example .env && nano .env
|
||
# =============================================================================
|
||
|
||
# --- Core paths ---
|
||
# Root output directory (logs, DB, video, CSV)
|
||
OUTPUT_DIR=/opt/bytetrack-counter
|
||
# SQLite database path for batch entries & crossing logs
|
||
DB_PATH=/opt/bytetrack-counter/bytetrack_counter.db
|
||
# JSON file persisting the current active batch state
|
||
STATE_FILE=/tmp/bytetrack_current_batch.json
|
||
# Shared memory directory used for reset signal (touch .reset to clear counter state)
|
||
SHM_DIR=/dev/shm/bytetrack-counter
|
||
|
||
# --- Input source ---
|
||
# RTSP / HTTP live stream, or a local video file path
|
||
SOURCE=rtsp://user:pass@192.168.0.100:554/stream1
|
||
# FFmpeg capture options passed to cv2.VideoCapture (RTSP low-latency flags)
|
||
OPENCV_FFMPEG_CAPTURE_OPTIONS=rtsp_transport;tcp|fflags;nobuffer|flags;low_delay
|
||
|
||
# --- RKNN model ---
|
||
# Path to exported .rknn model (YOLO format, e.g. yolo11n.rknn)
|
||
MODEL_PATH=/opt/models/yolo9t.rknn
|
||
# Input image size for the model (square, e.g. 320 → 320×320)
|
||
IMGSZ=320
|
||
# Use FP16 inference on NPU (true/false); currently unused in ByteTrack variant
|
||
HALF=false
|
||
# NPU core mask: 1=core0, 2=core1, 3=core0+core1, 7=all three
|
||
CORE_MASK=7
|
||
# Compute device index (reserved; not used at runtime)
|
||
DEVICE=0
|
||
|
||
# --- YOLO decoder ---
|
||
# Number of object classes the model outputs (e.g. 2 = ayam + talenan)
|
||
NUM_CLASSES=2
|
||
# Apply sigmoid to raw class scores (true/false); set true if model head uses BCE logits
|
||
SCORE_SIGMOID=false
|
||
|
||
# --- Detection ---
|
||
# Confidence threshold – detections below this are discarded before NMS
|
||
CONF=0.3
|
||
|
||
# --- ByteTrack tracking ---
|
||
# General for ayam, index 0
|
||
# Detections with score ≥ this get priority matching in the first association stage
|
||
TRACK_HIGH_THRESH_0=0.5
|
||
# Detections with score between this and TRACK_HIGH_THRESH are matched in the second stage
|
||
TRACK_LOW_THRESH_0=0.1
|
||
# IoU threshold for the first-stage association (0–1). Higher = stricter overlap required
|
||
TRACK_MATCH_THRESH_0=0.8
|
||
# Frames a track survives without a match before being permanently removed
|
||
TRACK_BUFFER_0=30
|
||
# Minimum consecutive (or total) hits needed before a track is considered confirmed
|
||
TRACK_MIN_HITS_0=3
|
||
|
||
# For talenan, index 1
|
||
# Detections with score ≥ this get priority matching in the first association stage
|
||
TRACK_HIGH_THRESH_1=0.5
|
||
# Detections with score between this and TRACK_HIGH_THRESH are matched in the second stage
|
||
TRACK_LOW_THRESH_1=0.1
|
||
# IoU threshold for the first-stage association (0–1). Higher = stricter overlap required
|
||
TRACK_MATCH_THRESH_1=0.6
|
||
# Frames a track survives without a match before being permanently removed
|
||
TRACK_BUFFER_1=30
|
||
# Minimum consecutive (or total) hits needed before a track is considered confirmed
|
||
TRACK_MIN_HITS_1=3
|
||
|
||
# --- Display ---
|
||
# Site name shown on the dashboard header (top-right)
|
||
SITE_NAME=ZenAi
|
||
|
||
# --- Object class names ---
|
||
# Camera / location identifier shown in HUD and stored in DB
|
||
CAMERA_NAME=ZenAi
|
||
# Label used for batch grouping in the database
|
||
OBJECT_LABEL=ayam-potong
|
||
# Class name for the counted object (must match NUM_CLASSES order, index 0)
|
||
CLASS_AYAM=ayam
|
||
# Class name for the batch-closing trigger object (must match NUM_CLASSES order, index 1)
|
||
CLASS_TALENAN=talenan
|
||
|
||
# --- Line crossing ---
|
||
# Direction for counting: rtl (right-to-left, default) | ltr (left-to-right) | both
|
||
CROSS_DIRECTION=rtl
|
||
# Fixed x-coordinate for the counting line (overrides LINE_X_FRAC if set)
|
||
LINE_X=
|
||
# Fraction of frame width where the counting line is drawn (default 0.5 = centre)
|
||
LINE_X_FRAC=0.5
|
||
|
||
# --- Batch management ---
|
||
# Daily cutoff time (HH:MM) – a new day's batch numbering starts after this time.
|
||
# CUTOFF_TIME is an alias used by the dashboard; DAILY_CUTOFF_TIME takes priority in counter_live_rknn_bytetrack.py.
|
||
DAILY_CUTOFF_TIME=20:00
|
||
CUTOFF_TIME=20:00
|
||
# Reset frame counter and ByteTrack track-ID counter back to 0 when the daily cutoff is reached (true/false, default: true)
|
||
RESET_COUNTERS_AT_CUTOFF=true
|
||
# Seconds of inactivity after which the current batch is auto-closed
|
||
BATCH_TIMEOUT_SECONDS=300
|
||
# Seconds a newly-opened batch ignores the talenan label before accepting a close trigger
|
||
IGNORE_BATCH_LABEL_TIMEOUT_SECONDS=30
|
||
# Minimum number of objects required for a batch to be saved as valid
|
||
MIN_OBJECT_PER_BATCH=60
|
||
# Minimum duration in seconds a batch must be open to be saved as valid
|
||
MIN_DURATION_PER_BATCH=60
|
||
|
||
# --- CSV export ---
|
||
# Write per-crossing events to a CSV file (true/false)
|
||
EXPORT_CSV=true
|
||
# Path where the crossing CSV is written
|
||
CROSS_CSV=/opt/batch-counter/batch_crossings.csv
|
||
|
||
# --- Rate / performance ---
|
||
# Enable motion detection pre-filter: skip inference on frames with no movement
|
||
# (true/false, default: false). When enabled, frames below MOTION_THRESHOLD are
|
||
# skipped, saving NPU/CPU load.
|
||
MOTION_DETECTION_ENABLED=false
|
||
# Mean absolute pixel difference threshold (0–255) to consider a frame as having
|
||
# motion. Lower = more sensitive. Default 5.0.
|
||
MOTION_THRESHOLD=5.0
|
||
# Sliding window in seconds for computing the crossing rate (objects/minute)
|
||
RATE_WINDOW_SEC=60
|
||
# Number of frames to discard at startup to let the stream buffer stabilise
|
||
WARMUP_FRAMES=30
|
||
# Delay in seconds between stream reconnection attempts
|
||
RECONNECT_DELAY_SEC=3
|
||
# Maximum reconnection attempts (0 = infinite)
|
||
MAX_RECONNECT_ATTEMPTS=0
|
||
# Print status log every N processed frames
|
||
FLUSH_EVERY_N_FRAMES=100
|
||
# Seconds after which a tracked but unseen object is pruned from the active set
|
||
TRACKED_PRUNE_SEC=300
|
||
|
||
# --- Video recording ---
|
||
# Save annotated frames to segmented MP4 files (true/false)
|
||
RECORD_VIDEO=false
|
||
# Duration in seconds of each video segment file
|
||
VIDEO_SEGMENT_SEC=3600
|
||
# Output video FPS (fallback if source FPS is unknown or ≤ 1)
|
||
OUTPUT_FPS=15
|
||
|
||
# --- Live stream snapshot ---
|
||
# Periodically write the latest annotated frame as JPEG for an external web server
|
||
LIVE_STREAM_ENABLED=false
|
||
# Path to the shared-memory snapshot file (served by nginx / lighttpd)
|
||
LIVE_STREAM_FRAME_PATH=/dev/shm/byetrack-counter/live_frame.jpg
|
||
# JPEG quality (1–100)
|
||
LIVE_STREAM_QUALITY=75
|
||
# Write the snapshot every N frames (lower = more frequent updates)
|
||
LIVE_STREAM_EVERY_N=2
|
||
|
||
# --- Dashboard (counter_dashboard.py) ---
|
||
# Template file: "dashboard.html" (default), "dashboard_lamborghini.html", or "dashboard_tesla.html"
|
||
DASHBOARD_TEMPLATE=dashboard.html
|
||
# Flask secret key for session/cookie signing — change in production!
|
||
SECRET_KEY=change-me-in-production
|
||
# Bind address for the Flask web server
|
||
DASHBOARD_HOST=0.0.0.0
|
||
# Listen port for the dashboard web UI
|
||
DASHBOARD_PORT=5000
|
||
# URL of the upload recounting dashboard (recounting_dashboard_upload.py); empty hides the header link
|
||
UPLOAD_DASHBOARD_URL=http://localhost:5003
|
||
# Enable Flask debug mode (true/false) — auto-reloads on code changes; disable in production
|
||
FLASK_DEBUG=false
|
||
# Fallback name for the active-batch JSON state file used by the dashboard
|
||
CURRENT_BATCH_PATH=/tmp/bytetrack_current_batch.json
|
||
|
||
# --- Recounting Dashboard (recounting_dashboard.py) ---
|
||
# Bind address and port
|
||
RECOUNTING_DASHBOARD_PORT=5002
|
||
# Base URL of the live counter dashboard API (same host)
|
||
LIVE_API_URL=http://localhost:5000
|
||
# Base URL of the recounting counter dashboard API (second node)
|
||
RECOUNT_API_URL=http://localhost:5001
|
||
# go2rtc base URL for consuming MJPEG stream (browser-facing)
|
||
GO2RTC_URL=http://localhost:1984
|
||
# RTSP port used by ffmpeg for pushing stream to go2rtc
|
||
RTSP_PORT=8554
|
||
# Stream name pushed to RTSP and consumed from go2rtc
|
||
RECOUNT_STREAM_NAME=stream_1
|
||
|
||
# --- Recounting Upload Dashboard (recounting_dashboard_upload.py) ---
|
||
# Bind port for the upload-first recount dashboard (distinct from 5002)
|
||
RECOUNTING_UPLOAD_PORT=5003
|
||
# Directory where uploaded MP4 files are stored
|
||
UPLOAD_DIR=/opt/bytetrack-counter/uploads
|
||
# Directory scanned for the "From Output Directory" file browser (folder-grouped MP4s).
|
||
# Selecting one of those files and pressing LOAD MP4 copies it into UPLOAD_DIR first.
|
||
OUTPUT_DIR=/opt/bytetrack-counter
|
||
# Command launched by LOAD MP4 (bytetrack-counter-cpp); {path} is the uploaded MP4.
|
||
# The process loads + pauses until START RECOUNT touches {SHM_DIR}/.continue.
|
||
RECOUNT_CMD=bytetrack-counter-cpp config.env --source {path}
|
||
# Template file for the upload dashboard: "recounting_upload_lamborghini.html" (default) or "recounting_upload.html"
|
||
RECOUNTING_UPLOAD_TEMPLATE=recounting_upload_lamborghini.html
|
||
# URL of the live counter dashboard (counter_dashboard.py); empty hides the header link
|
||
LIVE_DASHBOARD_URL=http://localhost:5000
|