mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
ffmpeg opens every run with ~20 lines of version and build banner and prints its diagnosis last, so the stderr[:200] eight of the nine call sites used kept the banner and threw the error away. The reporter's twelve capture failures all read "ffmpeg version 7.1.4 ... configuration: --prefix=/usr --extra-version=", identical on every install; the exit code was the only usable byte. The banner-stripping summariser written for #925 lived private to the camera route. It now lives in backend/app/utils/ffmpeg_output.py and every ffmpeg and ffprobe stderr goes through it. Two things the scattered copies also got wrong: four logged the input URL unmasked, publishing a printer access code or camera password, and four called a bare .decode() on bytes ffmpeg copies stream fragments into. ----- Delete the files a no-3MF archive owns, without taking a printer folder Both delete paths derived the directory from file_path, which such an archive does not have, so they removed nothing and logged it at ERROR under a SECURITY banner. That was true when the archive was an empty row and stopped being true once one could hold a timelapse and finish photos in <archive_dir>/<id>/ and an uploaded source in archive/no_source/<id>/. The two are cleaned up by different means, because <archive_dir>/<id> shares a namespace with the per-printer folders: a normal archive lives at <archive_dir>/<printer_id>/<timestamp>_<name>/, so archive/1 is printer 1's folder and also the directory the shared helper hands archive id 1. Ids come from unrelated sequences, so the first few archives collide with the printers on every install, and an rmtree there takes every print that printer made -- measured on a scratch tree. no_source/<id> is a level deeper under a name no printer id can take and is removed whole; the id-named directory gives up only its photos subdirectory and the video the row records, then goes only if that left it empty. The depth guard moves from one to two for the same reason: a file_path that lost a path component could point the delete at a printer folder, and no archive directory has been one level deep since the first commit. Hard delete had its own copy of these rules, which the helper's docstring says it exists to prevent, and it had diverged -- it skipped the print-log thumbnail cleanup whenever a guard tripped. ----- Stop the RTSPS proxy leaving a handler behind at shutdown asyncio.start_server keeps only a weak reference to the connection callback's task, so a handler still awaiting its forwarders could be collected while pending -- "Task was destroyed but it is pending!", at ERROR with a traceback into camera.py, once every few hundred snapshots. Teardown had the matching gap: server.close() leaves established connections running, so the close waited on a handler that only finishes when the peer drops, and ffmpeg has already been reaped by then. Handlers are held for as long as they run and cancelled at shutdown, which is Server.close_clients() by hand -- that landed in 3.13 and Bambuddy supports 3.10. Both the snapshot path and the streaming endpoint share the shutdown.