This commit is contained in:
wangbo 2025-05-15 20:58:54 +08:00
parent f93b880d3f
commit 7bfaa76190
2 changed files with 69 additions and 31 deletions

View File

@ -1,6 +1,6 @@
WEB_DIRECTORY = "js" WEB_DIRECTORY = "js"
from .nodes import NODE_CLASS_MAPPINGS from .nodes import NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS
__all__ = ['NODE_CLASS_MAPPINGS'] __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
from aiohttp import ClientSession, web from aiohttp import ClientSession, web
from server import PromptServer from server import PromptServer

View File

@ -1,48 +1,86 @@
import requests import requests
import io import io
import librosa.core as core import librosa # Changed from librosa.core
import torch import torch
import numpy # For type hinting, though librosa.load returns numpy array
import warnings
class AudioLoadPath: class AudioLoadPath:
@classmethod @classmethod
def INPUT_TYPES(s): def INPUT_TYPES(cls): # Changed s to cls for convention
return {"required": { "path": ("STRING", {"default": "X://insert/path/here.mp4"}), return {
"sample_rate": ("INT", {"default": 22050, "min": 6000, "max": 192000, "step": 1}), "required": {
"offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1e6, "step": 0.001}), "path": ("STRING", {"default": "X://insert/path/here.mp4"}),
"duration": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1e6, "step": 0.001})}} "sample_rate": ("INT", {"default": 22050, "min": 6000, "max": 192000, "step": 1}),
"offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1e6, "step": 0.001}),
"duration": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1e6, "step": 0.001})
}
}
RETURN_TYPES = ("AUDIO", ) RETURN_TYPES = ("AUDIO",)
CATEGORY = "EasyAI" CATEGORY = "EasyAI" # Or your preferred category
FUNCTION = "load" FUNCTION = "load"
def load(self, path: str, sample_rate: int, offset: float, duration: float|None): def load(self, path: str, sample_rate: int, offset: float, duration: float | None):
if duration == 0.0: if duration == 0.0:
duration = None duration = None
if path.startswith(('http://', 'https://')): audio_data_source = None
try: try:
response = requests.get(path) if path.startswith(('http://', 'https://')):
response.raise_for_status() # For network paths, download and load from memory
audio_data = io.BytesIO(response.content) response = requests.get(path, timeout=10) # Added timeout
response.raise_for_status() # Raises an exception for bad status codes
audio_data_source = io.BytesIO(response.content)
else:
# For local paths (absolute or relative)
audio_data_source = path
import warnings # Use librosa to load audio.
with warnings.catch_warnings(): # mono=False ensures that the output numpy array is always 2D (channels, samples).
warnings.simplefilter("ignore") # For mono audio, this will be (1, samples).
audio, _ = core.load(audio_data, sr=sample_rate, offset=offset, duration=duration) # librosa.load will resample to the target 'sample_rate' if it's provided.
with warnings.catch_warnings():
warnings.simplefilter("ignore") # Suppress librosa warnings if any
audio_np, loaded_sr = librosa.load(
audio_data_source,
sr=sample_rate,
offset=offset,
duration=duration,
mono=False # Ensures audio_np is 2D: (channels, samples)
)
except Exception as e: # Convert numpy array to PyTorch tensor
raise Exception(f"加载网络音频失败: {str(e)}") audio_tensor = torch.from_numpy(audio_np) # Shape: (channels, samples)
else:
audio, _ = core.load(path, sr=sample_rate, offset=offset, duration=duration)
# 修改维度处理方式 # Add a batch dimension to conform to (batch_size, channels, samples)
audio = torch.from_numpy(audio).float() # Here, batch_size is 1 as we are loading a single audio file.
# 确保音频是二维张量 [channels, samples] audio_tensor = audio_tensor.unsqueeze(0) # Shape: (1, channels, samples)
if audio.dim() == 1:
audio = audio.unsqueeze(0) # 添加channel维度
return (audio,) # Prepare the output dictionary for the "AUDIO" type
output_audio_dict = {
"waveform": audio_tensor,
"sample_rate": loaded_sr # Use the actual loaded sample rate (should match input 'sample_rate')
}
# Return as a tuple, as ComfyUI expects
return (output_audio_dict,)
except requests.exceptions.RequestException as e:
# Handle network-specific errors
raise Exception(f"Failed to load audio from URL: {str(e)}")
except FileNotFoundError as e:
# Handle local file not found errors
raise Exception(f"Audio file not found: {path} - {str(e)}")
except Exception as e:
# Handle other potential errors (e.g., librosa failing to decode, invalid path)
raise Exception(f"Failed to load audio: {str(e)}")
# Node mappings for ComfyUI
NODE_CLASS_MAPPINGS = { NODE_CLASS_MAPPINGS = {
"AudioLoadPath": AudioLoadPath, "AudioLoadPath": AudioLoadPath
}
NODE_DISPLAY_NAME_MAPPINGS = {
"AudioLoadPath": "Load Audio (Path/URL)"
} }