LED Billboard Message
Upload a blank billboard and overlay text. Generate a smooth zoom in shot revealing your message.
概要
This ComfyUI workflow, titled 'LED Billboard Message,' is designed to seamlessly overlay text onto a blank billboard image and create a smooth zoom-in video that reveals your message. The workflow utilizes several nodes, including LoadImage for importing the billboard base, and GeminiImage2Node for integrating text onto the image. KlingStartEndFrameNode is used to define the start and end frames of the zoom-in effect, ensuring a smooth transition. SaveImage and SaveVideo nodes are employed to export the final image and video outputs.
The custom nodes from comfyui_essentials facilitate advanced operations like RegexReplace for text manipulation, enhancing the workflow's versatility.
入力するもの
- ワークフローを読み込み中
ComfyUI で実行できます。 このワークフローはこのページでは実行できません。すべてが読み込まれた状態でComfy Cloudで開くか、ご自身のComfyUI用にダウンロードしてください。
Cloudで試すワークフローの内部
ノードグラフの読み取り専用プレビューです。ノードを編集するには、Comfy Cloudで開くかダウンロードしてください。
Loading the graph
Open full-size workflow preview- 作成者
- Rob
カスタムノードが必要です
- ワークフローを読み込み中
コードからこのワークフローを使用する
可能な場合はワークフローグラフと入力から生成されます。それ以外の場合は保存された例が表示されます。料金が発生する場合があるため、コードを実行する前に認証情報とエンドポイントを確認してください。
What you need
- Runs on
- Comfy Cloud
- キー
- COMFY_API_KEY
- ファイル
- コードによって URL からアップロードされます
有料の Cloud プランとクレジットが必要です。
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"10": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "Load Billboard Image"
}
},
"11": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "auto",
"images": [
"59:59",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": "Task: Realistic composite of text content onto an LED billboard mockup, preserving original composition.\n\nInput Image(s):\n- Input 1 (Scene): Billboard mockup structure and environment. The screen area is the target destination.\n- Input 2 (Content): Source image containing text/logotype (NOT THE BACKGROUND COLOR)\n\nProcess:\n1. Identify the screen surface area in Input 1.\n2. Treat only the text of Input 2 (NOT the background color) as the content to be overlayed onto the screen.\n3. Apply a perspective transformation to the entire Input 2 content canvas so it perfectly matches the angle, orientation, and boundaries of the billboard screen in Input 1.\n4. Render the transformed content with an illuminated LED matrix aesthetic.\n\nTechnical Requirements:\n- **Composition & Scale Consistency (Crucial):** The relative scale and positioning of the text as seen within the boundaries of Input 2 MUST be maintained. Do NOT scale up the text object to fill the billboard screen. If the text is small in Input 2, it must remain small relative to the screen size in the final output, surrounded by the appropriate amount of black padding.\n- **Color & Light:** The active text pixels must be the exact hexadecimal color of image 2 text. They should emit a bright, illuminated glow (halation) typical of LED signage.\n- **Screen Texture:** The entire screen surface (both lit text and unlit background padding) must show a visible, realistic grid texture of individual LED pixel diodes.\n- **Integration:** The physical structure of the billboard framing and the surrounding environment from Input 1 must be preserved exactly.\n\nOutput: The final image showing the scene from Input 1, with the screen displaying the exact composition of Input 2 (without the solid background color) as a glowing, pixelated LED array.",
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 11111,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"12": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_2_FILENAME"
},
"_meta": {
"title": "Load Text Overlay Image"
}
},
"19": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-last_frame",
"images": [
"11",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"20": {
"class_type": "KlingStartEndFrameNode",
"inputs": {
"aspect_ratio": "16:9",
"cfg_scale": 0.5,
"end_frame": [
"11",
0
],
"mode": "pro mode / 5s duration / kling-v2-5-turbo",
"negative_prompt": "",
"prompt": "LED billboard text morphs, pixel glyphs flicker and cascade like a digital waterfall, individual LED cells pulse and brighten as new letters materialize, slight camera zoom in revealing more billboard detail and closer framing on screen, maintaining the textured LED grid with radiant glow against black panel. ",
"start_frame": [
"33",
0
]
},
"_meta": {
"title": "Kling Start-End Frame to Video"
}
},
"21": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-first_frame",
"images": [
"33",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"23": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/ComfyUI-video",
"format": "auto",
"format.codec": "auto",
"video": [
"20",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"33": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "auto",
"images": [
"49:24",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"72",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 12345,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"58": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 300
},
"_meta": {
"title": "Expand Image Borders by %"
}
},
"71": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": ""
},
"_meta": {
"title": "Describe the Outpainted Region"
}
},
"72": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "<description>",
"replace": [
"71",
0
],
"string": [
"73",
0
]
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"73": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Task: Canvas Expansion and Content Cleanup\n\nInput Image: Contains main header text, subtext, and central visual content.\n\nProcess & Requirements:\n\n1. **Text Cleanup (Removal):**\n * Identify and completely remove the \"subtext\" element.\n * Reconstruct the area beneath the removed subtext to match the immediate surrounding background texture and lighting flawlessly.\n\n2. **Header Preservation (Constraint):**\n * Isolate the \"main header text.\"\n * Ensure this header remains in its exact original position. It must not shift during the canvas expansion process.\n\n3. **Outpainting (Generation):**\n * Expand the canvas borders to fill the transparent blank area. The original pixel information MUST remain, only generate within the transparent blank area.\n * **Content Generation:** The newly generated areas must seamlessly extend outside the existing background context and MUST include the following elements if specified: <description>\n * **Technical Consistency:** Ensure perfect continuity of lighting, shadows, color palette, texture, and perspective from the original image edges into the new expanded areas. The transition between original and new content must be invisible.\n\nOutput: A larger canvas image with the subtext removed, the main header locked in place, and the surrounding environment naturally expanded."
},
"_meta": {
"title": "Prompt Template"
}
},
"49:24": {
"class_type": "ImagePadForOutpaint",
"inputs": {
"bottom": [
"49:32",
0
],
"feathering": 40,
"image": [
"11",
0
],
"left": [
"49:28",
0
],
"right": [
"49:28",
0
],
"top": [
"49:32",
0
]
},
"_meta": {
"title": "Pad Image for Outpainting"
}
},
"49:27": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"49:58",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"49:28": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"49:27",
0
],
"b": [
"49:47",
0
],
"value": "(a * b) / 2"
},
"_meta": {
"title": "Calculate left/right pixel expand"
}
},
"49:32": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"49:27",
1
],
"b": [
"49:47",
0
],
"value": "(a * b) / 2"
},
"_meta": {
"title": "Calculate top/bottom pixel expand"
}
},
"49:45": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"49:24",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"49:47": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"58",
0
],
"b": 0,
"value": "a / 100"
},
"_meta": {
"title": "Calculate % to decimal value"
}
},
"49:58": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"11",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"59:15": {
"class_type": "ResizeAndPadImage",
"inputs": {
"image": [
"12",
0
],
"interpolation": "area",
"padding_color": "black",
"target_height": [
"59:16",
1
],
"target_width": [
"59:16",
0
]
},
"_meta": {
"title": "Resize And Pad Image"
}
},
"59:16": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"10",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"59:59": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"10",
0
],
"images.image1": [
"59:15",
0
]
},
"_meta": {
"title": "Batch Images"
}
}
})
# Replace each example.com URL with a public URL of your file.
workflow.set_input("10", "image", client.assets.from_url("https://example.com/replace-with-a-url/image"))
workflow.set_input("12", "image", client.assets.from_url("https://example.com/replace-with-a-url/image_2"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)よくある質問
The LoadImage node supports common formats like JPEG and PNG. Ensure your billboard image is in one of these formats for compatibility.
The speed can be adjusted by modifying the start and end frames in the KlingStartEndFrameNode. Increasing the frame range will slow down the zoom effect.
Yes, you can return to the GeminiImage2Node to edit the text and reprocess the image and video outputs as needed.
You can adjust the text size and positioning in the GeminiImage2Node to ensure it fits appropriately on the billboard surface.