Add .env support for API keys, add input tooltips
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# Copy this file to .env and fill in your API keys
|
||||
# You can reference these variable names directly in the nodes
|
||||
|
||||
GEMINI_API_KEY="your_gemini_api_key"
|
||||
OPENAI_API_KEY="your_openai_api_key"
|
||||
XI_API_KEY="your_elevenlabs_api_key"
|
||||
REPLICATE_API_TOKEN="your_replicate_api_token"
|
||||
@@ -51,251 +51,149 @@ All nodes in this collection require API keys to function.
|
||||
* **ElevenLabs TTS Node:** You will need an [ElevenLabs API Key](https://elevenlabs.io/).
|
||||
* **Vertex AI Nodes (Imagen Edit, Veo Vertex AI):** You will need a Google Cloud Project ID, a service account with appropriate permissions, and the location for the resources.
|
||||
|
||||
You can paste your key directly into the `api_key` field on the corresponding node. For Vertex AI nodes, you will need to provide the project ID, location, and path to your service account JSON file.
|
||||
You can paste your key directly into the `api_key` field on the corresponding node. For Vertex AI nodes, you will need to provide the project ID, location, and paste your service account JSON content.
|
||||
|
||||
### Using Environment Variables (.env file)
|
||||
|
||||
Instead of pasting API keys directly into nodes, you can store them in a `.env` file:
|
||||
|
||||
1. Copy `.env.example` to `.env` in the node directory
|
||||
2. Fill in your API keys:
|
||||
```
|
||||
GEMINI_API_KEY=your_gemini_key_here
|
||||
OPENAI_API_KEY=your_openai_key_here
|
||||
XI_API_KEY=your_elevenlabs_key_here
|
||||
REPLICATE_API_TOKEN=your_replicate_token_here
|
||||
```
|
||||
3. In the node's `api_key` field, enter the variable name (e.g., `GEMINI_API_KEY`) instead of the actual key
|
||||
|
||||
This keeps your API keys secure and makes it easy to switch between different keys or projects.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Node Guide
|
||||
|
||||
> **Note:** All nodes include standard inputs like `api_key`, `prompt`, `model`, `temperature`, and `seed` where applicable. Only unique or notable inputs are listed below.
|
||||
|
||||
### Flux Kontext Pro / Max
|
||||
|
||||
These nodes allow you to transform an input image based on a text prompt. They are ideal for applying artistic styles or making significant conceptual changes to an existing image.
|
||||
Transform images based on text prompts. Ideal for applying artistic styles or making conceptual changes.
|
||||
|
||||
* **Category:** `image/edit`
|
||||
* **Inputs:**
|
||||
* `image`: The source image to transform.
|
||||
* `prompt`: A text description of the desired output (e.g., "A vibrant Van Gogh painting", "Make this a 90s cartoon").
|
||||
* `replicate_api_token`: Your API token from Replicate.
|
||||
* `aspect_ratio`: The desired output aspect ratio. `match_input_image` is highly recommended to preserve the original composition.
|
||||
* `output_format`: `jpg` or `png`.
|
||||
* `safety_tolerance`: Adjust the content safety filter level.
|
||||
* **Output:**
|
||||
* `image`: The generated image.
|
||||
* **Key Inputs:** `image`, `aspect_ratio` (use `match_input_image` to preserve composition)
|
||||
* **Output:** `image`
|
||||
|
||||
### Flux.2 (Replicate)
|
||||
|
||||
Generate images using Black Forest Labs' FLUX.2 models via the Replicate API.
|
||||
Generate images using FLUX.2 models (Pro, Max, Dev) via Replicate.
|
||||
|
||||
* **Category:** `image/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: The text prompt for image generation.
|
||||
* `api_key`: Your Replicate API token.
|
||||
* `model`: Choose between `flux-2-max`, `flux-2-pro`, or `flux-2-dev`.
|
||||
* `aspect_ratio`: The desired aspect ratio for the generated image.
|
||||
* `output_format`: `webp`, `jpg`, or `png`.
|
||||
* `output_quality`: Quality of the output image (0-100).
|
||||
* `image_1` to `image_5` (Optional): Input images for image-to-image or control tasks.
|
||||
* **Output:**
|
||||
* `image`: The generated image.
|
||||
* **Key Inputs:** `image_1` to `image_5` (optional, for image-to-image tasks)
|
||||
* **Output:** `image`
|
||||
|
||||
### Gemini Chat
|
||||
|
||||
A versatile node for text generation and image/audio analysis. Use it to understand an image's content, analyze audio, or to generate creative text for other nodes.
|
||||
Multimodal text generation with image and audio analysis capabilities.
|
||||
|
||||
* **Category:** `text/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: The text prompt or question you want to ask the model.
|
||||
* `model`: The Gemini model to use (e.g., `gemini-2.5-pro`, `gemini-2.5-flash`).
|
||||
* `temperature`: Controls the creativity of the output.
|
||||
* `thinking`: Enables the model's thinking/reasoning process.
|
||||
* `seed`: Seed for reproducibility.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `system_instruction` (Optional): Provide context or rules for how the model should behave.
|
||||
* `thinking_budget` (Optional): Token budget for thinking.
|
||||
* `image` (Optional): An input image for the model to analyze.
|
||||
* `audio` (Optional): An input audio for the model to analyze.
|
||||
* **Output:**
|
||||
* `response`: The text generated by the Gemini model.
|
||||
* **Key Inputs:** `thinking`, `thinking_budget`, `system_instruction`, `image` (optional), `audio` (optional)
|
||||
* **Output:** `response` (text)
|
||||
|
||||
### Gemini Segmentation
|
||||
|
||||
This node uses a Gemini model to generate segmentation masks for specified objects within an image.
|
||||
Generate segmentation masks for objects in an image.
|
||||
|
||||
* **Category:** `image/generation`
|
||||
* **Inputs:**
|
||||
* `image`: The source image for segmentation.
|
||||
* `segment_prompt`: A text description of the objects to segment (e.g., "the car", "all people").
|
||||
* `model`: The Gemini model to use.
|
||||
* `temperature`: Controls randomness.
|
||||
* `thinking`: Enable thinking process.
|
||||
* `seed`: Seed for reproducibility.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `thinking_budget` (Optional): Token budget for thinking.
|
||||
* **Output:**
|
||||
* `mask`: A black and white mask of the segmented objects.
|
||||
* **Key Inputs:** `image`, `segment_prompt` (e.g., "the car", "all people"), `thinking`, `thinking_budget`
|
||||
* **Output:** `mask`
|
||||
|
||||
### Gemini Speaker Diarization
|
||||
|
||||
Separate audio into different speaker tracks using Gemini.
|
||||
Separate audio into different speaker tracks.
|
||||
|
||||
* **Category:** `audio/diarise`
|
||||
* **Inputs:**
|
||||
* `audio`: The input audio to process.
|
||||
* `num_speakers`: The expected number of speakers.
|
||||
* `model`: The Gemini model to use.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `seed`: Seed for reproducibility.
|
||||
* `temperature`: Controls randomness.
|
||||
* `thinking` (Optional): Enable thinking process.
|
||||
* `thinking_budget` (Optional): Token budget for thinking.
|
||||
* **Output:**
|
||||
* `speaker_1` to `speaker_4`: Audio tracks for up to 4 separated speakers.
|
||||
* **Key Inputs:** `audio`, `num_speakers`, `thinking`, `thinking_budget`
|
||||
* **Output:** `speaker_1` to `speaker_4` (audio tracks)
|
||||
|
||||
### GPT Image Edit
|
||||
|
||||
This node uses OpenAI's API to perform powerful, prompt-based inpainting and editing.
|
||||
Prompt-based inpainting and image editing using OpenAI's API.
|
||||
|
||||
* **Category:** `image/edit`
|
||||
* **Inputs:**
|
||||
* `image`: The source image to edit.
|
||||
* `mask` (Optional): A black and white mask. The model will edit the **white area** of the mask.
|
||||
* `prompt`: A description of the edit to perform.
|
||||
* `api_key`: Your API key from OpenAI.
|
||||
* `...other_params`: Various quality and formatting options for the OpenAI API.
|
||||
* **Output:**
|
||||
* `image`: The edited image.
|
||||
* **Key Inputs:** `image_1` to `image_5`, `mask` (optional, white area = edit region), `background`, `quality`, `size`
|
||||
* **Output:** `image`
|
||||
|
||||
### OpenAI LLM
|
||||
|
||||
Access OpenAI's powerful language models for text generation and reasoning.
|
||||
Access OpenAI language models (GPT-4, GPT-5, o1, etc.) for text generation.
|
||||
|
||||
* **Category:** `text/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: The text prompt.
|
||||
* `model`: The OpenAI model to use (e.g., `gpt-4.1`, `o1`, `gpt-5`).
|
||||
* `temperature`: Controls randomness.
|
||||
* `reasoning_effort`: Effort level for reasoning models.
|
||||
* `api_key`: Your OpenAI API key.
|
||||
* `max_output_tokens`: Maximum number of tokens to generate.
|
||||
* `system_instruction` (Optional): System level instructions.
|
||||
* `image` (Optional): Input image for multimodal models.
|
||||
* **Output:**
|
||||
* `response`: The generated text response.
|
||||
* **Key Inputs:** `reasoning_effort` (low/medium/high), `max_output_tokens`, `system_instruction`, `image` (optional)
|
||||
* **Output:** `response` (text)
|
||||
|
||||
### OpenAI Text-to-Speech
|
||||
|
||||
Generate high-quality speech from text using OpenAI's TTS models.
|
||||
Generate speech using OpenAI's TTS models.
|
||||
|
||||
* **Category:** `audio/generation`
|
||||
* **Inputs:**
|
||||
* `text`: The text to convert to speech.
|
||||
* `model`: The TTS model to use (e.g., `gpt-4o-mini-tts`, `tts-1`).
|
||||
* `voice`: The voice to use (e.g., `alloy`, `echo`).
|
||||
* `response_format`: Output audio format.
|
||||
* `speed`: Speaking speed.
|
||||
* `api_key`: Your OpenAI API key.
|
||||
* `instructions` (Optional): Instructions for the model (supported by some models).
|
||||
* **Output:**
|
||||
* `audio`: The generated audio.
|
||||
* **Key Inputs:** `text`, `voice` (alloy, echo, etc.), `response_format`, `speed`, `instructions` (optional)
|
||||
* **Output:** `audio`
|
||||
|
||||
### Google Imagen Generator
|
||||
|
||||
Generate images from a text prompt using Google's Imagen models.
|
||||
Generate images from text using Google's Imagen models.
|
||||
|
||||
* **Category:** `image/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: A text description of the image to generate.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `model`: The Imagen model to use.
|
||||
* `...other_params`: Options for number of images, aspect ratio, and image size.
|
||||
* **Output:**
|
||||
* `images`: The generated image(s).
|
||||
* **Key Inputs:** `number_of_images`, `aspect_ratio`, `image_size`, `guidance_scale`, `negative_prompt`
|
||||
* **Output:** `images`
|
||||
|
||||
### Google Imagen Edit (Vertex AI only)
|
||||
|
||||
Perform advanced image editing, inpainting, outpainting, and background swapping using Imagen on Google's Vertex AI platform.
|
||||
Advanced image editing with inpainting, outpainting, and background swapping.
|
||||
|
||||
* **Category:** `image/edit`
|
||||
* **Inputs:**
|
||||
* `image`: The source image to edit.
|
||||
* `mask`: A mask defining the area to edit.
|
||||
* `prompt`: A description of the desired edit.
|
||||
* `project_id`: Your Google Cloud Project ID.
|
||||
* `location`: The Google Cloud location for the model.
|
||||
* `service_account`: Path to your Google Cloud service account JSON file.
|
||||
* `edit_mode`: The type of edit to perform (e.g., inpainting, outpainting).
|
||||
* `...other_params`: Controls for negative prompt, seed, and steps.
|
||||
* **Output:**
|
||||
* `edited_images`: The edited image(s).
|
||||
* **Key Inputs:** `image`, `mask`, `project_id`, `location`, `service_account` (JSON content), `edit_mode`
|
||||
* **Output:** `edited_images`
|
||||
|
||||
### Nano Banana
|
||||
|
||||
A creative image generation node that can take a combination of text and up to five images as input.
|
||||
Creative image generation using a specialized Gemini model.
|
||||
|
||||
* **Category:** `image/generation`
|
||||
* **Inputs:**
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `prompt` (Optional): A text prompt.
|
||||
* `image_1` to `image_5` (Optional): Up to five source images.
|
||||
* `...other_params`: Controls for aspect ratio, temperature, top_p, and seed.
|
||||
* **Output:**
|
||||
* `image`: The generated image.
|
||||
* **Key Inputs:** `image_1` to `image_5` (optional), `aspect_ratio`, `resolution`, `top_p`
|
||||
* **Output:** `image`
|
||||
|
||||
### Veo Video Generator (Vertex AI)
|
||||
|
||||
Generate short, high-quality video clips from a text description using Google's Veo model on Vertex AI.
|
||||
Generate video clips using Google's Veo model on Vertex AI.
|
||||
|
||||
* **Category:** `video/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: A text description of the video to generate.
|
||||
* `project_id`: Your Google Cloud Project ID.
|
||||
* `location`: The Google Cloud location for the model.
|
||||
* `service_account`: Path to your Google Cloud service account JSON file.
|
||||
* `...other_params`: Controls for negative prompt, aspect ratio, audio generation, and seed.
|
||||
* **Output:**
|
||||
* `frames`: The generated video frames, output as an image batch.
|
||||
* **Key Inputs:** `project_id`, `location`, `service_account` (JSON content), `resolution`, `aspect_ratio`, `duration_seconds`, `generate_audio`, `first_frame`/`last_frame` (optional)
|
||||
* **Output:** `frames`, `audio`
|
||||
|
||||
### Veo Video Generator (Gemini API)
|
||||
|
||||
Generate videos using Google's Veo 2.0 model via the Gemini API. Supports text-to-video and image-to-video.
|
||||
Generate videos using Veo 2.0 via the Gemini API. Supports text-to-video and image-to-video.
|
||||
|
||||
* **Category:** `video/generation`
|
||||
* **Inputs:**
|
||||
* `prompt`: A text description of the video.
|
||||
* `image` (Optional): An input image for image-to-video generation.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `model`: The Veo model to use (e.g., `veo-2.0-generate-001`).
|
||||
* `aspect_ratio`: Desired aspect ratio (16:9 or 9:16).
|
||||
* `duration_seconds`: Duration of the video (e.g., 5-8 seconds).
|
||||
* `...other_params`: Controls for negative prompt and seed.
|
||||
* **Output:**
|
||||
* `frames`: The generated video frames.
|
||||
* **Key Inputs:** `aspect_ratio`, `duration_seconds`, `negative_prompt`, `image` (optional, for image-to-video)
|
||||
* **Output:** `frames`
|
||||
|
||||
### ElevenLabs TTS
|
||||
|
||||
Generate speech from text using the ElevenLabs API.
|
||||
Generate speech using ElevenLabs' diverse voices and models.
|
||||
|
||||
* **Category:** `audio/generation`
|
||||
* **Inputs:**
|
||||
* `text`: The text to convert to speech.
|
||||
* `api_key`: Your API key from ElevenLabs.
|
||||
* `voice_id`: The ID of the voice to use for generation.
|
||||
* `model_id`: The ElevenLabs model to use.
|
||||
* `output_format`: The desired output audio format.
|
||||
* `stability`: Controls the stability and variability of the generated speech.
|
||||
* `similarity_boost`: Enhances the similarity of the generated speech to the chosen voice.
|
||||
* `speed`: Adjusts the speaking rate.
|
||||
* `style`: Controls the expressiveness of the speech.
|
||||
* `use_speaker_boost`: A boolean to enable or disable speaker boost.
|
||||
* `seed`: A seed for ensuring reproducible results.
|
||||
* **Output:**
|
||||
* `audio`: The generated audio waveform and sample rate.
|
||||
* **Key Inputs:** `text`, `voice_id`, `model_id`, `stability`, `similarity_boost`, `speed`, `style`, `use_speaker_boost`
|
||||
* **Output:** `audio`
|
||||
|
||||
### Gemini TTS
|
||||
|
||||
Generate speech from text using Google's Gemini TTS models.
|
||||
Generate speech using Google's Gemini TTS models.
|
||||
|
||||
* **Category:** `audio/generation`
|
||||
* **Inputs:**
|
||||
* `text`: The text to be converted into speech.
|
||||
* `api_key`: Your API key from Google AI Studio.
|
||||
* `model`: The specific Gemini model to use for generation.
|
||||
* `voice_id`: The prebuilt voice to use for the output.
|
||||
* `temperature`: Controls the randomness and creativity of the output.
|
||||
* `seed`: A seed for ensuring reproducible results.
|
||||
* `system_prompt` (Optional): A system-level instruction to guide the model's behavior.
|
||||
* **Output:**
|
||||
* `audio`: The generated audio waveform and sample rate.
|
||||
* **Key Inputs:** `text`, `voice_id`, `system_prompt` (optional)
|
||||
* **Output:** `audio`
|
||||
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
from .flux_kontext_replicate import NODE_CLASS_MAPPINGS as PRO_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as PRO_DISPLAY
|
||||
from .gemini_node import NODE_CLASS_MAPPINGS as GEMINI_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as GEMINI_DISPLAY
|
||||
from .gemini_diarisation import NODE_CLASS_MAPPINGS as GEMINI_DIAR_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as GEMINI_DIAR_DISPLAY
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ class ElevenLabsTTSNode:
|
||||
"style": ("FLOAT", {"default": 0.50, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"use_speaker_boost": ("BOOLEAN", {"default": True}),
|
||||
"seed": ("INT", {"default": 40, "min": 0, "max": 4294967294}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put ElevenLabs API key or .env variable name (XI_API_KEY)"}),
|
||||
},
|
||||
"optional": {
|
||||
"previous_text": ("STRING", {"multiline": True, "default": ""}),
|
||||
@@ -68,7 +68,7 @@ class ElevenLabsTTSNode:
|
||||
if not text.strip():
|
||||
raise ValueError("Text input cannot be empty.")
|
||||
|
||||
key = api_key.strip() or os.environ.get("XI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("XI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("No API key provided.")
|
||||
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@ class Flux2Replicate:
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True, "default": "A beautiful landscape"}),
|
||||
"api_key": ("STRING", {"default": ""}),
|
||||
"api_key": ("STRING", {"default": "", "tooltip": "Directly put Replicate API token or .env variable name (REPLICATE_API_TOKEN)"}),
|
||||
"model": (["flux-2-max", "flux-2-pro", "flux-2-dev"], {"default": "flux-2-max"}),
|
||||
"aspect_ratio": (["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5", "21:9", "9:21", "2:1", "1:2"], {"default": "1:1"}),
|
||||
"output_format": (["webp", "jpg", "png"], {"default": "webp"}),
|
||||
@@ -49,7 +49,7 @@ class Flux2Replicate:
|
||||
def generate_image(self, prompt, api_key, model, aspect_ratio, output_format, output_quality,
|
||||
image_1=None, image_2=None, image_3=None, image_4=None, image_5=None):
|
||||
try:
|
||||
os.environ["REPLICATE_API_TOKEN"] = api_key
|
||||
os.environ["REPLICATE_API_TOKEN"] = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("REPLICATE_API_TOKEN", "")
|
||||
|
||||
input_images = []
|
||||
for img in [image_1, image_2, image_3, image_4, image_5]:
|
||||
@@ -68,7 +68,7 @@ class Flux2Replicate:
|
||||
|
||||
# Add safety_tolerance for models that support it (flux-2-max and flux-2-pro)
|
||||
if model in ["flux-2-max", "flux-2-pro"]:
|
||||
replicate_input["safety_tolerance"] = 0
|
||||
replicate_input["safety_tolerance"] = 1
|
||||
|
||||
# Run Replicate model
|
||||
output = replicate.run(
|
||||
|
||||
@@ -13,7 +13,7 @@ class FluxKontextReplicate:
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"prompt": ("STRING", {"multiline": True, "default": "Make this a 90s cartoon"}),
|
||||
"api_key": ("STRING", {"default": ""}),
|
||||
"api_key": ("STRING", {"default": "", "tooltip": "Directly put Replicate API token or .env variable name (REPLICATE_API_TOKEN)"}),
|
||||
"model": (["flux-kontext-dev", "flux-kontext-max", "flux-kontext-pro"], {"default": "flux-kontext-dev"}),
|
||||
"aspect_ratio": (["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5", "21:9", "9:21", "2:1", "1:2", "match_input_image"], {"default": "match_input_image"}),
|
||||
"output_format": (["jpg", "png"], {"default": "jpg"}),
|
||||
@@ -30,7 +30,7 @@ class FluxKontextReplicate:
|
||||
|
||||
def generate_image(self, image, prompt, api_key, model, aspect_ratio, output_format, safety_tolerance, seed, prompt_upsampling):
|
||||
try:
|
||||
os.environ["REPLICATE_API_TOKEN"] = api_key
|
||||
os.environ["REPLICATE_API_TOKEN"] = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("REPLICATE_API_TOKEN", "")
|
||||
|
||||
# Convert tensor to PIL and save to buffer
|
||||
tensor = image.squeeze(0) if len(image.shape) == 4 else image
|
||||
|
||||
@@ -16,18 +16,18 @@ class GeminiDiarisationAPI:
|
||||
"audio": ("AUDIO",),
|
||||
"num_speakers": ("INT", {"default": 2, "min": 1, "max": 10, "step": 1}),
|
||||
"model": ("STRING", {"default": "gemini-2.5-flash", "multiline": False}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False, "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"}),
|
||||
"seed": ("INT", {"default": 69, "min": 0, "max": 2147483646, "step": 1}),
|
||||
"temperature": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 2.0, "step": 0.1})
|
||||
},
|
||||
"optional": {
|
||||
"thinking": ("BOOLEAN", {"default": False}),
|
||||
"thinking_budget": ("INT", {"default": 1024, "min": 0, "max": 24576, "step": 1}),
|
||||
"thinking_budget": ("INT", {"default": 1024, "min": 0, "max": 24576, "step": 1, "tooltip": "-1 = auto, 0 = disabled, 1+ = token budget"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AUDIO", "AUDIO", "AUDIO", "AUDIO", "STRING")
|
||||
RETURN_NAMES = ("speaker_1", "speaker_2", "speaker_3", "speaker_4", "json")
|
||||
RETURN_TYPES = ("AUDIO", "AUDIO", "AUDIO", "AUDIO")
|
||||
RETURN_NAMES = ("speaker_1", "speaker_2", "speaker_3", "speaker_4")
|
||||
FUNCTION = "diarise"
|
||||
CATEGORY = "audio/diarise"
|
||||
|
||||
@@ -64,7 +64,7 @@ class GeminiDiarisationAPI:
|
||||
w.writeframes((audio_np * 32767).astype(np.int16).tobytes())
|
||||
|
||||
# 2. Setup Client
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key: raise ValueError("API Key missing")
|
||||
client = genai.Client(api_key=key, http_options={'api_version': 'v1beta'})
|
||||
|
||||
@@ -149,7 +149,6 @@ class GeminiDiarisationAPI:
|
||||
tensor = torch.from_numpy(track).float().unsqueeze(0).unsqueeze(0)
|
||||
outputs.append({"waveform": tensor, "sample_rate": sr})
|
||||
|
||||
outputs.append(json.dumps(result, indent=2))
|
||||
return tuple(outputs)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {"GeminiDiarisationAPI": GeminiDiarisationAPI}
|
||||
|
||||
+3
-3
@@ -17,11 +17,11 @@ class GeminiChatNode:
|
||||
"temperature": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 2.0, "step": 0.1}),
|
||||
"thinking": ("BOOLEAN", {"default": False}),
|
||||
"seed": ("INT", {"default": 69, "min": -1, "max": 2147483646, "step": 1}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False})
|
||||
"api_key": ("STRING", {"default": "", "multiline": False, "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"})
|
||||
},
|
||||
"optional": {
|
||||
"system_instruction": ("STRING", {"multiline": True, "default": ""}),
|
||||
"thinking_budget": ("INT", {"default": 0, "min": -1, "max": 24576, "step": 1}),
|
||||
"thinking_budget": ("INT", {"default": 0, "min": -1, "max": 24576, "step": 1, "tooltip": "-1 = auto, 0 = disabled"}),
|
||||
"image": ("IMAGE",),
|
||||
"audio": ("AUDIO",),
|
||||
}
|
||||
@@ -35,7 +35,7 @@ class GeminiChatNode:
|
||||
def generate(self, prompt, model, temperature, thinking, seed, api_key,
|
||||
system_instruction=None, thinking_budget=-1, image=None, audio=None):
|
||||
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key: raise ValueError("Error: No API key provided.")
|
||||
|
||||
client = genai.Client(api_key=key, http_options={'api_version': 'v1beta'})
|
||||
|
||||
+3
-3
@@ -20,10 +20,10 @@ class GeminiSegmentationNode:
|
||||
"temperature": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 2.0, "step": 0.1}),
|
||||
"thinking": ("BOOLEAN", {"default": False}),
|
||||
"seed": ("INT", {"default": 69, "min": -1, "max": 2147483646, "step": 1}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False})
|
||||
"api_key": ("STRING", {"default": "", "multiline": False, "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"})
|
||||
},
|
||||
"optional": {
|
||||
"thinking_budget": ("INT", {"default": 0, "min": -1, "max": 24576, "step": 1}),
|
||||
"thinking_budget": ("INT", {"default": 0, "min": -1, "max": 24576, "step": 1, "tooltip": "-1 = auto, 0 = disabled"}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class GeminiSegmentationNode:
|
||||
CATEGORY = "image/generation"
|
||||
|
||||
def generate_segmentation(self, image, segment_prompt, model, temperature, thinking, seed, api_key, thinking_budget=0):
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")
|
||||
if not key: raise ValueError("API Key missing")
|
||||
client = genai.Client(api_key=key, http_options={'api_version': 'v1beta'})
|
||||
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ class GeminiTTSNode:
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"multiline": True, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"}),
|
||||
"model": (["gemini-2.5-flash-preview-tts", "gemini-2.5-pro-preview-tts"],),
|
||||
"voice_id": (["Zephyr", "Puck", "Charon", "Kore", "Fenrir", "Leda", "Orus", "Aoede", "Callirrhoe", "Autonoe", "Enceladus", "Iapetus", "Umbriel", "Algieba", "Despina", "Erinome", "Achernar", "Laomedeia", "Rasalgethi", "Algenib", "Achird", "Pulcherrima", "Gacrux", "Schedar", "Alnilam", "Sulafat", "Sadaltager", "Sadachbia", "Vindemiatrix", "Zubenelgenubi"],),
|
||||
"seed": ("INT", {"default": 69, "min": -1, "max": 2147483646, "step": 1}),
|
||||
@@ -30,7 +30,7 @@ class GeminiTTSNode:
|
||||
if not text.strip():
|
||||
raise ValueError("Text input cannot be empty.")
|
||||
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("No API key provided.")
|
||||
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ class GPTImageEditNode:
|
||||
"image_1": ("IMAGE",),
|
||||
"model": (["gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5"],),
|
||||
"prompt": ("STRING", {"multiline": True, "default": "Edit this image"}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put OpenAI API key or .env variable name (OPENAI_API_KEY)"}),
|
||||
"background": (["auto", "transparent", "opaque"], {"default": "auto"}),
|
||||
"quality": (["auto", "high", "medium", "low"], {"default": "auto"}),
|
||||
"size": (["auto", "1024x1024", "1536x1024", "1024x1536"], {"default": "auto"}),
|
||||
@@ -56,7 +56,7 @@ class GPTImageEditNode:
|
||||
def edit_image(self, image_1, model, prompt, api_key, background, quality, size,
|
||||
output_format, output_compression, n_images, mask=None, **kwargs):
|
||||
|
||||
key = api_key.strip() or os.environ.get("OPENAI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("OPENAI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("GPT Image Edit: No API Key provided.")
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class GoogleImagenNode:
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"}),
|
||||
"model": (["models/imagen-4.0-ultra-generate-001", "models/imagen-4.0-generate-001", "models/imagen-4.0-fast-generate-001", "models/imagen-3.0-generate-002"],),
|
||||
"number_of_images": ("INT", {"default": 1, "min": 1, "max": 4, "step": 1}),
|
||||
"aspect_ratio": (["1:1", "9:16", "16:9", "4:3", "3:4"],),
|
||||
@@ -31,7 +31,7 @@ class GoogleImagenNode:
|
||||
CATEGORY = "image/generation"
|
||||
|
||||
def generate_images(self, prompt, api_key, model, number_of_images, aspect_ratio, image_size, seed, guidance_scale, negative_prompt=""):
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key: raise ValueError("No API key provided.")
|
||||
|
||||
client = genai.Client(api_key=key)
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ class GoogleImagenEditNode:
|
||||
"prompt": ("STRING", {"multiline": True, "default": "Edit this image"}),
|
||||
"project_id": ("STRING", {"multiline": False, "default": ""}),
|
||||
"location": (["global", "us-central1", "us-east1", "us-east4", "us-east5", "us-south1", "us-west1", "us-west2", "us-west3", "us-west4", "northamerica-northeast1", "northamerica-northeast2", "southamerica-east1", "southamerica-west1", "africa-south1", "europe-west1", "europe-north1", "europe-west2", "europe-west3", "europe-west4", "europe-west6", "europe-west8", "europe-west9", "europe-west12", "europe-southwest1", "europe-central2", "asia-east1", "asia-east2", "asia-northeast1", "asia-northeast2", "asia-northeast3", "asia-south1", "asia-south2", "asia-southeast1", "asia-southeast2", "australia-southeast1", "australia-southeast2", "me-central1", "me-central2", "me-west1"], {"default": "us-central1"}),
|
||||
"service_account": ("STRING", {"multiline": True, "default": ""}),
|
||||
"service_account": ("STRING", {"multiline": True, "default": "", "tooltip": "Paste service account JSON content"}),
|
||||
"edit_mode": (["EDIT_MODE_INPAINT_INSERTION", "EDIT_MODE_INPAINT_REMOVAL", "EDIT_MODE_OUTPAINT", "EDIT_MODE_BGSWAP"], {"default": "EDIT_MODE_INPAINT_INSERTION"}),
|
||||
"number_of_images": ("INT", {"default": 1, "min": 1, "max": 4, "step": 1}),
|
||||
"seed": ("INT", {"default": 69, "min": 1, "max": 2147483646, "step": 1}),
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ class NanoBananaNode:
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"}),
|
||||
"model": (["gemini-3-pro-image-preview", "gemini-2.5-flash-image"],),
|
||||
"aspect_ratio": (["1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", "21:9"],),
|
||||
"resolution": (["1K", "2K", "4K"], {"default": "1K"}),
|
||||
@@ -48,7 +48,7 @@ class NanoBananaNode:
|
||||
def generate(self, api_key, model, aspect_ratio, resolution, temperature, top_p, seed,
|
||||
prompt="", system_instruction="", **kwargs):
|
||||
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("No API key provided.")
|
||||
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ class OpenAILLMNode:
|
||||
"model": (["gpt-4.1","gpt-4.1-mini","gpt-5","gpt-5.2","gpt-5-mini","gpt-5-nano","gpt-5.2-pro","o1","o3-mini"],),
|
||||
"temperature": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.01}),
|
||||
"reasoning_effort": (["low", "medium", "high"],),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put OpenAI API key or .env variable name (OPENAI_API_KEY)"}),
|
||||
"max_output_tokens": ("INT", {"default": 16384, "min": 1, "max": 32768, "step": 1})
|
||||
},
|
||||
"optional": {
|
||||
@@ -36,7 +36,7 @@ class OpenAILLMNode:
|
||||
if not prompt.strip():
|
||||
raise ValueError("Prompt cannot be empty.")
|
||||
|
||||
key = api_key.strip() or os.environ.get("OPENAI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("OPENAI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("No API key provided.")
|
||||
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ class OpenAITTSNode:
|
||||
"pcm"
|
||||
],),
|
||||
"speed": ("FLOAT", {"default": 1.0, "min": 0.25, "max": 4.0, "step": 0.01}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put OpenAI API key or .env variable name (OPENAI_API_KEY)"}),
|
||||
},
|
||||
"optional": {
|
||||
"instructions": ("STRING", {"multiline": True, "default": ""}),
|
||||
@@ -53,7 +53,7 @@ class OpenAITTSNode:
|
||||
if not text.strip():
|
||||
raise ValueError("Text input cannot be empty.")
|
||||
|
||||
key = api_key.strip() or os.environ.get("OPENAI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("OPENAI_API_KEY")
|
||||
if not key:
|
||||
raise ValueError("No API key provided. Set OPENAI_API_KEY environment variable or provide it in the node.")
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "externalapi-helpers"
|
||||
description = "Various ComfyUI nodes for Gemini, Replicate and OpenAI"
|
||||
version = "1.0.6"
|
||||
version = "1.0.7"
|
||||
license = {file = "LICENSE"}
|
||||
# classifiers = [
|
||||
# # For OS-independent nodes (works on all operating systems)
|
||||
@@ -20,7 +20,7 @@ license = {file = "LICENSE"}
|
||||
# "Environment :: GPU :: Apple Metal", # Apple Metal support
|
||||
# ]
|
||||
|
||||
dependencies = ["replicate", "pillow", "numpy", "torch", "google-genai", "opencv-python", "soundfile", "openai", "av"]
|
||||
dependencies = ["replicate", "pillow", "numpy", "torch", "google-genai", "opencv-python", "soundfile", "openai", "av", "python-dotenv"]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/Aryan185/ComfyUI-ExternalAPI-Helpers"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
python-dotenv
|
||||
replicate
|
||||
pillow
|
||||
numpy
|
||||
|
||||
@@ -12,7 +12,7 @@ class SoraGen:
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True, "default": "A calico cat playing a piano on stage"}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": ""}),
|
||||
"api_key": ("STRING", {"multiline": False, "default": "", "tooltip": "Directly put OpenAI API key or .env variable name (OPENAI_API_KEY)"}),
|
||||
"model": (["sora-2", "sora-2-pro"], {"default": "sora-2"}),
|
||||
"size": (["720x1280", "1280x720", "1024x1792", "1792x1024"], {"default": "1280x720"}),
|
||||
"duration": (["4", "8", "12"], {"default": "4"}),
|
||||
@@ -28,7 +28,9 @@ class SoraGen:
|
||||
OUTPUT_IS_LIST = (True, False)
|
||||
|
||||
def generate_video(self, prompt, api_key, model, size, duration, seed, input_image=None):
|
||||
client = OpenAI(api_key=api_key)
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("OPENAI_API_KEY")
|
||||
if not key: raise ValueError("No API key provided.")
|
||||
client = OpenAI(api_key=key)
|
||||
api_args = {"prompt": prompt, "model": model, "size": size, "seconds": duration}
|
||||
|
||||
img_buf = None
|
||||
|
||||
@@ -29,7 +29,7 @@ class VeoVertexVideoGenerator:
|
||||
"asia-southeast2", "australia-southeast1", "australia-southeast2",
|
||||
"me-central1", "me-central2", "me-west1"
|
||||
], {"default": "us-central1"}),
|
||||
"service_account": ("STRING", {"multiline": True, "default": ""}),
|
||||
"service_account": ("STRING", {"multiline": True, "default": "", "tooltip": "Paste service account JSON content"}),
|
||||
"model": ([
|
||||
"veo-2.0-generate-001", "veo-2.0-generate-exp", "veo-2.0-generate-preview",
|
||||
"veo-3.0-generate-001", "veo-3.0-fast-generate-001",
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ class VeoGeminiVideoGenerator:
|
||||
"model": (["veo-2.0-generate-001"], {"default": "veo-2.0-generate-001"}),
|
||||
"aspect_ratio": (["16:9", "9:16"], {"default": "16:9"}),
|
||||
"duration_seconds": ("INT", {"default": 8, "min": 5, "max": 8, "step": 1}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False}),
|
||||
"api_key": ("STRING", {"default": "", "multiline": False, "tooltip": "Directly put Gemini API key or .env variable name (GEMINI_API_KEY)"}),
|
||||
"seed": ("INT", {"default": 69, "min": -1, "max": 2147483646, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
@@ -36,7 +36,7 @@ class VeoGeminiVideoGenerator:
|
||||
negative_prompt=None, image=None):
|
||||
|
||||
# 1. Setup Client
|
||||
key = api_key.strip() or os.environ.get("GEMINI_API_KEY")
|
||||
key = os.environ.get(api_key.strip(), api_key.strip()) or os.environ.get("GEMINI_API_KEY")
|
||||
if not key: raise ValueError("API Key required")
|
||||
client = genai.Client(http_options={"api_version": "v1beta"}, api_key=key)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user