backup
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
"""Regenerate carpet-cleaning and commercial-overview service images with industrial extractor prompts."""
|
||||
import os, sys, time, subprocess
|
||||
try:
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
except ImportError:
|
||||
os.system(f"{sys.executable} -m pip install google-genai --quiet")
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
|
||||
API_KEY = os.environ.get("GEMINI_API_KEY", "AIzaSyB_1p8KvaT_rdNJGPs8HKk8bKsvUlcL6Kg")
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
IMG_DIR = os.path.join(BASE_DIR, "assets", "images", "services")
|
||||
VID_DIR = os.path.join(BASE_DIR, "assets", "videos", "hero", "clips")
|
||||
REEL_OUT = os.path.join(BASE_DIR, "assets", "videos", "hero", "hero-reel.mp4")
|
||||
client = genai.Client(api_key=API_KEY)
|
||||
|
||||
# ── Service images ────────────────────────────────────────────────────────────
|
||||
IMAGES = [
|
||||
{
|
||||
"name": "carpet-cleaning",
|
||||
"prompt": (
|
||||
"Wide shot of a large industrial stand-up hot water extraction machine being pushed across "
|
||||
"a plush beige residential carpet. The machine is a heavy commercial-grade upright extractor "
|
||||
"on wheels — tall, wide cleaning head at the base, long upright handle. "
|
||||
"The carpet behind it transitions from dirty and matted to clean, bright, and fluffy. "
|
||||
"Completely dry machine exterior, no steam, no water spraying anywhere. "
|
||||
"Warm natural interior light. Ultra-realistic professional photography."
|
||||
),
|
||||
},
|
||||
{
|
||||
"name": "commercial-overview",
|
||||
"prompt": (
|
||||
"Professional carpet cleaning technician in a plain black shirt, shown from the side, "
|
||||
"pushing a large industrial stand-up hot water extraction machine through a bright commercial "
|
||||
"building lobby. The machine is a heavy commercial-grade upright extractor on wheels — "
|
||||
"tall, wide cleaning head, long handle. Clean carpet visible. No steam, no water spraying, "
|
||||
"no face visible. Professional editorial photography, ultra-realistic."
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
for item in IMAGES:
|
||||
out_path = os.path.join(IMG_DIR, f"{item['name']}.jpg")
|
||||
print(f"[IMG] Generating {item['name']}...")
|
||||
try:
|
||||
resp = client.models.generate_images(
|
||||
model="imagen-4.0-generate-001",
|
||||
prompt=item["prompt"],
|
||||
config=types.GenerateImagesConfig(
|
||||
number_of_images=1, aspect_ratio="4:3",
|
||||
output_mime_type="image/jpeg",
|
||||
safety_filter_level="block_low_and_above",
|
||||
),
|
||||
)
|
||||
if resp.generated_images:
|
||||
b = resp.generated_images[0].image.image_bytes
|
||||
with open(out_path, "wb") as f:
|
||||
f.write(b)
|
||||
print(f" Saved {out_path} ({len(b)//1024}KB)")
|
||||
else:
|
||||
print(f" No image returned")
|
||||
except Exception as e:
|
||||
print(f" Error: {e}")
|
||||
|
||||
# ── Video shots ───────────────────────────────────────────────────────────────
|
||||
SHOTS = [
|
||||
{
|
||||
"name": "shot-04-extraction-carpet",
|
||||
"prompt": (
|
||||
"Cinematic slow-motion wide shot: a large industrial stand-up hot water extraction machine "
|
||||
"being pushed steadily forward across a beige residential carpet. The machine is a tall "
|
||||
"professional-grade upright extractor — heavy-duty, commercial size, on wheels, with a wide "
|
||||
"cleaning head at the base and an upright handle. No steam, no spraying water, no visible "
|
||||
"liquid anywhere on the machine exterior. The carpet behind the machine transitions from dirty "
|
||||
"and matted to bright, clean, and fluffy as it passes. Warm natural room light. Photorealistic."
|
||||
),
|
||||
},
|
||||
{
|
||||
"name": "shot-09-technician-unloading",
|
||||
"prompt": (
|
||||
"Wide shot of a professional carpet cleaning technician wearing a plain black shirt with no logo, "
|
||||
"rolling a large industrial stand-up hot water extraction machine out of a white service van "
|
||||
"parked in a residential driveway in upstate New York. The machine is a heavy commercial-grade "
|
||||
"upright extractor on wheels — tall, industrial size. Autumn trees in background, bright day. "
|
||||
"Technician shown from side or behind, no face visible. Photorealistic."
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
MODELS = ["veo-2.0-generate-001", "veo-3.0-generate-001"]
|
||||
|
||||
def poll(op, timeout=420):
|
||||
elapsed = 0
|
||||
while not op.done:
|
||||
if elapsed >= timeout:
|
||||
return None
|
||||
print(f" Waiting... ({elapsed}s)")
|
||||
time.sleep(15)
|
||||
elapsed += 15
|
||||
op = client.operations.get(op)
|
||||
return op
|
||||
|
||||
saved_clips = []
|
||||
for item in SHOTS:
|
||||
out_path = os.path.join(VID_DIR, f"{item['name']}.mp4")
|
||||
print(f"\n[VID] Generating {item['name']}...")
|
||||
done = False
|
||||
for model in MODELS:
|
||||
try:
|
||||
print(f" Model: {model}")
|
||||
op = client.models.generate_videos(
|
||||
model=model, prompt=item["prompt"],
|
||||
config=types.GenerateVideosConfig(
|
||||
aspect_ratio="16:9", resolution="720p",
|
||||
duration_seconds=6, number_of_videos=1,
|
||||
),
|
||||
)
|
||||
op = poll(op)
|
||||
if op and op.response and op.response.generated_videos:
|
||||
vid = op.response.generated_videos[0].video
|
||||
try:
|
||||
b = client.files.download(file=vid)
|
||||
except Exception:
|
||||
b = None
|
||||
if b:
|
||||
with open(out_path, "wb") as f:
|
||||
f.write(b)
|
||||
print(f" Saved ({os.path.getsize(out_path)//1024}KB)")
|
||||
saved_clips.append(item["name"])
|
||||
done = True
|
||||
break
|
||||
except Exception as e:
|
||||
print(f" Error with {model}: {e}")
|
||||
if not done:
|
||||
print(f" FAILED: {item['name']}")
|
||||
|
||||
# ── Reconcat reel if both shots regenerated ───────────────────────────────────
|
||||
if len(saved_clips) == 2:
|
||||
print("\nReconcatenating reel...")
|
||||
concat_file = os.path.join(VID_DIR, "concat.txt")
|
||||
order = [
|
||||
"shot-01-door-opens-trimmed",
|
||||
"shot-02-pan-to-stains",
|
||||
"shot-03-stain-closeup",
|
||||
"shot-04-extraction-carpet",
|
||||
"shot-05-extraction-couch",
|
||||
"shot-06-extraction-stairs",
|
||||
"shot-07-office-entryway",
|
||||
"shot-08-showroom",
|
||||
"shot-09-technician-unloading",
|
||||
]
|
||||
with open(concat_file, "w") as f:
|
||||
for name in order:
|
||||
f.write(f"file '{os.path.join(VID_DIR, name)}.mp4'\n")
|
||||
result = subprocess.run(
|
||||
["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", concat_file,
|
||||
"-c:v", "libx264", "-crf", "22", "-preset", "fast",
|
||||
"-movflags", "+faststart", REEL_OUT],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
print(f" Reel saved ({os.path.getsize(REEL_OUT)//1024}KB)")
|
||||
else:
|
||||
print(f" ffmpeg error: {result.stderr[-300:]}")
|
||||
else:
|
||||
print(f"\nOnly {len(saved_clips)}/2 video shots regenerated — skipping reconcat.")
|
||||
|
||||
print("\nDone.")
|
||||
Reference in New Issue
Block a user