@@ -9,12 +9,7 @@ export interface VideoThumbnailDecodeRequest {
99 fit ?: "contain" | "cover" ;
1010}
1111
12- /**
13- * The times a strip of `frameCount` slices shows: each slice's left edge, so a strip twice as long
14- * holds every frame of this one, then the clip's last frame. A poster is the midpoint.
15- */
16- // Inside the last frame: a time at the very end of a file can decode to nothing.
17- const END_FRAME_LEAD_S = 0.001 ;
12+ const LAST_FRAME_INSET_S = 0.001 ;
1813
1914export function videoThumbnailTimestamps (
2015 start : number ,
@@ -29,10 +24,9 @@ export function videoThumbnailTimestamps(
2924 { length : count } ,
3025 ( _ , index ) => safeStart + ( safeDuration * index ) / count ,
3126 ) ;
32- return [ ...edges , safeStart + Math . max ( 0 , safeDuration - END_FRAME_LEAD_S ) ] ;
27+ return [ ...edges , safeStart + Math . max ( 0 , safeDuration - LAST_FRAME_INSET_S ) ] ;
3328}
3429
35- /** A decoded frame, shared by every strip of its source that would accept it for a time. */
3630interface SharedFrame {
3731 url : string ;
3832 decodedAt : number ;
@@ -44,11 +38,9 @@ interface HeldFrame {
4438 frame : SharedFrame ;
4539}
4640
47- /** A strip takes a frame decoded inside its range, at most `lead` before the time it shows. */
4841interface FrameWindow {
4942 sourceStart : number ;
5043 lead : number ;
51- /** The clip's last frame, shown as decoded at its own time, never from an earlier keyframe. */
5244 end : number ;
5345}
5446
@@ -64,7 +56,6 @@ function takeSharedFrame(key: string, time: number, window: FrameWindow): Shared
6456 return frame ;
6557}
6658
67- /** Shares a newly decoded frame, or the same frame another strip decoded meanwhile. */
6859function shareFrame ( key : string , decodedAt : number , url : string ) : SharedFrame {
6960 const frames = sharedFrames . get ( key ) ?? [ ] ;
7061 const existing = frames . find ( ( shared ) => shared . decodedAt === decodedAt ) ;
@@ -102,9 +93,7 @@ async function canvasToBlob(canvas: HTMLCanvasElement | OffscreenCanvas): Promis
10293}
10394
10495interface DecodedResources {
105- /** One frame per slot of the strip; a slot the source could not decode stays empty. */
10696 urls : ( string | undefined ) [ ] ;
107- /** The shared frames this strip holds, released when the strip is. */
10897 held : HeldFrame [ ] ;
10998 canvases : Set < HTMLCanvasElement | OffscreenCanvas > ;
11099}
@@ -115,7 +104,6 @@ interface ThumbnailCanvasSink {
115104 ) : AsyncIterable < { canvas : HTMLCanvasElement | OffscreenCanvas } | null > ;
116105}
117106
118- /** What a strip of a source needs before it can name its frames. */
119107interface SourceInfo {
120108 aspect : number ;
121109 metadataDuration : number | null ;
@@ -149,7 +137,6 @@ function targetDimensions(
149137 } ;
150138}
151139
152- /** The strip's frame times, clamped to what the file holds, and the frames it accepts for them. */
153140function stripTimes (
154141 request : VideoThumbnailDecodeRequest ,
155142 info : SourceInfo ,
@@ -181,7 +168,6 @@ function stripTimes(
181168 return { window, timestamps } ;
182169}
183170
184- /** Holds every frame of the strip already decoded; returns the slots still to decode. */
185171function takeDecodedFrames (
186172 { timestamps, window } : ReturnType < typeof stripTimes > ,
187173 keyOf : ( time : number ) => string ,
@@ -240,10 +226,7 @@ function loadedResult(
240226 } ;
241227}
242228
243- /**
244- * Sparse Mediabunny extraction with one pooled canvas and one cleanup owner. Frames another strip
245- * of the source already shows are reused, so a zoom decodes only the frames that are new.
246- */
229+ /** Sparse Mediabunny extraction with one pooled canvas and one cleanup owner. */
247230export async function decodeVideoThumbnail (
248231 request : VideoThumbnailDecodeRequest ,
249232 signal : AbortSignal ,
0 commit comments