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
- 你的文件
- 由代码根据链接上传
需要付费的 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.