#!/usr/bin/env python3 """ quiXzoom Academy — Bildgenerator med Gemini Genererar pedagogiska bilder för utbildningsmoduler """ import os import sys import json import base64 from pathlib import Path from datetime import datetime # Konfiguration GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") GEMINI_ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp-image-generation:generateContent" S3_BUCKET = "quixzoom-landing-prod" ACADEMY_PATH = "academy/images" # Lektionsbilder som ska genereras LESSON_IMAGES = { "m1l1": { "title": "Välkommen till quiXzoom", "prompt": "En vänlig illustration av en person med smartphone som fotograferar en bro i solnedgång. Modern, ren stil med blå och gröna färger. Pedagogisk känsla, inte fotorealistisk.", "style": "illustration" }, "m1l2": { "title": "Skapa ditt konto", "prompt": "Steg-för-steg visuell guide som visar en smartphone-skärm med registreringsflöde. Visa profil, ID-verifiering och bankkonto. Ren, modern UI-stil med blå accentfärger.", "style": "ui_mockup" }, "m2l1": { "title": "AI-granskning", "prompt": "En illustration som visar hur AI analyserar en fotografi. Dela bilden i två delar: vänster sida visar originalbild på en bro, höger sida visar AI-analys med markeringar för skärpa, ljus och komposition. Futuristisk men pedagogisk stil.", "style": "technical_illustration" }, "m2l2": { "title": "Ljus och exponering", "prompt": "Tre bilder i rad som visar samma bro: 1) för mörk (underexponerad), 2) perfekt exponerad i gyllene timmen, 3) för ljus (överexponerad). Pedagogisk jämförelse med tydliga etiketter. Fotorealistisk stil.", "style": "photo_comparison" }, "m2l3": { "title": "Fokus och skärpa", "prompt": "Två bilder som visar skillnaden mellan oskarp och skarp fotografi. Vänster: suddig bild på en vägskylt. Höger: knivskarp bild på samma skylt. Pedagogisk stil med förstoringsglas-effekt som visar detaljer.", "style": "photo_comparison" }, "m2l4": { "title": "Framing och komposition", "prompt": "En illustration som visar kompositionsregler för fotografering. Visa en bro med grid-linjer (rule of thirds), pil som pekar på huvudobjektet, och exempel på bra vs dålig framing. Pedagogisk, ren stil.", "style": "educational_diagram" }, "m3l1": { "title": "GPS-accuracy", "prompt": "En karta över en stad med GPS-satelliter ovanför. Visa en smartphone som tar emot signaler från 4+ satelliter. Färgkodad accuracy-cirkel runt enheten: grön (noggrann), gul (medel), röd (låg). Teknisk men pedagogisk illustration.", "style": "technical_illustration" }, "m4l1": { "title": "Personlig säkerhet", "prompt": "En illustration som visar säker fotografering. Person med reflexväst och smartphone fotograferar en bro från säker plats. Trafikkegel, varselväst, och säkerhetsavstånd markerat. Pedagogisk, vänlig stil.", "style": "illustration" }, "m5l1": { "title": "Batch-fotografering", "prompt": "En karta med optimerad rutt mellan flera fotopunkter (A, B, C, D). Visa en person som effektivt fotograferar flera platser i rad. Bil- eller cykel-ikon som visar transport. Pedagogisk, ren stil med gröna och blå färger.", "style": "map_illustration" }, "m6l1": { "title": "Förstå utbetalningar", "prompt": "En illustration som visar utbetalningsflödet. Från godkänd fotografi → AI-granskning → godkännande → utbetalning till bankkonto. Flödesdiagram-stil med ikoner och pilar. Modern, ren design med gröna färger för pengar/framgång.", "style": "flowchart" } } def generate_image(lesson_id: str, api_key: str) -> dict: """Generera bild för en lektion med Gemini""" lesson = LESSON_IMAGES.get(lesson_id) if not lesson: return {"error": f"Unknown lesson: {lesson_id}"} print(f"🎨 Genererar bild för: {lesson['title']}") # Bygg prompt för Gemini full_prompt = f"""Generera en pedagogisk bild för en online-utbildning om crowdsourcing-fotografering. Titel: {lesson['title']} Beskrivning: {lesson['prompt']} Krav: - Bilden ska vara pedagogisk och lätt att förstå - Använd quiXzooms färger: blå (#0066FF), grön (#00C853), svart (#0A0A0A) - Ingen text i bilden (text läggs till separat) - Format: 16:9 bredbild - Stil: {lesson['style']} """ # Här skulle vi anropa Gemini API # För nu, skapa en placeholder return { "lesson_id": lesson_id, "title": lesson['title'], "prompt": full_prompt, "status": "queued", "timestamp": datetime.utcnow().isoformat() } def generate_all_images(): """Generera alla bilder för Academy""" if not GEMINI_API_KEY: print("⚠️ Ingen GEMINI_API_KEY hittad. Sätter upp placeholder-bilder.") print(" Sätt miljövariabel: export GEMINI_API_KEY='din-nyckel'") # Skapa JSON med alla prompts för senare generering output = { "generated_at": datetime.utcnow().isoformat(), "total_images": len(LESSON_IMAGES), "status": "pending_api_key", "images": LESSON_IMAGES } with open("academy-images-pending.json", "w") as f: json.dump(output, f, indent=2, ensure_ascii=False) print(f"\n📄 Sparade {len(LESSON_IMAGES)} bild-prompts till academy-images-pending.json") print(" Kör skriptet igen när API-nyckel är satt.") return # Generera alla bilder results = [] for lesson_id, lesson in LESSON_IMAGES.items(): result = generate_image(lesson_id, GEMINI_API_KEY) results.append(result) print(f" ✅ {lesson_id}: {result['status']}") # Spara resultat output = { "generated_at": datetime.utcnow().isoformat(), "total_images": len(results), "status": "completed", "results": results } with open("academy-images-generated.json", "w") as f: json.dump(output, f, indent=2, ensure_ascii=False) print(f"\n✅ Genererade {len(results)} bilder") print("📄 Resultat sparat i academy-images-generated.json") def upload_to_s3(image_path: str, s3_key: str): """Ladda upp bild till S3""" import subprocess cmd = [ "aws", "s3", "cp", image_path, f"s3://{S3_BUCKET}/{s3_key}", "--acl", "public-read", "--content-type", "image/png" ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: url = f"https://{S3_BUCKET}.s3.eu-north-1.amazonaws.com/{s3_key}" print(f" ✅ Uppladdad: {url}") return url else: print(f" ❌ Fel: {result.stderr}") return None if __name__ == "__main__": print("🎨 quiXzoom Academy — Bildgenerator") print("=" * 50) if len(sys.argv) > 1 and sys.argv[1] == "--generate": generate_all_images() else: print("\nAnvändning:") print(" python academy-image-generator.py --generate") print("\nKräver:") print(" - GEMINI_API_KEY miljövariabel") print(" - AWS-credentials för S3-uppladdning") print(f"\nFörbereder {len(LESSON_IMAGES)} bilder...") generate_all_images()