Add ACE-Step music generation to the studio and library.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-02 23:58:18 -05:00
co-authored by Cursor
parent c79cca39ae
commit 5555155884
25 changed files with 2157 additions and 44 deletions
+17 -5
View File
@@ -12,6 +12,7 @@ export interface JobEvent {
mediaType?: string
clipId?: string
stillId?: string
trackId?: string
hideThumbnail?: boolean
error?: string
elapsedMs?: number
@@ -31,7 +32,7 @@ export interface JobEvent {
export interface Job {
id: string
kind?: 'video' | 'edit'
kind?: 'video' | 'edit' | 'music'
promptId?: string
clientId: string
status: JobStatus
@@ -41,8 +42,10 @@ export interface Job {
maxStep: number
startedAt: number
video?: { filename: string; subfolder: string; type: string }
audio?: { filename: string; subfolder: string; type: string }
clipId?: string
stillId?: string
trackId?: string
hideThumbnail?: boolean
imageComfyHost?: string
library?: {
@@ -102,6 +105,12 @@ export interface Job {
loraStack?: import('~/utils/loras').LoraStackItem[]
shotLoras?: string[]
shotLoraStacks?: import('~/utils/loras').LoraStackItem[][]
tags?: string
lyrics?: string
instrumental?: boolean
audioExt?: string
engine?: string
lyricsStrength?: number
}
error?: string
socketReady?: boolean
@@ -115,9 +124,10 @@ export interface Job {
const jobs = new Map<string, Job>()
const MAX_JOBS = 40
export function createJob(): Job {
export function createJob(kind: Job['kind'] = 'video'): Job {
const job: Job = {
id: crypto.randomUUID(),
kind,
clientId: crypto.randomUUID(),
status: 'queued',
message: 'Queued',
@@ -175,6 +185,7 @@ export function listJobs() {
}
export function jobSnapshot(job: Job) {
const media = job.kind === 'music' ? job.audio : job.video
return {
jobId: job.id,
kind: job.kind || 'video',
@@ -186,11 +197,12 @@ export function jobSnapshot(job: Job) {
maxStep: job.maxStep,
promptId: job.promptId,
elapsedMs: Date.now() - job.startedAt,
filename: job.library?.folderLocked ? undefined : job.video?.filename,
subfolder: job.library?.folderLocked ? undefined : job.video?.subfolder,
mediaType: job.library?.folderLocked ? undefined : job.video?.type,
filename: job.library?.folderLocked ? undefined : media?.filename,
subfolder: job.library?.folderLocked ? undefined : media?.subfolder,
mediaType: job.library?.folderLocked ? undefined : media?.type,
clipId: job.clipId,
stillId: job.stillId,
trackId: job.trackId,
hideThumbnail: job.hideThumbnail,
error: job.error,
folderLocked: job.library?.folderLocked,