Makes what the server derives from an upload with ffmpeg: a video's still, which the thumbnails route serves, an audio file's waveform, which the waveform route serves, and the scaled-down copies of any image, which serveImage (lib/upload.ts) serves for every route that answers one. Each is made on its first request and kept under a name this module gives, a dump's in THUMBNAILS_DIR and the scaled copies in SCALED_DIR, until dump-service replaces or deletes the upload and removeGeneratedMedia drops them. generatedMediaSweepJob takes what that leaves behind.

Functions

f
audioWaveform(
srcPath: string,
outPath: string
): Promise<void>

Writes the waveform of the audio file srcPath as the waveform route's whole response, so the route serves it as a file, with its ETag.

f
ensureGenerated(
outPath: string,
generate: () => Promise<void>,
srcPath?: string
): Promise<boolean>

Makes outPath with generate unless it exists. Resolves false when it can't be made, because ffmpeg is missing or failed.

f
generatedPaths(dumpId: string): { still: string; waveform: string; }

Returns where the still and the waveform generated from dump dumpId's upload are kept.

f
removeGeneratedMedia(dumpId: string): Promise<void>

Deletes what was generated from dump dumpId's upload, once dump-service has replaced or deleted it. The routes make them again from a new one.

f
removeScaledImages(srcPath: string): Promise<void>

Deletes the scaled copies of the upload at srcPath, once it is deleted. One that is replaced needs no call: its copies are made again, being older than it (ensureGenerated).

f
scaledImagePath(
srcPath: string,
width: ImageWidth,
format?: ScaledFormat
): string

Returns where the copy of the upload at srcPath scaled to width is kept, in format: under SCALED_DIR, at the upload's own path below UPLOADS_DIR.

f
scaleImage(
srcPath: string,
outPath: string,
width: ImageWidth,
unnamed 3: ImageTraits,
format?: ScaledFormat
): Promise<void>

Writes a copy of an image at most width wide, never wider than the image itself, as a WebP unless format names another. WebP keeps a PNG's transparency and a GIF's animation, at a fraction of either's bytes.

f
scaleImageBytes(
bytes: Uint8Array,
width: ImageWidth,
traits: ImageTraits
): Promise<Uint8Array | null>

Returns bytes, an image held in memory, scaled as scaleImage does, or null when it can't be, because ffmpeg is missing or failed. The image proxy scales what it fetched with it, and keeps the result itself.

f
sweepGeneratedMedia(): Promise<number>

Deletes the generated files nothing serves any more, and returns how many: the scaled copies of an upload that is gone, which the services' own removals missed or never made, as for a user's avatar; the previews of image dumps under their former name, <id>.preview.jpg or .png, which the scaled copies replaced; and the temporary files a generation left unfinished. Nothing else of THUMBNAILS_DIR is touched, the custom thumbnails kept there being uploads.

f
videoStill(
srcPath: string,
outPath: string
): Promise<void>

Writes a 320-pixel-wide JPEG still of a video, one second in.

Interfaces

I
ImageTraits

What scaleImage is told of the image it scales, which scalableImage (lib/upload.ts) reads from its first bytes.

  • animated: boolean

    Whether its frames are an animation, as a GIF's are. A still may hold more than one image too, a phone's JPEG carrying a gain map or a depth map after the photo, and ffmpeg reads each as a frame.

  • orientation: number

    The EXIF orientation to turn the image by, 1 when it is upright.

Type Aliases

T
ScaledFormat = "webp" | "jpg" | "png"

The formats a scaled copy comes in: WebP for a browser, and a JPEG or a PNG for what doesn't read it, as some mail clients don't.

Variables

v
generatedMediaSweepJob: Job

Runs sweepGeneratedMedia a minute after the server starts, which clears what a new version no longer uses as soon as it is deployed, then once a day. main.ts starts it.