# core/prompt_engineering.py import json # create_story_breakdown_prompt - (ensure key_action and emotional_beat are descriptive) - REMAINS SAME def create_story_breakdown_prompt(user_idea, genre="sci-fi", mood="suspenseful", num_scenes=3): return f""" You are an expert screenwriter and visual storyteller. Based on: "{user_idea}", genre: "{genre}", mood: "{mood}". Generate a {num_scenes}-scene story breakdown. For each scene: 1. scene_number (int) 2. emotional_beat (str): Short title for the scene's core feeling. 3. setting_description (str): Vivid description (30-50 words). 4. characters_involved (list of str): Names of characters. 5. key_action (str): Main event for video overlay (15-20 words). 6. dialogue_snippet (str): Brief impactful dialogue. 7. visual_style_suggestion (str): Keywords for visual style. 8. camera_angle_suggestion (str): Specific camera shot. Output ONLY the JSON list of scenes. Example: {{ "scene_number": 1, "emotional_beat": "Tense Standoff", "setting_description": "Rain-slicked, neon-drenched alleyway...", "characters_involved": ["Detective Kaito", "Informant"], "key_action": "Kaito cautiously approaches a nervous informant.", "dialogue_snippet": "Informant: 'They know...'", "visual_style_suggestion": "Neo-noir, cyberpunk...", "camera_angle_suggestion": "Medium shot..."}} [{{"scene1_details..."}}, {{"scene2_details..."}}] """ # create_image_prompt_from_scene_data - (injects char defs & style) - REMAINS SAME def create_image_prompt_from_scene_data(scene_data, character_definitions=None, global_style_reference=""): emotional_beat_title = scene_data.get('emotional_beat', 'A cinematic scene') setting_desc = scene_data.get('setting_description', 'A visually interesting setting.') key_action_desc = scene_data.get('key_action', 'A significant moment unfolds.') characters_involved_in_scene = scene_data.get('characters_involved', []) character_prompt_segments = [] if characters_involved_in_scene: for char_name_from_scene in characters_involved_in_scene: char_name_clean = char_name_from_scene.strip(); char_lookup_key = char_name_clean.lower() if character_definitions and char_lookup_key in character_definitions: character_prompt_segments.append(f"{char_name_clean} (described as: {character_definitions[char_lookup_key]})") else: character_prompt_segments.append(char_name_clean) characters_narrative = "" if character_prompt_segments: if len(character_prompt_segments) == 1: characters_narrative = f"The main character is {character_prompt_segments[0]}." else: characters_narrative = f"The scene features {', '.join(character_prompt_segments[:-1])}, and {character_prompt_segments[-1]}." narrative_prompt = f"Scene Number: {scene_data.get('scene_number', 'N/A')}. Setting: {setting_desc}. {characters_narrative} Key Action: {key_action_desc}. Emotional Tone: {scene_data.get('emotional_beat', '')}." style_instructions = f"Visual Style: {scene_data.get('visual_style_suggestion', 'cinematic, photorealistic')}." if global_style_reference: style_instructions += f" Specific style reference: {global_style_reference}." camera_instructions = f"Camera Perspective: {scene_data.get('camera_angle_suggestion', 'eye-level medium shot')}." full_prompt = (f"Generate an ultra-detailed, photorealistic, and highly cinematic digital painting or concept art image. " f"The image should depict: '{emotional_beat_title}'. Narrative Context: {narrative_prompt} " f"Artistic & Technical Instructions: {style_instructions} {camera_instructions} " f"Emphasize: Cinematic composition, dramatic lighting, rich textures, depth of field, strong atmospheric effects. " f"The image must feel like a high-quality film still. Pay close attention to character details.") return " ".join(full_prompt.split()) # --- NEW: Prompt for Narration Script --- def create_narration_script_prompt(story_scenes_data, overall_mood, overall_genre): """ Generates a prompt for Gemini to write a concise narration script for an animatic, covering all provided scenes. """ scenes_summary = [] for i, scene in enumerate(story_scenes_data): scenes_summary.append( f"Scene {scene.get('scene_number', i+1)} ({scene.get('emotional_beat','')}):\n" f"- Setting: {scene.get('setting_description','')}\n" f"- Key Action: {scene.get('key_action','')}\n" f"- Characters: {', '.join(scene.get('characters_involved',[]))}\n" f"- Implied Dialogue/Thought: {scene.get('dialogue_snippet','(none)')}" ) full_summary_text = "\n\n".join(scenes_summary) prompt = f""" You are a professional scriptwriter for documentary-style voiceovers and cinematic trailers. Given the following scene summaries for an animatic storyboard: --- SCENE SUMMARIES --- {full_summary_text} --- END SCENE SUMMARIES --- Overall Story Genre: {overall_genre} Overall Story Mood: {overall_mood} Write a concise, engaging, and continuous narration script that flows smoothly across these scenes. The narration should enhance the visual storytelling, not just describe what's visible. It should set the tone, build suspense or emotion, and connect the scenes thematically. The tone of the narration should match the overall mood and genre. Keep the narration for each scene relatively brief (1-2 short sentences per scene on average). The total narration should be suitable for a short animatic (e.g., if 3 scenes at 4 seconds each, total ~12 seconds of video, so narration should be ~60-90 words max). Do not include scene numbers or explicit directives like "(Voiceover)" in the output. Just provide the pure narration text. Focus on evocative language. Example (if scenes were about a space discovery): "The red dust of Mars whispered secrets of a forgotten age. Deep within the chasm, an impossible structure pulsed with an alien light, beckoning humanity towards a destiny unknown, and perhaps, a truth too vast to comprehend." Output ONLY the narration script text. """ return " ".join(prompt.split()) # create_scene_regeneration_prompt - REMAINS SAME def create_scene_regeneration_prompt(original_scene_data, user_feedback, full_story_context=None): context_str = f"Original scene (Scene Number {original_scene_data.get('scene_number')}):\n{json.dumps(original_scene_data, indent=2)}\n\n" if full_story_context: context_str += f"Full story context:\n{json.dumps(full_story_context, indent=2)}\n\n" return (f"Expert script doctor. Original scene:\n{context_str}User feedback: \"{user_feedback}\"\n" f"Regenerate ONLY the JSON for this single scene, incorporating feedback. Maintain structure. 'key_action' max 15-20 words.") # create_visual_regeneration_prompt - REMAINS SAME def create_visual_regeneration_prompt(original_image_prompt_text, user_feedback_on_visuals, scene_data, character_definitions=None, global_style_reference=""): scene_context_summary = (f"Scene: {scene_data.get('emotional_beat', '')}. Setting: {scene_data.get('setting_description', '')}. " f"Action: {scene_data.get('key_action', '')}. Characters: {', '.join(scene_data.get('characters_involved',[]))}.") char_details_str = "Relevant characters: " + (", ".join([f"{name} ({desc})" for name, desc in character_definitions.items() if name.lower() in [cn.lower() for cn in scene_data.get('characters_involved',[])]])) if character_definitions else "None specified." return (f"AI assistant for refining DALL-E 3 prompts. Original Scene Context: {scene_context_summary} {char_details_str} " f"Global Style: \"{global_style_reference}\". Original DALL-E 3 prompt was: \"{original_image_prompt_text}\". " f"User feedback on visual: \"{user_feedback_on_visuals}\". Generate a new, revised DALL-E 3 prompt. " f"It must be ultra-detailed, photorealistic, cinematic, film/game quality. Translate feedback into concrete visual descriptions. " f"Respect character descriptions. Output ONLY the new prompt string.")