speedn commited on
Commit
a1dcbea
·
verified ·
1 Parent(s): 0c51b1d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -164
app.py CHANGED
@@ -1,125 +1,85 @@
1
  # app.py
2
- # VisPrompt Studio — Image/Text → Detailed Prompts (CPU, uncensored)
3
- # - Runs on Hugging Face Spaces (free CPU)
4
- # - Upload an image OR type a scene; get an image prompt, a video prompt, or both
5
- # - Uses Salesforce/blip-image-captioning-base for image understanding (no safety filters)
6
 
7
- import os
8
- import random
9
- import math
10
- from typing import Tuple, Optional
11
 
12
  import gradio as gr
13
  from PIL import Image, ExifTags
14
  import torch
15
- from transformers import BlipProcessor, BlipForConditionalGeneration
16
 
17
- HF_MODEL_ID = "Salesforce/blip-image-captioning-base"
18
-
19
- # Lazy globals
20
- _processor: Optional[BlipProcessor] = None
21
- _model: Optional[BlipForConditionalGeneration] = None
22
-
23
-
24
- def _load_blip():
25
- """Load BLIP processor/model into CPU once."""
26
- global _processor, _model
27
- if _processor is None or _model is None:
28
- _processor = BlipProcessor.from_pretrained(HF_MODEL_ID)
29
- _model = BlipForConditionalGeneration.from_pretrained(HF_MODEL_ID)
30
- _model.to("cpu")
31
- _model.eval()
32
-
33
-
34
- def safe_open_image(inp) -> Optional[Image.Image]:
35
- if inp is None:
36
- return None
37
- if isinstance(inp, Image.Image):
38
- return inp.convert("RGB")
 
 
 
39
  return Image.open(inp).convert("RGB")
40
 
41
-
42
  def exif_info(img: Image.Image) -> dict:
43
- """Extract a couple of useful EXIF fields if present."""
44
  out = {}
45
  try:
46
  raw = img.getexif()
47
- if not raw:
48
- return out
49
  tag_map = {ExifTags.TAGS.get(k, k): v for k, v in raw.items()}
50
  fl = tag_map.get("FocalLength")
51
- if isinstance(fl, tuple) and len(fl) == 2 and fl[1] != 0:
52
- out["focal_length_mm"] = round(fl[0] / fl[1], 1)
53
  elif isinstance(fl, (int, float)):
54
  out["focal_length_mm"] = float(fl)
55
- if "Model" in tag_map:
56
- out["camera_model"] = str(tag_map["Model"]).strip()
57
- if "Make" in tag_map:
58
- out["camera_make"] = str(tag_map["Make"]).strip()
59
  except Exception:
60
  pass
61
  return out
62
 
63
-
64
- # Small lexicons to enrich prompts (kept inline for mobile copy/paste simplicity)
65
- CAMERA_ANGLES = [
66
- "eye-level", "low-angle", "high-angle", "aerial/top-down", "worm's-eye", "Dutch tilt"
67
- ]
68
- SHOT_SIZES = [
69
- "extreme close-up", "close-up", "medium shot", "wide shot", "extreme wide shot"
70
- ]
71
- LENSES = [
72
- "14mm ultra-wide", "24mm wide-angle", "35mm street", "50mm standard", "85mm portrait", "135mm telephoto", "200mm telephoto"
73
- ]
74
- LIGHTING = [
75
- "soft diffused light", "golden hour rim light", "overcast softbox feel", "hard noon sun with crisp shadows",
76
- "blue hour ambient", "tungsten practicals", "neon key with colored rim", "studio softbox left + kicker right",
77
- "volumetric god rays", "moody chiaroscuro"
78
- ]
79
- COMPOSITION = [
80
- "rule of thirds", "leading lines", "central composition", "frame within a frame", "negative space",
81
- "foreground bokeh", "shallow depth of field", "symmetry", "diagonal dynamics", "layered depth"
82
- ]
83
- POST = [
84
- "high micro-contrast", "subtle film grain", "cinematic color grade", "Kodak Portra palette",
85
- "teal–orange split tone", "matte shadows", "HDR tonality restrained", "8k detail", "photorealistic finish"
86
- ]
87
- STYLES = [
88
- "documentary realism", "editorial fashion", "street photography", "nature landscape", "architectural minimalism",
89
- "cyberpunk neon", "sci-fi cinematic", "fantasy epic", "moody noir", "retro 35mm film"
90
- ]
91
- VIDEO_MOTION = [
92
- "slow dolly-in", "gentle push-in", "handheld micro-jitters", "locked-off tripod", "gimbal glide", "orbit right-to-left",
93
- "crane rise", "parallax truck shot", "rack focus mid-shot"
94
- ]
95
- VIDEO_META = [
96
- "24 fps", "30 fps", "48 fps", "cinematic motion blur", "shutter 1/48", "global illumination feel"
97
- ]
98
- VIDEO_TRANSITIONS = ["straight cut", "cinematic fade-in/out", "cross dissolve", "match cut"]
99
- NEGATIVE = [
100
- "no distortion", "no chromatic aberration", "no blown highlights", "no excessive sharpening",
101
- "no artifacts", "no watermark", "no text overlay"
102
- ]
103
-
104
 
