[BUG] First run on an empty model cache: every camera worker downloads and converts the same model at once, one worker fails, and the posthoc pipeline waits forever (2.0.0-alpha.23)
Hi all, second report from the same RTMPose evaluation (see #886 for the first). We processed a six-camera recording through alpha.23 on a fresh install, and the very first run stalled. Worth a report because anyone processing six or more cameras on a new machine will hit it.
Describe the bug
The posthoc pipeline starts one VideoNode per camera at the same time. On a cold cache each of them downloads and converts the same model files into the shared cache. They race each other, one of them reads a half-written file and dies while building its session, and the aggregator then waits for a worker that will never report. The pipeline stays alive, so a headless caller never returns and the UI never shows completion.
We hit it on both tracker paths:
- RTMPose (ONNX models in
~/.cache/skellytracker/models/), six workers, one dies:
Unhandled exception in ManagedThread VideoNode-Camera_5: Failed to load model 'yolox-m' with provider='coreml': [ONNXRuntimeError] : 1 : FAIL : Load model from /Users/.../.cache/skellytracker/models/yolox_m_8xb8-300e_humanart-c2c7a14a.onnx.prenms.onnx failed: ... onnxruntime::Model::Model(...) ModelProto does not have a graph.
skellytracker.core.sessions.session_errors.SessionCreationError: Failed to load model 'yolox-m' with provider='coreml' ... The other five reported "session ready" and kept detecting. "ModelProto does not have a graph" is what a partially written .prenms.onnx looks like while another worker is still converting it.
- MediaPipe (
.taskfiles in~/.freemocap/skellytracker-models/), six workers, the temp-file rename collides:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/.../.freemocap/skellytracker-models/00b93401_pose_landmarker_full.tmp' -> '/Users/.../.freemocap/skellytracker-models/00b93401_pose_landmarker_full.task'In that case the run reported completion with no output files at all.
- MediaPipe with the default HEAVY model, six workers, cold cache: the race surfaced as a model-build error rather than a file error, because one worker read the
.taskwhile another was still writing it:
RuntimeError: Could not build model from the provided pre-loaded flatbuffer: Input tensor 286 to op 187 (DENSIFY) is not producedWe first read this as an Apple Silicon incompatibility with the heavy model. It is not: on a warm cache the same HEAVY model loads and runs on one camera and on six (300 frames x 6 cameras in 23 s). So the race can also masquerade as a platform or model bug, which may be worth knowing when triaging reports.
To Reproduce
- Empty (or start without)
~/.cache/skellytracker/models/and~/.freemocap/skellytracker-models/. - Process a six-camera recording with the posthoc pipeline (either detector).
- Watch the per-worker logs: several "downloading" lines for the same model, then one
SessionCreationError(RTMPose) orFileNotFoundErroron the.tmprename (MediaPipe).
Expected: one download and conversion per model, then all workers load it. Actual: as above, and the pipeline never finishes.
What works around it here
Build one skeleton session in a single process before starting the pipeline (build_skeleton_onnx_session(batch_size=1, model_name=...) for RTMPose, or a one-camera MediaPipe run first). Once the cache is warm, six-camera runs are clean every time (4.9 minutes for 2700 frames x 6 cameras on an M4 with CoreML).
Suggested fix
Any of these would do, in increasing order of thoroughness: download and convert the models in the pipeline manager before spawning the VideoNodes; take a per-model file lock around download-and-convert with a "skip if the final file already exists" check (write to a unique temp name, then rename); and treat a dead VideoNode as a pipeline failure so the aggregator errors out instead of waiting forever.
Log
Excerpts above; the full logs are available on request.
Environment Information:
- OS: macOS 26.6.2, Apple Silicon (M4, 16 GB)
- Python Version: 3.12.14
- Freemocap Version: v2.0.0-alpha.23 from the GitHub tag with
uv sync --frozen(skellytracker cb739aa, onnxruntime 1.28.0 with CoreML, mediapipe 0.10.33) - Are you running
freemocapin a virtual environment?: yes (uv .venv) - Blender Version (If applicable): n/a
Additional context
A smaller thing we noticed in the same runs, mentioned here rather than as its own issue: with WorkerMode.THREAD, the interpreter stays alive after "Posthoc mocap complete" and manager.shutdown(); something in the worker threads is non-daemon. That may only matter for headless callers like us.
Source: freemocap/freemocap