Skip to content

fix: count every per-frame stage in the overall render progress - #42

Merged
smb merged 1 commit into
mainfrom
fix/overall-progress-stages
Sep 4, 2026
Merged

smb merged 1 commit into
mainfrom
fix/overall-progress-stages

Conversation

@smb

@smb smb commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #23

Summary

The overall progress budget was len(timestamps) * 2 while a render runs three per-frame stages. Segmentation filled the first half, encode the second, and post-process reported nothing: it published its own stage progress but left the overall figure untouched. The dialog derives both the frame rate and the remaining time from that figure (ui/source_presentation.py:99-100, remaining = total - completed over a rate sampled from the same counter), so both froze with it. The reporter measured 23:47 remaining, unchanged across 72 seconds, with roughly 18 seconds of work left.

What #27 changed about the fix

Two things make a single multiplier wrong regardless of whether it is two or three.

  • The rebuild path has the same defect, worse. _encode_snapshot is reached from render() and from rebuild(), and rebuild() never set an overall context, so the counter was empty through the whole post-process stage and the encode stage then started a fresh 0..frame_count scale — the bar jumped from nothing to a new maximum mid-job. Since the transform stage exists to make the cheap re-encode the normal path, that is now the progress users see most often.
  • Trimming makes the stages different lengths. transform_stage.stage_encoder_frames stages only transform.kept_range(frame_count), so after a trim segmentation runs over the full grid while post-process and encode run over the kept frames.

The budget

Case Total Stages
Full render timestamps + 2 × kept segmentation, post-process, encode
Transform rebuild 2 × kept post-process, encode
Auto-fit (max_bytes) unchanged encode stays indeterminate; earlier stages report their real share

Observed streams: a two-frame render publishes 1, 2, 2, 3, 4, 4, 6, 6 against a total of 6; a two-frame rebuild publishes 1, 2, 2, 4, 4 against 4. Non-decreasing, and exactly at the total when the job ends.

Deliberately not done

The issue's closing note suggests weighting the stages, since they run at roughly 0.7, 5.3 and 1 frames per second. Not taken here: the measured defect is a counter that stops and an estimate that stops being recomputed, and honest unit counting fixes both. An estimate that is imprecise because the stages differ in rate is a smaller, separate question, and better answered with numbers from the fixed build than guessed at now.

jobs/render.py shrinks from 2938 to 2871 lines in the baseline.

Test plan

  • uv run ruff check . && uv run mypy src && QT_QPA_PLATFORM=offscreen uv run pytest -q: 1781 passed, 4 skipped.
  • New tests assert the recorded ProgressEvent stream for a full render, a trimmed render, a transform rebuild, and an auto-fit render, plus the framing helper in isolation.

🤖 Generated with Claude Code

The overall budget was len(timestamps) * 2 while a render runs three
per-frame stages. Segmentation filled the first half, encode the
second, and post-process reported nothing at all: it published its own
stage progress but left the overall figure untouched. The dialog
derives both the frame rate and the remaining time from that figure, so
both froze with it. The reporter measured 23:47 remaining, unchanged
across 72 seconds, while about 18 seconds of work were left.

Two things the transform stage changed since the issue was filed make a
single multiplier wrong in any case. The rebuild path reaches the same
code without ever setting an overall context, so its counter was empty
through post-process and then started a fresh scale at encode; that is
now the common path, because rebuilding is what a transform edit does.
And post-process stages only the kept frames, so after a trim the three
stages have different lengths.

The budget is therefore computed from the work the job will do:
timestamps plus twice the kept count for a render, twice the kept count
for a rebuild, with each stage occupying its own share. Auto-fit still
reports the encode stage as indeterminate, since the number of attempts
is unknown.

Deliberately not weighting the stages by their measured rates. The
defect is a counter that stops and an estimate that stops being
recomputed; honest counting fixes both, and an imprecise estimate is a
smaller, separate question best answered with numbers from the fixed
build.

Closes #23

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@smb
smb merged commit ecf63f4 into main Sep 4, 2026
11 checks passed
@smb
smb deleted the fix/overall-progress-stages branch September 4, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overall render progress omits the post-process stage, freezing the rate and the time estimate

1 participant