Name-Feld mit fortlaufender Nummer für alle Audio-Nodes

Alle Generierungs-Nodes (MusicGen, MusicGenLong, AudioGen)
haben jetzt ein 'name' Feld. Dateien werden als
name_001.wav, name_002.wav, etc. gespeichert statt mit
Timestamp. z.B. heavy_strike_001.wav

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Andre 2026-03-21 18:08:29 +01:00
parent b5af85a890
commit 5b326e2de6
2 changed files with 35 additions and 7 deletions

View file

@ -2,6 +2,8 @@ import torch
import torchaudio import torchaudio
import os import os
import time import time
import glob as globmod
import re
class MusicGenNode: class MusicGenNode:
@ -10,6 +12,7 @@ class MusicGenNode:
return { return {
"required": { "required": {
"prompt": ("STRING", {"multiline": True, "default": "dark dungeon ambience, slow, mysterious"}), "prompt": ("STRING", {"multiline": True, "default": "dark dungeon ambience, slow, mysterious"}),
"name": ("STRING", {"default": "music"}),
"duration": ("FLOAT", {"default": 10.0, "min": 1.0, "max": 120.0, "step": 1.0}), "duration": ("FLOAT", {"default": 10.0, "min": 1.0, "max": 120.0, "step": 1.0}),
"model": (["facebook/musicgen-stereo-medium", "facebook/musicgen-stereo-large", "facebook/musicgen-medium", "facebook/musicgen-large", "facebook/musicgen-small"],), "model": (["facebook/musicgen-stereo-medium", "facebook/musicgen-stereo-large", "facebook/musicgen-medium", "facebook/musicgen-large", "facebook/musicgen-small"],),
"seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}), "seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}),
@ -26,7 +29,7 @@ class MusicGenNode:
CATEGORY = "AudioCraft" CATEGORY = "AudioCraft"
OUTPUT_NODE = True OUTPUT_NODE = True
def generate(self, prompt, duration, model, seed, temperature, cfg_coef, top_k, extend_stride): def generate(self, prompt, name, duration, model, seed, temperature, cfg_coef, top_k, extend_stride):
from audiocraft.models import MusicGen from audiocraft.models import MusicGen
from audiocraft.data.audio import audio_write from audiocraft.data.audio import audio_write
@ -49,9 +52,12 @@ class MusicGenNode:
output_dir = "/app/ComfyUI/output/audio" output_dir = "/app/ComfyUI/output/audio"
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
filename = f"musicgen_{int(time.time())}" base_name = re.sub(r'[^\w\-]', '_', name.strip().lower())
num = _next_number(output_dir, base_name)
filename = f"{base_name}_{num:03d}"
out_path = os.path.join(output_dir, filename) out_path = os.path.join(output_dir, filename)
audio_write(out_path, wav[0].cpu(), mg.sample_rate, strategy="loudness") audio_write(out_path, wav[0].cpu(), mg.sample_rate, strategy="loudness")
print(f"[MusicGen] Saved: {filename}.wav")
return (out_path + ".wav",) return (out_path + ".wav",)
@ -63,6 +69,7 @@ class MusicGenLongNode:
return { return {
"required": { "required": {
"prompt": ("STRING", {"multiline": True, "default": "dark fantasy orchestral music, deep cello, french horn, slow war drums, mysterious ambient"}), "prompt": ("STRING", {"multiline": True, "default": "dark fantasy orchestral music, deep cello, french horn, slow war drums, mysterious ambient"}),
"name": ("STRING", {"default": "music_long"}),
"total_duration": ("FLOAT", {"default": 90.0, "min": 10.0, "max": 300.0, "step": 5.0}), "total_duration": ("FLOAT", {"default": 90.0, "min": 10.0, "max": 300.0, "step": 5.0}),
"segment_duration": ("FLOAT", {"default": 30.0, "min": 10.0, "max": 30.0, "step": 5.0}), "segment_duration": ("FLOAT", {"default": 30.0, "min": 10.0, "max": 30.0, "step": 5.0}),
"context_seconds": ("FLOAT", {"default": 5.0, "min": 1.0, "max": 10.0, "step": 0.5}), "context_seconds": ("FLOAT", {"default": 5.0, "min": 1.0, "max": 10.0, "step": 0.5}),
@ -80,7 +87,7 @@ class MusicGenLongNode:
CATEGORY = "AudioCraft" CATEGORY = "AudioCraft"
OUTPUT_NODE = True OUTPUT_NODE = True
def generate_long(self, prompt, total_duration, segment_duration, context_seconds, model, seed, temperature, cfg_coef, top_k): def generate_long(self, prompt, name, total_duration, segment_duration, context_seconds, model, seed, temperature, cfg_coef, top_k):
from audiocraft.models import MusicGen from audiocraft.models import MusicGen
from audiocraft.data.audio import audio_write from audiocraft.data.audio import audio_write
@ -128,19 +135,34 @@ class MusicGenLongNode:
output_dir = "/app/ComfyUI/output/audio" output_dir = "/app/ComfyUI/output/audio"
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
filename = f"musicgen_long_{int(time.time())}" base_name = re.sub(r'[^\w\-]', '_', name.strip().lower())
num = _next_number(output_dir, base_name)
filename = f"{base_name}_{num:03d}"
out_path = os.path.join(output_dir, filename) out_path = os.path.join(output_dir, filename)
audio_write(out_path, result, sample_rate, strategy="loudness") audio_write(out_path, result, sample_rate, strategy="loudness")
print(f"[MusicGenLong] Fertig: {out_path}.wav ({result.shape[1]/sample_rate:.1f}s)") print(f"[MusicGenLong] Fertig: {filename}.wav ({result.shape[1]/sample_rate:.1f}s)")
return (out_path + ".wav",) return (out_path + ".wav",)
def _next_number(output_dir, base_name):
"""Findet die nächste fortlaufende Nummer für einen Dateinamen"""
pattern = os.path.join(output_dir, f"{base_name}_*.wav")
existing = globmod.glob(pattern)
max_num = 0
for f in existing:
match = re.search(rf"{re.escape(base_name)}_(\d+)", os.path.basename(f))
if match:
max_num = max(max_num, int(match.group(1)))
return max_num + 1
class AudioGenNode: class AudioGenNode:
@classmethod @classmethod
def INPUT_TYPES(cls): def INPUT_TYPES(cls):
return { return {
"required": { "required": {
"prompt": ("STRING", {"multiline": True, "default": "sword clash metal sound effect"}), "prompt": ("STRING", {"multiline": True, "default": "sword clash metal sound effect"}),
"name": ("STRING", {"default": "sfx"}),
"duration": ("FLOAT", {"default": 3.0, "min": 0.5, "max": 30.0, "step": 0.5}), "duration": ("FLOAT", {"default": 3.0, "min": 0.5, "max": 30.0, "step": 0.5}),
"seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}), "seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}),
"temperature": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 2.0, "step": 0.05}), "temperature": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 2.0, "step": 0.05}),
@ -155,7 +177,7 @@ class AudioGenNode:
CATEGORY = "AudioCraft" CATEGORY = "AudioCraft"
OUTPUT_NODE = True OUTPUT_NODE = True
def generate(self, prompt, duration, seed, temperature, cfg_coef, top_k): def generate(self, prompt, name, duration, seed, temperature, cfg_coef, top_k):
from audiocraft.models import AudioGen from audiocraft.models import AudioGen
from audiocraft.data.audio import audio_write from audiocraft.data.audio import audio_write
@ -176,9 +198,12 @@ class AudioGenNode:
output_dir = "/app/ComfyUI/output/audio" output_dir = "/app/ComfyUI/output/audio"
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
filename = f"audiogen_{int(time.time())}" base_name = re.sub(r'[^\w\-]', '_', name.strip().lower())
num = _next_number(output_dir, base_name)
filename = f"{base_name}_{num:03d}"
out_path = os.path.join(output_dir, filename) out_path = os.path.join(output_dir, filename)
audio_write(out_path, wav[0].cpu(), ag.sample_rate, strategy="loudness") audio_write(out_path, wav[0].cpu(), ag.sample_rate, strategy="loudness")
print(f"[AudioGen] Saved: {filename}.wav")
return (out_path + ".wav",) return (out_path + ".wav",)

View file

@ -17,6 +17,7 @@
"properties": {"Node name for S&R": "AudioGen"}, "properties": {"Node name for S&R": "AudioGen"},
"widgets_values": [ "widgets_values": [
"fast metal sword swing whoosh close range", "fast metal sword swing whoosh close range",
"heavy_strike",
1.5, 1.5,
0, 0,
"fixed", "fixed",
@ -72,6 +73,7 @@
"properties": {"Node name for S&R": "AudioGen"}, "properties": {"Node name for S&R": "AudioGen"},
"widgets_values": [ "widgets_values": [
"magical energy charging electric crackling buildup impact", "magical energy charging electric crackling buildup impact",
"spell_effect",
2.5, 2.5,
0, 0,
"fixed", "fixed",
@ -127,6 +129,7 @@
"properties": {"Node name for S&R": "AudioGen"}, "properties": {"Node name for S&R": "AudioGen"},
"widgets_values": [ "widgets_values": [
"wind blowing through dark stone dungeon corridor echoing", "wind blowing through dark stone dungeon corridor echoing",
"dungeon_ambient",
8.0, 8.0,
0, 0,
"fixed", "fixed",