2025-05-07 05:33:34 -07:00
import torch
2025-08-22 05:05:36 +03:00
from typing_extensions import override
2025-05-07 05:33:34 -07:00
import comfy . model_management
2025-05-07 16:22:07 -07:00
import node_helpers
2026-04-20 18:59:26 -07:00
from comfy_api . latest import ComfyExtension , IO
2025-08-22 05:05:36 +03:00
2026-04-20 18:59:26 -07:00
class TextEncodeAceStepAudio ( IO . ComfyNode ) :
2025-08-22 05:05:36 +03:00
@classmethod
def define_schema ( cls ) :
2026-04-20 18:59:26 -07:00
return IO . Schema (
2025-08-22 05:05:36 +03:00
node_id = " TextEncodeAceStepAudio " ,
2026-06-17 08:33:09 +08:00
category = " model/conditioning/ace " ,
2025-08-22 05:05:36 +03:00
inputs = [
2026-04-20 18:59:26 -07:00
IO . Clip . Input ( " clip " ) ,
IO . String . Input ( " tags " , multiline = True , dynamic_prompts = True ) ,
IO . String . Input ( " lyrics " , multiline = True , dynamic_prompts = True ) ,
IO . Float . Input ( " lyrics_strength " , default = 1.0 , min = 0.0 , max = 10.0 , step = 0.01 ) ,
2025-08-22 05:05:36 +03:00
] ,
2026-04-20 18:59:26 -07:00
outputs = [ IO . Conditioning . Output ( ) ] ,
2025-08-22 05:05:36 +03:00
)
2025-05-07 05:33:34 -07:00
@classmethod
2026-04-20 18:59:26 -07:00
def execute ( cls , clip , tags , lyrics , lyrics_strength ) - > IO . NodeOutput :
2025-05-07 05:33:34 -07:00
tokens = clip . tokenize ( tags , lyrics = lyrics )
2025-05-07 16:22:07 -07:00
conditioning = clip . encode_from_tokens_scheduled ( tokens )
conditioning = node_helpers . conditioning_set_values ( conditioning , { " lyrics_strength " : lyrics_strength } )
2026-04-20 18:59:26 -07:00
return IO . NodeOutput ( conditioning )
2025-05-07 05:33:34 -07:00
2026-04-20 18:59:26 -07:00
class TextEncodeAceStepAudio15 ( IO . ComfyNode ) :
2026-02-02 21:06:18 -08:00
@classmethod
def define_schema ( cls ) :
2026-04-20 18:59:26 -07:00
return IO . Schema (
2026-02-02 21:06:18 -08:00
node_id = " TextEncodeAceStepAudio1.5 " ,
2026-06-17 08:33:09 +08:00
category = " model/conditioning/ace " ,
2026-02-02 21:06:18 -08:00
inputs = [
2026-04-20 18:59:26 -07:00
IO . Clip . Input ( " clip " ) ,
IO . String . Input ( " tags " , multiline = True , dynamic_prompts = True ) ,
IO . String . Input ( " lyrics " , multiline = True , dynamic_prompts = True ) ,
IO . Int . Input ( " seed " , default = 0 , min = 0 , max = 0xffffffffffffffff , control_after_generate = True ) ,
IO . Int . Input ( " bpm " , default = 120 , min = 10 , max = 300 ) ,
IO . Float . Input ( " duration " , default = 120.0 , min = 0.0 , max = 2000.0 , step = 0.1 ) ,
IO . Combo . Input ( " timesignature " , options = [ ' 2 ' , ' 3 ' , ' 4 ' , ' 6 ' ] ) ,
2026-05-06 05:47:57 +03:00
IO . Combo . Input ( " language " , options = [ ' ar ' , ' az ' , ' bg ' , ' bn ' , ' ca ' , ' cs ' , ' da ' , ' de ' , ' el ' , ' en ' , ' es ' , ' fa ' , ' fi ' , ' fr ' , ' he ' , ' hi ' , ' hr ' , ' ht ' , ' hu ' , ' id ' , ' is ' , ' it ' , ' ja ' , ' ko ' , ' la ' , ' lt ' , ' ms ' , ' ne ' , ' nl ' , ' no ' , ' pa ' , ' pl ' , ' pt ' , ' ro ' , ' ru ' , ' sa ' , ' sk ' , ' sr ' , ' sv ' , ' sw ' , ' ta ' , ' te ' , ' th ' , ' tl ' , ' tr ' , ' uk ' , ' ur ' , ' vi ' , ' yue ' , ' zh ' , ' unknown ' ] , default = ' en ' ) ,
2026-04-20 18:59:26 -07:00
IO . Combo . Input ( " keyscale " , options = [ f " { root } { quality } " for quality in [ " major " , " minor " ] for root in [ " C " , " C# " , " Db " , " D " , " D# " , " Eb " , " E " , " F " , " F# " , " Gb " , " G " , " G# " , " Ab " , " A " , " A# " , " Bb " , " B " ] ] ) ,
IO . Boolean . Input ( " generate_audio_codes " , default = True , tooltip = " Enable the LLM that generates audio codes. This can be slow but will increase the quality of the generated audio. Turn this off if you are giving the model an audio reference. " , advanced = True ) ,
IO . Float . Input ( " cfg_scale " , default = 2.0 , min = 0.0 , max = 100.0 , step = 0.1 , advanced = True ) ,
IO . Float . Input ( " temperature " , default = 0.85 , min = 0.0 , max = 2.0 , step = 0.01 , advanced = True ) ,
IO . Float . Input ( " top_p " , default = 0.9 , min = 0.0 , max = 2000.0 , step = 0.01 , advanced = True ) ,
IO . Int . Input ( " top_k " , default = 0 , min = 0 , max = 100 , advanced = True ) ,
IO . Float . Input ( " min_p " , default = 0.000 , min = 0.0 , max = 1.0 , step = 0.001 , advanced = True ) ,
2026-02-02 21:06:18 -08:00
] ,
2026-04-20 18:59:26 -07:00
outputs = [ IO . Conditioning . Output ( ) ] ,
2026-02-02 21:06:18 -08:00
)
@classmethod
2026-04-20 18:59:26 -07:00
def execute ( cls , clip , tags , lyrics , seed , bpm , duration , timesignature , language , keyscale , generate_audio_codes , cfg_scale , temperature , top_p , top_k , min_p ) - > IO . NodeOutput :
2026-02-12 11:28:48 +10:00
tokens = clip . tokenize ( tags , lyrics = lyrics , bpm = bpm , duration = duration , timesignature = int ( timesignature ) , language = language , keyscale = keyscale , seed = seed , generate_audio_codes = generate_audio_codes , cfg_scale = cfg_scale , temperature = temperature , top_p = top_p , top_k = top_k , min_p = min_p )
2026-02-02 21:06:18 -08:00
conditioning = clip . encode_from_tokens_scheduled ( tokens )
2026-04-20 18:59:26 -07:00
return IO . NodeOutput ( conditioning )
2026-02-02 21:06:18 -08:00
2025-05-07 05:33:34 -07:00
2026-04-20 18:59:26 -07:00
class EmptyAceStepLatentAudio ( IO . ComfyNode ) :
2025-05-07 05:33:34 -07:00
@classmethod
2025-08-22 05:05:36 +03:00
def define_schema ( cls ) :
2026-04-20 18:59:26 -07:00
return IO . Schema (
2025-08-22 05:05:36 +03:00
node_id = " EmptyAceStepLatentAudio " ,
2026-02-02 21:06:18 -08:00
display_name = " Empty Ace Step 1.0 Latent Audio " ,
2026-06-17 08:33:09 +08:00
category = " model/latent/ace " ,
2025-08-22 05:05:36 +03:00
inputs = [
2026-04-20 18:59:26 -07:00
IO . Float . Input ( " seconds " , default = 120.0 , min = 1.0 , max = 1000.0 , step = 0.1 ) ,
IO . Int . Input (
2025-08-22 05:05:36 +03:00
" batch_size " , default = 1 , min = 1 , max = 4096 , tooltip = " The number of latent images in the batch. "
) ,
] ,
2026-04-20 18:59:26 -07:00
outputs = [ IO . Latent . Output ( ) ] ,
2025-08-22 05:05:36 +03:00
)
2025-05-07 05:33:34 -07:00
2025-08-22 05:05:36 +03:00
@classmethod
2026-04-20 18:59:26 -07:00
def execute ( cls , seconds , batch_size ) - > IO . NodeOutput :
2025-05-07 05:33:34 -07:00
length = int ( seconds * 44100 / 512 / 8 )
2026-04-06 18:12:16 -07:00
latent = torch . zeros ( [ batch_size , 8 , 16 , length ] , device = comfy . model_management . intermediate_device ( ) , dtype = comfy . model_management . intermediate_dtype ( ) )
2026-04-20 18:59:26 -07:00
return IO . NodeOutput ( { " samples " : latent , " type " : " audio " } )
2025-08-22 05:05:36 +03:00
2025-05-07 05:33:34 -07:00
2026-04-20 18:59:26 -07:00
class EmptyAceStep15LatentAudio ( IO . ComfyNode ) :
2026-02-02 21:06:18 -08:00
@classmethod
def define_schema ( cls ) :
2026-04-20 18:59:26 -07:00
return IO . Schema (
2026-02-02 21:06:18 -08:00
node_id = " EmptyAceStep1.5LatentAudio " ,
display_name = " Empty Ace Step 1.5 Latent Audio " ,
2026-06-17 08:33:09 +08:00
category = " model/latent/ace " ,
2026-02-02 21:06:18 -08:00
inputs = [
2026-04-20 18:59:26 -07:00
IO . Float . Input ( " seconds " , default = 120.0 , min = 1.0 , max = 1000.0 , step = 0.01 ) ,
IO . Int . Input (
2026-02-02 21:06:18 -08:00
" batch_size " , default = 1 , min = 1 , max = 4096 , tooltip = " The number of latent images in the batch. "
) ,
] ,
2026-04-20 18:59:26 -07:00
outputs = [ IO . Latent . Output ( ) ] ,
2026-02-02 21:06:18 -08:00
)
@classmethod
2026-04-20 18:59:26 -07:00
def execute ( cls , seconds , batch_size ) - > IO . NodeOutput :
2026-02-02 21:06:18 -08:00
length = round ( ( seconds * 48000 / 1920 ) )
2026-04-06 18:12:16 -07:00
latent = torch . zeros ( [ batch_size , 64 , length ] , device = comfy . model_management . intermediate_device ( ) , dtype = comfy . model_management . intermediate_dtype ( ) )
2026-05-18 21:14:30 -07:00
return IO . NodeOutput ( { " samples " : latent , " type " : " audio " , " downscale_ratio_temporal " : 1764 } )
2026-02-02 21:06:18 -08:00
2026-04-20 18:59:26 -07:00
class ReferenceAudio ( IO . ComfyNode ) :
2026-02-02 21:06:18 -08:00
@classmethod
def define_schema ( cls ) :
2026-04-20 18:59:26 -07:00
return IO . Schema (
2026-02-02 21:06:18 -08:00
node_id = " ReferenceTimbreAudio " ,
2026-06-17 08:33:09 +08:00
display_name = " Set Reference Audio " ,
category = " model/conditioning " ,
2026-02-02 21:06:18 -08:00
is_experimental = True ,
2026-02-04 18:29:22 -08:00
description = " This node sets the reference audio for ace step 1.5 " ,
2026-02-02 21:06:18 -08:00
inputs = [
2026-04-20 18:59:26 -07:00
IO . Conditioning . Input ( " conditioning " ) ,
IO . Latent . Input ( " latent " , optional = True ) ,
2026-02-02 21:06:18 -08:00
] ,
outputs = [
2026-04-20 18:59:26 -07:00
IO . Conditioning . Output ( ) ,
2026-02-02 21:06:18 -08:00
]
)
@classmethod
2026-04-20 18:59:26 -07:00
def execute ( cls , conditioning , latent = None ) - > IO . NodeOutput :
2026-02-02 21:06:18 -08:00
if latent is not None :
conditioning = node_helpers . conditioning_set_values ( conditioning , { " reference_audio_timbre_latents " : [ latent [ " samples " ] ] } , append = True )
2026-04-20 18:59:26 -07:00
return IO . NodeOutput ( conditioning )
2026-02-02 21:06:18 -08:00
2025-08-22 05:05:36 +03:00
class AceExtension ( ComfyExtension ) :
@override
2026-04-20 18:59:26 -07:00
async def get_node_list ( self ) - > list [ type [ IO . ComfyNode ] ] :
2025-08-22 05:05:36 +03:00
return [
TextEncodeAceStepAudio ,
EmptyAceStepLatentAudio ,
2026-02-02 21:06:18 -08:00
TextEncodeAceStepAudio15 ,
EmptyAceStep15LatentAudio ,
2026-02-04 18:29:22 -08:00
ReferenceAudio ,
2025-08-22 05:05:36 +03:00
]
2025-05-07 05:33:34 -07:00
2025-08-22 05:05:36 +03:00
async def comfy_entrypoint ( ) - > AceExtension :
return AceExtension ( )