Skip to content

fix: un-stick federated video posters — emit asset-arrived for the regenerated thumbnail and name it from the history row - #4306

Merged
atomantic merged 1 commit into
mainfrom
claim/issue-4162
Aug 15, 2026
Merged

fix: un-stick federated video posters — emit asset-arrived for the regenerated thumbnail and name it from the history row#4306
atomantic merged 1 commit into
mainfrom
claim/issue-4162

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

A federated video poster never un-stuck from MediaImage's "Syncing" placeholder. Two independent defects in doPullOneAsset (server/services/sharing/peerSyncAssets.js), both fixed here:

  • No arrival event for the thumbnail. The receiver-side pull emitted asset-arrived once — for the .mp4 — then regenerated the video's thumbnail with no matching emit. MediaImage matches arrivals on filename alone, so a poster <img> that had already 404'd stayed on the placeholder until a remount even though the bytes were on disk. The regenerated thumbnail now gets its own asset-arrived (kind: 'video-thumbnail').
  • Wrong thumbnail name for a stitched final. The name was derived from the mp4 basename. That is only coincidentally correct for a videoGen clip (<jobId>.mp4 beside thumbnail: '<jobId>.jpg'); server/services/videoTimeline/local.js writes a stitched timeline final as timeline-<projectId-slice>-<ts>.mp4 beside an independent randomUUID() history id, and every poster URL the UI builds is /data/video-thumbnails/<row.id>.jpg. So the regenerated file landed under a name nothing ever requests. The name now comes from the synced history row's thumbnail field, resolved by video filename via a new videoThumbnailNameForVideo() reader.

Details worth noting:

  • The row rides the wire from a peer, so its thumbnail goes through sanitizeAssetFilename before it can become a path segment; a traversal-shaped value falls back to the stem rather than escaping data/video-thumbnails/.
  • The mp4 stem stays the fallback for the window where the asset bytes beat the videoHistory metadata category across — that is the pre-existing behavior, so this is strictly additive and can't regress the clip case.
  • The two video-history.json readers in this module now share one readVideoHistoryRows() helper.

Closes #4162

Test plan

  • New server/services/sharing/peerSyncAssets.videoThumbnail.test.js (5 cases): timeline-final naming from the history row, videoGen-clip arrival emit, stem fallback when the row has not synced, traversal-shaped thumbnail rejected, and no thumbnail arrival when regeneration returns null (ffmpeg missing). Verified the 3 behavior cases fail against the pre-fix source and pass after.
  • cd server && NODE_ENV=test npx vitest run services/sharing/ — 22 files, 579 tests pass.
  • cd server && NODE_ENV=test npm test — 29489 pass. The only failures are 2 pre-existing, environment-dependent cases in routes/health.test.js, confirmed failing identically on a clean main checkout.

…d name it from the history row (#4162)

doPullOneAsset regenerated a pulled video's thumbnail but emitted
`asset-arrived` only for the .mp4, so MediaImage's filename-keyed listener
never fired for the poster and a federated Creative Director card sat on the
"Syncing" placeholder until a remount.

The name was also derived from the mp4 basename. That is only coincidentally
right for a videoGen clip (`<jobId>.mp4` beside `thumbnail: '<jobId>.jpg'`) and
flatly wrong for a stitched timeline final, which videoTimeline/local.js writes
as `timeline-<slice>-<ts>.mp4` beside an independent randomUUID history id — so
the regenerated file landed under a name no poster URL ever requests. The name
now comes from the synced history row's `thumbnail` field (sanitized, since it
rode the wire from a peer), falling back to the mp4 stem for the window where
the bytes beat the videoHistory metadata category across.
@atomantic
atomantic merged commit ad6ba10 into main Aug 15, 2026
7 checks passed
@atomantic
atomantic deleted the claim/issue-4162 branch August 15, 2026 19:11
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.

Federated video poster never un-sticks from 'Syncing' (thumbnail name/event mismatch)

1 participant