105
  def smart_choices(caption: str, w: int, h: int, exif: dict, seed: int):
106
- """Pick plausible settings using simple heuristics."""
107
  rnd = random.Random(seed)
108
  aspect = (w / h) if h > 0 else 1.0
109
-
110
  shot = "wide shot" if aspect >= 1.5 else "medium shot"
111
  text = caption.lower()
112
-
113
- if any(k in text for k in ["portrait", "selfie", "face", "headshot"]):
114
  shot = "close-up"
115
-
116
- if any(k in text for k in ["aerial", "drone", "top-down", "overhead", "bird's-eye", "bird’s-eye"]):
117
  angle = "aerial/top-down"
118
- elif any(k in text for k in ["towering", "imposing", "hero", "statue"]):
119
  angle = "low-angle"
120
  else:
121
- angle = rnd.choice(CAMERA_ANGLES[:3]) # eye/high/low
122
-
123
  lens = f'{exif["focal_length_mm"]}mm' if "focal_length_mm" in exif else rnd.choice(LENSES)
124
  light = rnd.choice(LIGHTING)
125
  comp = ", ".join(rnd.sample(COMPOSITION, k=2))
@@ -128,61 +88,60 @@ def smart_choices(caption: str, w: int, h: int, exif: dict, seed: int):
128
  neg = ", ".join(NEGATIVE[:3] + rnd.sample(NEGATIVE[3:], k=2))
129
  return angle, shot, lens, light, comp, style, post, neg, aspect
130
 
 
 
 
 
 
131
 
132
- @torch.inference_mode()
133
- def caption_image(img: Image.Image, beam_search: bool, max_len: int) -> str:
134
- _load_blip()
135
- inputs = _processor(images=img, return_tensors="pt")
136
- max_len = int(max(16, min(128, max_len)))
137
- if beam_search:
138
- kwargs = dict(max_length=max_len, num_beams=3)
139
- else:
140
- kwargs = dict(max_length=max_len)
141
- out = _model.generate(**inputs, **kwargs)
142
- return _processor.decode(out[0], skip_special_tokens=True).strip()
143
-
144
-
145
- def build_image_prompt(subject_desc: str, angle: str, shot: str, lens: str,
146
- light: str, comp: str, style: str, post: str, aspect: float) -> str:
147
- ar_text = "16:9" if aspect >= 1.6 else ("4:3" if aspect >= 1.3 else "1:1")
148
- prompt = (
149
- f"{subject_desc}. "
150
- f"Camera angle: {angle}. Shot size: {shot}. Lens: {lens}. "
151
- f"Lighting: {light}. Composition: {comp}. Style: {style}. Post-processing: {post}. "
152
- f"Aspect ratio hint: {ar_text}. "
153
- f"Ultra-detailed, physically plausible, consistent scale."
154
- )
155
- return prompt
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
- def build_video_prompt(image_prompt: str, motion: str, meta: list, transition: str, seconds: int) -> str:
159
- meta_str = ", ".join(meta)
160
- return (
161
- f"{image_prompt} "
162
- f"Now render as a {seconds}s cinematic video; camera motion: {motion}; "
163
- f"{meta_str}; transitions: {transition}. "
164
- f"Maintain temporal consistency, realistic motion parallax, and coherent lighting through the sequence."
165
- )
 
 
 
 
166
 
 
 
 
 
 
167
 
