luckiest-co 1.0.65 → 1.0.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ # Phase 5: Video Ad Generation
2
+
3
+ After the user is satisfied with the campaign image set, offer to create a short cinematic video ad.
4
+
5
+ Ask:
6
+
7
+ ```markdown
8
+ Generate a short video ad from the selected campaign images?
9
+
10
+ - Yes, generate video
11
+ - No, skip
12
+ ```
13
+
14
+ If yes, let the user pick which campaign image should be used as the video's first frame:
15
+
16
+ ```markdown
17
+ Which campaign image should become the video's first frame?
18
+
19
+ - Shot 1: Hero
20
+ - Shot 2: Detail
21
+ - Shot 3: Environment
22
+ - Other selected campaign image
23
+ ```
24
+
25
+ ## Video Motion Prompt
26
+
27
+ Construct a motion-focused prompt that describes camera movement, lighting animation, environmental motion, and product fidelity.
28
+
29
+ ```markdown
30
+ {camera movement} shot of the selected product campaign image.
31
+ Preserve the product's exact silhouette, closure geometry, material, label placement, and luxury set design from the first frame.
32
+ {lighting animation}. {environmental motion}.
33
+ Cinematic beauty commercial, luxury fragrance advertisement, smooth motion, professional color grading, premium campaign finish.
34
+ ```
35
+
36
+ ## Camera Movement Options
37
+
38
+ - **Slow dolly zoom in**: slow push-in that emphasizes product detail
39
+ - **Gentle orbit around**: subtle camera arc that reveals dimensionality
40
+ - **Slow pull-back reveal**: starts close, then reveals the full set
41
+ - **Static with subtle parallax**: premium stillness with micro-depth movement
42
+ - **Crane down**: downward reveal that feels dramatic and editorial
43
+
44
+ ## Lighting Animation
45
+
46
+ - Golden light slowly shifting across the glass or packaging surface
47
+ - Soft caustics dancing on nearby marble, water, or reflective surfaces
48
+ - Light gradually transitioning from cool to warm
49
+ - Rim light subtly tracing the bottle or container edge
50
+ - Highlight line gliding across the cap, label, or curved body
51
+
52
+ Match the lighting physics to the product material. Do not describe caustics or transmission for frosted, matte, ceramic, or opaque packaging.
53
+
54
+ ## Environmental Motion
55
+
56
+ - Particles floating gently in the air
57
+ - Petals drifting slowly through the frame
58
+ - Water ripples expanding outward
59
+ - Silk fabric undulating in a gentle breeze
60
+ - Mist swirling around the base
61
+ - Subtle shadow movement from leaves, curtains, or sculptural props
62
+
63
+ ## Generation Guidance
64
+
65
+ Use whichever image-to-video tool this session has (for example a connected
66
+ image-to-video MCP tool). If the user wants more than a single 3-5 second clip
67
+ (a cut with several shots, captions, music, or end card), hand off to
68
+ `luckiest-video-studio` with the chosen stills as references instead.
69
+
70
+ Generate a short video from the selected campaign image as the first frame. Keep motion elegant and restrained; the product should remain stable, recognizable, and premium.
71
+
72
+ Recommended defaults:
73
+
74
+ | Setting | Recommendation |
75
+ |---------|----------------|
76
+ | Duration | 3-5 seconds |
77
+ | Aspect ratio | Match the selected campaign image |
78
+ | Variants | 1-2 options unless the user asks for more |
79
+ | Motion intensity | Low to medium; avoid chaotic movement |
80
+
81
+ ## QA Before Presenting
82
+
83
+ Review the video before showing it:
84
+
85
+ | Check | What to verify |
86
+ |-------|----------------|
87
+ | Product identity | Product remains recognizable throughout |
88
+ | Shape stability | Bottle/container does not melt, stretch, or morph |
89
+ | Closure fidelity | Cap, pump, stopper, or lid remains consistent |
90
+ | Label stability | Label does not drift unnaturally; minor AI text changes may be acceptable |
91
+ | Motion quality | Camera movement is smooth and premium |
92
+ | Material truth | Light behavior matches the product material |
93
+
94
+ If the product shape changes significantly, regenerate with stronger fidelity language and calmer motion.
95
+
96
+ ## Presentation
97
+
98
+ Show the final video result as playable media or a link, plus a one-sentence creative description. Keep logs and request payloads out of the main reply, but answer plainly if the user asks which model, settings, or prompt made it.
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Shrink local product photos so an agent can read them as images.
4
+
5
+ Fits each image inside 1024x1024, converts it to JPEG (quality 85), then lowers
6
+ quality and scale until the file is at most 145 KB. Reads local files only and
7
+ makes no network calls. Needs Pillow (pip install pillow).
8
+
9
+ Usage:
10
+ python3 compress_product_img.py --images photo.jpg [more.jpg ...] [--out-dir DIR]
11
+
12
+ Prints one line per image:
13
+ [COMPRESSED] <out path> (1200KB -> 140KB, 1024x768)
14
+ """
15
+
16
+ import argparse
17
+ import io
18
+ import os
19
+ import sys
20
+ import tempfile
21
+ import uuid
22
+
23
+ try:
24
+ from PIL import Image, ImageOps
25
+ except ImportError:
26
+ sys.exit("[ERROR] Pillow is not installed. Run: pip install pillow")
27
+
28
+ MAX_DIM = 1024
29
+ MAX_BYTES = 148_480 # 145 KB, under the agent Read tool's image size limit
30
+
31
+
32
+ def _open_rgb(raw: bytes) -> Image.Image:
33
+ img = Image.open(io.BytesIO(raw))
34
+ img = ImageOps.exif_transpose(img) or img
35
+ return img.convert("RGB") if img.mode != "RGB" else img
36
+
37
+
38
+ def compress(raw: bytes) -> tuple[bytes, int, int]:
39
+ """Return (jpeg_bytes, width, height), at most MAX_BYTES when reachable."""
40
+ img = _open_rgb(raw)
41
+ img.thumbnail((MAX_DIM, MAX_DIM), Image.Resampling.LANCZOS)
42
+ base_w, base_h = img.size
43
+
44
+ quality, scale = 85, 1.0
45
+ while True:
46
+ size = (max(1, round(base_w * scale)), max(1, round(base_h * scale)))
47
+ frame = img if scale == 1.0 else img.resize(size, Image.Resampling.LANCZOS)
48
+ buf = io.BytesIO()
49
+ frame.save(buf, format="JPEG", quality=quality)
50
+ out = buf.getvalue()
51
+ if len(out) <= MAX_BYTES or (quality <= 30 and scale <= 0.3):
52
+ return out, frame.width, frame.height
53
+ if quality > 30:
54
+ quality -= 10
55
+ else:
56
+ scale -= 0.1
57
+
58
+
59
+ def main():
60
+ parser = argparse.ArgumentParser(description="Shrink product photos for agent vision")
61
+ parser.add_argument("--images", nargs="+", required=True, help="Local image paths")
62
+ parser.add_argument("--out-dir", default=tempfile.gettempdir(), help="Where to write JPEGs")
63
+ args = parser.parse_args()
64
+ os.makedirs(args.out_dir, exist_ok=True)
65
+
66
+ for src in args.images:
67
+ if not os.path.isfile(src):
68
+ print(f"[ERROR] Not a local file: {src}")
69
+ continue
70
+ with open(src, "rb") as f:
71
+ raw = f.read()
72
+ try:
73
+ data, w, h = compress(raw)
74
+ except Exception as e: # bad or unsupported image
75
+ print(f"[ERROR] Could not compress {src}: {e}")
76
+ continue
77
+ out = os.path.join(args.out_dir, f"product_{uuid.uuid4().hex[:12]}.jpg")
78
+ with open(out, "wb") as f:
79
+ f.write(data)
80
+ print(f"[COMPRESSED] {out} ({len(raw) // 1024}KB -> {len(data) // 1024}KB, {w}x{h})")
81
+
82
+
83
+ if __name__ == "__main__":
84
+ main()