fix(diashow): never project a video, however its poster turned out
`merge` decided by whether a usable still existed, so the same clip was included or dropped depending on whether ffmpeg happened to extract a poster — a video WITH a thumbnail was queued and shown as a frozen frame, one without was skipped. Keyed on the mime type instead: the projector shows stills only. The test factory casts through `as unknown as FeedUpload`, so adding a field the queue reads does not fail typechecking — it fails at runtime, which is how this surfaced as ten broken tests rather than a compile error. The factory now carries `mime_type` and the comment says why keeping it in step matters. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,14 +26,25 @@ export class SlideQueue {
|
||||
private recentlyShown: string[] = [];
|
||||
|
||||
/**
|
||||
* Add uploads, de-duplicated by id. Only *displayable* items (preview- or
|
||||
* thumbnail-ready) are kept — a still-compressing upload has no image yet, so it's
|
||||
* skipped until a later sync brings it with a preview. `live` items jump onto the live
|
||||
* queue (shown next); otherwise they join the shuffle pool. Returns the count newly added.
|
||||
* Add uploads, de-duplicated by id. `live` items jump onto the live queue (shown next);
|
||||
* otherwise they join the shuffle pool. Returns the count newly added.
|
||||
*
|
||||
* Two things are skipped:
|
||||
*
|
||||
* 1. **Videos, deliberately and by mime type.** The projector shows stills only — a clip
|
||||
* would either hold the slide for its full duration or be cut off mid-way, and it has
|
||||
* no audio path on a room's screen. This used to happen only ACCIDENTALLY, as a side
|
||||
* effect of the derivative check below: a video whose poster frame extracted fine has
|
||||
* a `thumbnail_url` and so was shown as a still frame, while one whose extraction
|
||||
* failed was dropped — the same upload included or excluded depending on whether
|
||||
* ffmpeg happened to find a frame. Now the rule is the mime type, so it is consistent.
|
||||
* 2. **Images with no derivative yet.** A still-compressing photo has no image to show;
|
||||
* it is picked up by a later sync once its preview exists.
|
||||
*/
|
||||
merge(uploads: FeedUpload[], opts: { live: boolean }): number {
|
||||
let added = 0;
|
||||
for (const u of uploads) {
|
||||
if (u.mime_type.startsWith('video/')) continue;
|
||||
if (!u.preview_url && !u.thumbnail_url) continue;
|
||||
if (this.allKnown.has(u.id)) continue;
|
||||
this.allKnown.set(u.id, u);
|
||||
|
||||
Reference in New Issue
Block a user