111 lines
3.0 KiB
Bash
111 lines
3.0 KiB
Bash
#!/bin/sh
|
|
|
|
# Low-confidence snapshot helper for yolov5 inference.
|
|
# Expected arguments:
|
|
# 1 source RTSP URL or local video file path from yolov5 -s
|
|
# 2 camera_id Camera id from yolov5 -c
|
|
# 3 timestamp Unix timestamp of the detection event
|
|
# 4 class_name Detected class name
|
|
# 5 confidence Detection confidence
|
|
# 6 left Box left
|
|
# 7 top Box top
|
|
# 8 right Box right
|
|
# 9 bottom Box bottom
|
|
#
|
|
# The script prints status lines to stdout/stderr. The inference program should
|
|
# capture those lines and write them into its own detect log.
|
|
|
|
SOURCE="$1"
|
|
CAMERA_ID="$2"
|
|
TS="$3"
|
|
CLASS_NAME="$4"
|
|
CONF="$5"
|
|
LEFT="$6"
|
|
TOP="$7"
|
|
RIGHT="$8"
|
|
BOTTOM="$9"
|
|
|
|
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
|
SNAPSHOT_TIMEOUT="${SNAPSHOT_TIMEOUT:-15}"
|
|
LOG_ROOT="${LOG_ROOT:-${SCRIPT_DIR}/.log}"
|
|
SNAPSHOT_DAY="$(date -d "@${TS}" "+%Y-%m-%d" 2>/dev/null || date "+%Y-%m-%d")"
|
|
SNAPSHOT_ROOT="${SNAPSHOT_ROOT:-${LOG_ROOT}/snapshots/${SNAPSHOT_DAY}}"
|
|
|
|
now_text() {
|
|
date "+%Y-%m-%d %H:%M:%S"
|
|
}
|
|
|
|
log_info() {
|
|
echo "$(now_text) low_conf_snapshot INFO $*"
|
|
}
|
|
|
|
log_error() {
|
|
echo "$(now_text) low_conf_snapshot ERROR $*" >&2
|
|
}
|
|
|
|
sanitize() {
|
|
echo "$1" | tr -c 'A-Za-z0-9_.-' '_'
|
|
}
|
|
|
|
if [ "$#" -lt 9 ]; then
|
|
log_error "invalid arguments: expected 9, got $#"
|
|
log_error "usage: $0 <source> <camera_id> <timestamp> <class_name> <confidence> <left> <top> <right> <bottom>"
|
|
exit 2
|
|
fi
|
|
|
|
if ! command -v ffmpeg >/dev/null 2>&1; then
|
|
log_error "ffmpeg not found"
|
|
exit 127
|
|
fi
|
|
|
|
CLASS_SAFE="$(sanitize "$CLASS_NAME")"
|
|
CONF_SAFE="$(sanitize "$CONF")"
|
|
BOX_SAFE="$(sanitize "${LEFT}_${TOP}_${RIGHT}_${BOTTOM}")"
|
|
OUT_DIR="${SNAPSHOT_ROOT}"
|
|
OUT_FILE="${OUT_DIR}/${TS}_${CAMERA_ID}_${CLASS_SAFE}_${CONF_SAFE}_${BOX_SAFE}.jpg"
|
|
|
|
if ! mkdir -p "$OUT_DIR"; then
|
|
log_error "failed to create output dir: $OUT_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "start source=\"$SOURCE\" camera_id=\"$CAMERA_ID\" ts=\"$TS\" class=\"$CLASS_NAME\" conf=\"$CONF\" box=($LEFT $TOP $RIGHT $BOTTOM)"
|
|
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
TIMEOUT_CMD="timeout ${SNAPSHOT_TIMEOUT}"
|
|
else
|
|
TIMEOUT_CMD=""
|
|
fi
|
|
|
|
case "$SOURCE" in
|
|
rtsp://*|RTSP://*)
|
|
# For RTSP streams, capture one live frame from the camera.
|
|
# shellcheck disable=SC2086
|
|
$TIMEOUT_CMD ffmpeg -y -rtsp_transport tcp -i "$SOURCE" -frames:v 1 -q:v 2 "$OUT_FILE" >/tmp/low_conf_snapshot_ffmpeg.log 2>&1
|
|
RET=$?
|
|
;;
|
|
*)
|
|
# For local mp4/h264 test files, capture the first decodable frame.
|
|
# shellcheck disable=SC2086
|
|
$TIMEOUT_CMD ffmpeg -y -i "$SOURCE" -frames:v 1 -q:v 2 "$OUT_FILE" >/tmp/low_conf_snapshot_ffmpeg.log 2>&1
|
|
RET=$?
|
|
;;
|
|
esac
|
|
|
|
if [ "$RET" -ne 0 ]; then
|
|
log_error "ffmpeg failed ret=$RET output=\"$OUT_FILE\""
|
|
if [ -f /tmp/low_conf_snapshot_ffmpeg.log ]; then
|
|
sed 's/^/ffmpeg: /' /tmp/low_conf_snapshot_ffmpeg.log >&2
|
|
fi
|
|
rm -f "$OUT_FILE"
|
|
exit "$RET"
|
|
fi
|
|
|
|
if [ ! -s "$OUT_FILE" ]; then
|
|
log_error "snapshot file is empty or missing: $OUT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "saved output=\"$OUT_FILE\""
|
|
exit 0
|