168
- def generate(
169
- image: Optional[Image.Image],
170
- text_scene: str,
171
- mode: str,
172
- beam_search: bool,
173
- max_len: int,
174
- seconds: int,
175
- seed: int
176
- ):
177
- """
178
- Returns: (caption, image_prompt, video_prompt) per selected mode.
179
- """
180
  img = safe_open_image(image)
181
  caption = ""
182
  base_desc = ""
183
 
184
  if img is not None:
185
- caption = caption_image(img, beam_search=beam_search, max_len=max_len)
186
  w, h = img.size
187
  exif = exif_info(img)
188
  angle, shot, lens, light, comp, style, post, neg, aspect = smart_choices(caption, w, h, exif, seed)
@@ -196,8 +155,7 @@ def generate(
196
  angle, shot, lens, light, comp, style, post, neg, aspect = smart_choices(base_desc, w, h, exif, seed)
197
 
198
  image_prompt = build_image_prompt(base_desc, angle, shot, lens, light, comp, style, post, aspect)
199
- negative_line = f"\nNegative prompt hints: {neg}"
200
-
201
  video_prompt = build_video_prompt(
202
  image_prompt,
203
  motion=random.choice(VIDEO_MOTION),
@@ -207,36 +165,36 @@ def generate(
207
  )
208
 
209
  if mode == "Image prompt":
210
- return caption, image_prompt + negative_line, ""
211
  elif mode == "Video prompt":
212
  return caption, "", video_prompt
213
  else:
214
- return caption, image_prompt + negative_line, video_prompt
215
 
216
-
217
- TITLE = "VisPrompt Studio — Image/Text → Prompts (CPU)"
218
  DESC = """
219
  Upload an image **or** describe a scene.
220
- Get a polished **image prompt**, a **video prompt**, or **both** — with camera angle, shot size, lens, lighting, composition, style, post, aspect ratio hints, plus optional negative prompt hints.
221
 
222
- - **Model:** Salesforce/blip-image-captioning-base (CPU; no built-in safety filters)
223
- - **Hardware:** Works on free CPU Spaces (first run downloads weights)
 
224
  """
225
 
226
-
227
  with gr.Blocks(title=TITLE) as demo:
228
  gr.Markdown(f"# {TITLE}\n{DESC}")
229
-
230
  with gr.Row():
231
  with gr.Column(scale=1):
 
232
  with gr.Tab("Image input"):
233
  image = gr.Image(type="pil", label="Upload an image", height=360)
234
  with gr.Tab("Text input"):
235
  text_scene = gr.Textbox(lines=6, placeholder="Describe the scene you want to reproduce...", label="Scene description")
236
 
237
- mode = gr.Radio(choices=["Image prompt", "Video prompt", "Both"], value="Both", label="Output type")
238
- beam_search = gr.Checkbox(True, label="Use beam search for caption (slightly slower, more detail)")
239
- max_len = gr.Slider(48, 128, value=80, step=1, label="Caption max length")
240
  seconds = gr.Slider(3, 12, value=6, step=1, label="Video duration (seconds)")
241
  seed = gr.Slider(0, 9999, value=1234, step=1, label="Style seed")
242
 
@@ -244,24 +202,14 @@ with gr.Blocks(title=TITLE) as demo:
244
 
245
  with gr.Column(scale=1):
246
  caption_box = gr.Textbox(label="Image caption (from model)", interactive=False, lines=3, show_copy_button=True)
247
- img_prompt_box = gr.Textbox(
248
- label="Image Prompt (copy-paste to image generators)",
249
- interactive=False,
250
- lines=12,
251
- show_copy_button=True,
252
- )
253
- vid_prompt_box = gr.Textbox(
254
- label="Video Prompt (copy-paste to video generators)",
255
- interactive=False,
256
- lines=14,
257
- show_copy_button=True,
258
- )
259
 
260
  run.click(
261
  fn=generate,
262
- inputs=[image, text_scene, mode, beam_search, max_len, seconds, seed],
263
  outputs=[caption_box, img_prompt_box, vid_prompt_box]
264
  )
265
 
266
  if __name__ == "__main__":
267
- demo.launch()
 
1
  # app.py
2
+ # VisPrompt Studio — Image/Text → Detailed Prompts (CPU, mostly uncensored)
3
+ # Models:
4
+ # - Qwen2-VL-2B-Instruct (default; stronger on people/NSFW, slower on CPU)
5
+ # - Salesforce/blip-image-captioning-base (fallback; faster on CPU)
6
 
7
+ import os, random, math
8
+ from typing import Optional, Tuple
 
 
9
 
10
  import gradio as gr
11
  from PIL import Image, ExifTags
12
  import torch
 
13
 
14
+ from transformers import (
15
+ AutoProcessor,
16
+ AutoModelForVision2Seq,
17
+ BlipProcessor,
18
+ BlipForConditionalGeneration,
19
+ )
20
+
21
+ # ===== Model IDs =====
22
+ MODEL_QWEN2_VL = "Qwen/Qwen2-VL-2B-Instruct"
23
+ MODEL_BLIP = "Salesforce/blip-image-captioning-base"
24
+
25
+ # Lazy globals for each backend
26
+ _q_processor = None
27
+ _q_model = None
28
+ _b_processor = None
29
+ _b_model = None
30
+
31
+ def device():
32
+ # Free CPU Space: force cpu. (If you later use ZeroGPU, you can set CUDA here.)
33
+ return "cpu"
34
+
35
+ # ---------- Utilities ----------
36
+ def safe_open_image(inp):
37
+ if inp is None: return None
38
+ if isinstance(inp, Image.Image): return inp.convert("RGB")
39
  return Image.open(inp).convert("RGB")
40
 
 
41
  def exif_info(img: Image.Image) -> dict:
 
42
  out = {}
43
  try:
44
  raw = img.getexif()
45
+ if not raw: return out
 
46
  tag_map = {ExifTags.TAGS.get(k, k): v for k, v in raw.items()}
47
  fl = tag_map.get("FocalLength")
48
+ if isinstance(fl, tuple) and len(fl)==2 and fl[1]!=0:
49
+ out["focal_length_mm"] = round(fl[0]/fl[1], 1)
50
  elif isinstance(fl, (int, float)):
51
  out["focal_length_mm"] = float(fl)
52
+ if "Model" in tag_map: out["camera_model"] = str(tag_map["Model"]).strip()
53
+ if "Make" in tag_map: out["camera_make"] = str(tag_map["Make"]).strip()
 
 
54
  except Exception:
55
  pass
56
  return out
57
 
58
+ CAMERA_ANGLES = ["eye-level","low-angle","high-angle","aerial/top-down","worm's-eye","Dutch tilt"]
59
+ SHOT_SIZES = ["extreme close-up","close-up","medium shot","wide shot","extreme wide shot"]
60
+ LENSES = ["14mm ultra-wide","24mm wide-angle","35mm street","50mm standard","85mm portrait","135mm telephoto","200mm telephoto"]
61
+ LIGHTING = ["soft diffused light","golden hour rim light","overcast softbox feel","hard noon sun with crisp shadows","blue hour ambient","tungsten practicals","neon key with colored rim","studio softbox left + kicker right","volumetric god rays","moody chiaroscuro"]
62
+ COMPOSITION = ["rule of thirds","leading lines","central composition","frame within a frame","negative space","foreground bokeh","shallow depth of field","symmetry","diagonal dynamics","layered depth"]
63
+ POST = ["high micro-contrast","subtle film grain","cinematic color grade","Kodak Portra palette","teal–orange split tone","matte shadows","HDR tonality restrained","8k detail","photorealistic finish"]
64
+ STYLES = ["documentary realism","editorial fashion","street photography","nature landscape","architectural minimalism","cyberpunk neon","sci-fi cinematic","fantasy epic","moody noir","retro 35mm film"]
65
+ VIDEO_MOTION = ["slow dolly-in","gentle push-in","handheld micro-jitters","locked-off tripod","gimbal glide","orbit right-to-left","crane rise","parallax truck shot","rack focus mid-shot"]
66
+ VIDEO_META = ["24 fps","30 fps","48 fps","cinematic motion blur","shutter 1/48","global illumination feel"]
67
+ VIDEO_TRANSITIONS = ["straight cut","cinematic fade-in/out","cross dissolve","match cut"]
68
+ NEGATIVE = ["no distortion","no chromatic aberration","no blown highlights","no excessive sharpening","no artifacts","no watermark","no text overlay"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  def smart_choices(caption: str, w: int, h: int, exif: dict, seed: int):
 
71
  rnd = random.Random(seed)
72
  aspect = (w / h) if h > 0 else 1.0
 
73
  shot = "wide shot" if aspect >= 1.5 else "medium shot"
74
  text = caption.lower()
75
+ if any(k in text for k in ["portrait","selfie","face","headshot"]):
 
76
  shot = "close-up"
77
+ if any(k in text for k in ["aerial","drone","top-down","overhead","bird's-eye","bird’s-eye"]):
 
78
  angle = "aerial/top-down"
79
+ elif any(k in text for k in ["towering","imposing","hero","statue"]):
80
  angle = "low-angle"
81
  else:
82
+ angle = rnd.choice(CAMERA_ANGLES[:3])
 
83
  lens = f'{exif["focal_length_mm"]}mm' if "focal_length_mm" in exif else rnd.choice(LENSES)
84
  light = rnd.choice(LIGHTING)
85
  comp = ", ".join(rnd.sample(COMPOSITION, k=2))
 
88
  neg = ", ".join(NEGATIVE[:3] + rnd.sample(NEGATIVE[3:], k=2))
89
  return angle, shot, lens, light, comp, style, post, neg, aspect
90
 
91
+ def build_image_prompt(desc, angle, shot, lens, light, comp, style, post, aspect):
92
+ ar = "16:9" if aspect >= 1.6 else ("4:3" if aspect >= 1.3 else "1:1")
93
+ return (f"{desc}. Camera angle: {angle}. Shot size: {shot}. Lens: {lens}. "
94
+ f"Lighting: {light}. Composition: {comp}. Style: {style}. Post-processing: {post}. "
95
+ f"Aspect ratio hint: {ar}. Ultra-detailed, physically plausible, consistent scale.")
96
 
97
+ def build_video_prompt(img_prompt: str, motion: str, meta: list, transition: str, seconds: int):
98
+ meta_str = ", ".join(meta)
99
+ return (f"{img_prompt} Now render as a {seconds}s cinematic video; camera motion: {motion}; "
100
+ f"{meta_str}; transitions: {transition}. Maintain temporal consistency, realistic parallax, coherent lighting.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
+ # ---------- Backends ----------
103
+ @torch.inference_mode()
104
+ def qwen2_vl_caption(img: Image.Image, max_new_tokens: int = 96) -> str:
105
+ global _q_processor, _q_model
106
+ if _q_processor is None or _q_model is None:
107
+ _q_processor = AutoProcessor.from_pretrained(MODEL_QWEN2_VL, trust_remote_code=True)
108
+ _q_model = AutoModelForVision2Seq.from_pretrained(MODEL_QWEN2_VL, torch_dtype=torch.float32, trust_remote_code=True)
109
+ _q_model.to(device()).eval()
110
+ # Simple instruction to push detailed descriptions (uncensored)
111
+ prompt = "Describe this image in exhaustive detail: people, clothing, actions, camera angle, lighting, background."
112
+ inputs = _q_processor(text=prompt, images=img, return_tensors="pt")
113
+ out = _q_model.generate(**inputs, max_new_tokens=max_new_tokens)
114
+ text = _q_processor.batch_decode(out, skip_special_tokens=True)[0].strip()
115
+ return text
116
 
117
+ @torch.inference_mode()
118
+ def blip_caption(img: Image.Image, beam_search: bool = True, max_len: int = 80) -> str:
119
+ global _b_processor, _b_model
120
+ if _b_processor is None or _b_model is None:
121
+ _b_processor = BlipProcessor.from_pretrained(MODEL_BLIP)
122
+ _b_model = BlipForConditionalGeneration.from_pretrained(MODEL_BLIP)
123
+ _b_model.to(device()).eval()
124
+ inputs = _b_processor(images=img, return_tensors="pt")
125
+ max_len = int(max(16, min(128, max_len)))
126
+ kwargs = dict(max_length=max_len, num_beams=3) if beam_search else dict(max_length=max_len)
127
+ out = _b_model.generate(**inputs, **kwargs)
128
+ return _b_processor.decode(out[0], skip_special_tokens=True).strip()
129
 
130
+ def caption_image(model_choice: str, img: Image.Image, beam_search: bool, max_len: int) -> str:
131
+ if model_choice == "Qwen2-VL-2B-Instruct":
132
+ return qwen2_vl_caption(img, max_new_tokens=max_len)
133
+ else:
134
+ return blip_caption(img, beam_search=beam_search, max_len=max_len)
135
 
136
+ # ---------- Main generate ----------
137
+ def generate(image: Optional[Image.Image], text_scene: str, mode: str,
138
+ beam_search: bool, max_len: int, seconds: int, seed: int, model_choice: str):
 
 
 
 
 
 
 
 
 
139
  img = safe_open_image(image)
140
  caption = ""
141
  base_desc = ""
142
 
143
  if img is not None:
144
+ caption = caption_image(model_choice, img, beam_search, max_len)
145
  w, h = img.size
146
  exif = exif_info(img)
147
  angle, shot, lens, light, comp, style, post, neg, aspect = smart_choices(caption, w, h, exif, seed)
 
155
  angle, shot, lens, light, comp, style, post, neg, aspect = smart_choices(base_desc, w, h, exif, seed)
156
 
157
  image_prompt = build_image_prompt(base_desc, angle, shot, lens, light, comp, style, post, aspect)
158
+ neg_line = f"\nNegative prompt hints: {neg}"
 
159
  video_prompt = build_video_prompt(
160
  image_prompt,
161
  motion=random.choice(VIDEO_MOTION),
 
165
  )
166
 
167
  if mode == "Image prompt":
168
+ return caption, image_prompt + neg_line, ""
169
  elif mode == "Video prompt":
170
  return caption, "", video_prompt
171
  else:
172
+ return caption, image_prompt + neg_line, video_prompt
173
 
174
+ # ---------- UI ----------
175
+ TITLE = "VisPrompt Studio — Image/Text → Prompts (Qwen2-VL or BLIP)"
176
  DESC = """
177
  Upload an image **or** describe a scene.
178
+ Get a polished **image prompt**, a **video prompt**, or **both** — with camera angle, shot size, lens, lighting, composition, style, post, AR hints, plus optional negative prompts.
179
 
180
+ **Models**:
181
+ - **Qwen2-VL-2B-Instruct (default)** stronger on people/NSFW & fashion; slower on CPU.
182
+ - **BLIP base** — faster on CPU; simpler captions.
183
  """
184
 
 
185
  with gr.Blocks(title=TITLE) as demo:
186
  gr.Markdown(f"# {TITLE}\n{DESC}")
 
187
  with gr.Row():
188
  with gr.Column(scale=1):
189
+ model_choice = gr.Dropdown(["Qwen2-VL-2B-Instruct","BLIP base"], value="Qwen2-VL-2B-Instruct", label="Captioning model")
190
  with gr.Tab("Image input"):
191
  image = gr.Image(type="pil", label="Upload an image", height=360)
192
  with gr.Tab("Text input"):
193
  text_scene = gr.Textbox(lines=6, placeholder="Describe the scene you want to reproduce...", label="Scene description")
194
 
195
+ mode = gr.Radio(choices=["Image prompt","Video prompt","Both"], value="Both", label="Output type")
196
+ beam_search = gr.Checkbox(True, label="BLIP: beam search (ignored for Qwen2-VL)")
197
+ max_len = gr.Slider(48, 128, value=96, step=1, label="Caption length / max tokens")
198
  seconds = gr.Slider(3, 12, value=6, step=1, label="Video duration (seconds)")
199
  seed = gr.Slider(0, 9999, value=1234, step=1, label="Style seed")
200
 
 
202
 
203
  with gr.Column(scale=1):
204
  caption_box = gr.Textbox(label="Image caption (from model)", interactive=False, lines=3, show_copy_button=True)
205
+ img_prompt_box = gr.Textbox(label="Image Prompt", interactive=False, lines=12, show_copy_button=True)
206
+ vid_prompt_box = gr.Textbox(label="Video Prompt", interactive=False, lines=14, show_copy_button=True)
 
 
 
 
 
 
 
 
 
 
207
 
208
  run.click(
209
  fn=generate,
210
+ inputs=[image, text_scene, mode, beam_search, max_len, seconds, seed, model_choice],
211
  outputs=[caption_box, img_prompt_box, vid_prompt_box]
212
  )
213
 
214
  if __name__ == "__main__":
215
+ demo.launch()