Show small stitch-frame thumbs when a video collection is expanded.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { spawn } from 'node:child_process'
|
||||
import { randomBytes, scrypt, timingSafeEqual } from 'node:crypto'
|
||||
import { promisify } from 'node:util'
|
||||
import type { H3Event } from 'h3'
|
||||
import { extractFirstFrame, extractLastFrame } from '~/server/utils/ffmpeg'
|
||||
|
||||
const scryptAsync = promisify(scrypt)
|
||||
|
||||
@@ -576,6 +577,50 @@ export function clipLastFramePath(owner: string, id: string) {
|
||||
return join(clipDir(owner, id), 'last-frame.png')
|
||||
}
|
||||
|
||||
export function clipFirstFramePath(owner: string, id: string) {
|
||||
return join(clipDir(owner, id), 'first-frame.jpg')
|
||||
}
|
||||
|
||||
export function clipFrameThumbFile(owner: string, id: string, kind: 'first' | 'last') {
|
||||
return join(clipDir(owner, id), kind === 'last' ? 'last-frame.thumb.jpg' : 'first-frame.thumb.jpg')
|
||||
}
|
||||
|
||||
export async function ensureScaledThumb(source: string, dest: string) {
|
||||
if (!existsSync(source)) return ''
|
||||
if (existsSync(dest)) {
|
||||
try {
|
||||
if (statSync(dest).mtimeMs >= statSync(source).mtimeMs) return dest
|
||||
} catch { /* rebuild */ }
|
||||
}
|
||||
const key = dest
|
||||
const pending = thumbBuilds.get(key)
|
||||
if (pending) return pending
|
||||
const build = withThumbSlot(async () => {
|
||||
const ok = await buildStillThumb(source, dest)
|
||||
return ok ? dest : source
|
||||
}).finally(() => {
|
||||
thumbBuilds.delete(key)
|
||||
})
|
||||
thumbBuilds.set(key, build)
|
||||
return build
|
||||
}
|
||||
|
||||
export async function ensureClipLastFrame(owner: string, id: string) {
|
||||
const video = clipVideoPath(owner, id)
|
||||
const dest = clipLastFramePath(owner, id)
|
||||
if (!existsSync(video)) return ''
|
||||
if (!existsSync(dest)) await extractLastFrame(video, dest)
|
||||
return existsSync(dest) ? dest : ''
|
||||
}
|
||||
|
||||
export async function ensureClipFirstFrame(owner: string, id: string) {
|
||||
const video = clipVideoPath(owner, id)
|
||||
const dest = clipFirstFramePath(owner, id)
|
||||
if (!existsSync(video)) return ''
|
||||
if (!existsSync(dest)) await extractFirstFrame(video, dest)
|
||||
return existsSync(dest) ? dest : ''
|
||||
}
|
||||
|
||||
export function extendTempDir(owner: string, jobId: string) {
|
||||
const dir = join(ownerRoot(owner), 'tmp', 'extend', jobId)
|
||||
mkdirSync(dir, { recursive: true })
|
||||
|
||||
Reference in New Issue
Block a user