119 lines
3.9 KiB
TypeScript
119 lines
3.9 KiB
TypeScript
import { emitJob, getJob, listJobs, type Job } from '~/server/utils/jobs'
|
|
import { listStudioJobs, type StudioJob } from '~/server/utils/studioQueue'
|
|
|
|
const LIVE_ERROR_KEEP_MS = 60 * 60 * 1000
|
|
|
|
function liveMusicActive(job: Job) {
|
|
if (job.kind !== 'music') return false
|
|
if (job.status === 'queued' || job.status === 'uploading' || job.status === 'running') return true
|
|
if (job.status === 'error' && Date.now() - job.startedAt < LIVE_ERROR_KEEP_MS) return true
|
|
return false
|
|
}
|
|
|
|
export function listLiveMusicJobs(owner: string) {
|
|
return listJobs()
|
|
.filter(job => liveMusicActive(job) && job.library?.ownerKey === owner)
|
|
.sort((a, b) => b.startedAt - a.startedAt)
|
|
}
|
|
|
|
export function summarizeLiveMusicJob(job: Job) {
|
|
const lib = job.library
|
|
const tags = String(lib?.tags || lib?.prompt || '').trim()
|
|
return {
|
|
id: job.id,
|
|
createdAt: job.startedAt,
|
|
updatedAt: job.startedAt,
|
|
status: job.status === 'error' ? 'error' : 'running',
|
|
kind: 'music' as const,
|
|
name: (lib?.name || '').trim() || tags.slice(0, 80) || 'Music',
|
|
prompt: tags,
|
|
shotCount: 1,
|
|
liveJobId: job.id,
|
|
source: 'live' as const,
|
|
lastError: job.error,
|
|
hideThumbnail: true,
|
|
folderLocked: lib?.folderLocked === true
|
|
}
|
|
}
|
|
|
|
export function inspectStudioJob(job: StudioJob) {
|
|
return {
|
|
source: 'studio' as const,
|
|
id: job.id,
|
|
createdAt: job.createdAt,
|
|
updatedAt: job.updatedAt,
|
|
status: job.status,
|
|
kind: job.kind === 'music' ? 'music' as const : job.kind === 'edit' ? 'edit' as const : 'video' as const,
|
|
name: job.name,
|
|
prompt: job.prompt,
|
|
shotCount: job.shotCount,
|
|
familyId: job.familyId,
|
|
shotQueueId: job.shotQueueId,
|
|
liveJobId: job.liveJobId,
|
|
lastError: job.lastError,
|
|
imagePipeline: job.payload.imagePipeline || 'v1',
|
|
cutIn: job.cutIn === true,
|
|
holdForCutIn: job.holdForCutIn === true,
|
|
pauseAfterCurrent: job.pauseAfterCurrent === true,
|
|
pausedByUser: job.pausedByUser === true,
|
|
payload: job.kind === 'music'
|
|
? { ...job.payload, tags: job.payload.prompt }
|
|
: job.payload
|
|
}
|
|
}
|
|
|
|
export function inspectLiveMusicJob(job: Job) {
|
|
const lib = job.library
|
|
const tags = String(lib?.tags || lib?.prompt || '').trim()
|
|
return {
|
|
source: 'live' as const,
|
|
id: job.id,
|
|
createdAt: job.startedAt,
|
|
updatedAt: job.startedAt,
|
|
status: job.status === 'error' ? 'error' : job.status === 'cancelled' ? 'cancelled' : 'running',
|
|
kind: 'music' as const,
|
|
name: (lib?.name || '').trim() || tags.slice(0, 80) || 'Music',
|
|
prompt: tags,
|
|
shotCount: 1,
|
|
liveJobId: job.id,
|
|
lastError: job.error,
|
|
imagePipeline: undefined,
|
|
payload: {
|
|
name: lib?.name || '',
|
|
prompt: tags,
|
|
tags,
|
|
lyrics: lib?.lyrics || '',
|
|
instrumental: lib?.instrumental === true,
|
|
folderId: lib?.folderId || '',
|
|
duration: lib?.duration,
|
|
steps: lib?.steps,
|
|
seed: lib?.seed,
|
|
cfg: lib?.cfg,
|
|
engine: lib?.engine,
|
|
lyricsStrength: lib?.lyricsStrength,
|
|
hideThumbnail: true,
|
|
folderLocked: lib?.folderLocked === true
|
|
}
|
|
}
|
|
}
|
|
|
|
export function findInspectJob(owner: string, id: string) {
|
|
const studio = listStudioJobs(owner).find(item => item.id === id)
|
|
if (studio) return inspectStudioJob(studio)
|
|
const live = getJob(id)
|
|
if (live?.kind === 'music' && live.library?.ownerKey === owner) return inspectLiveMusicJob(live)
|
|
return null
|
|
}
|
|
|
|
export async function cancelLiveMusicJob(owner: string, id: string) {
|
|
const live = getJob(id)
|
|
if (!live || live.kind !== 'music' || live.library?.ownerKey !== owner) {
|
|
throw createError({ statusCode: 404, statusMessage: 'Queued job not found' })
|
|
}
|
|
live.status = 'cancelled'
|
|
if (live.library) live.library.stopAfterCurrent = true
|
|
emitJob(live, { type: 'error', error: 'Job interrupted.', message: 'Job interrupted.' })
|
|
const { interruptComfy } = await import('~/server/utils/comfy')
|
|
await interruptComfy().catch(() => false)
|
|
}
|