mgbam commited on
Commit
48777e5
Β·
verified Β·
1 Parent(s): cd569d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +10 -37
app.py CHANGED
@@ -9,7 +9,6 @@ from core.prompt_engineering import (
9
  create_visual_regeneration_prompt
10
  )
11
  import os
12
- # import json # Only if you need to st.json for debugging
13
 
14
  # --- Configuration & Initialization ---
15
  st.set_page_config(page_title="CineGen AI Pro", layout="wide", initial_sidebar_state="expanded")
@@ -36,27 +35,23 @@ if 'gemini_handler' not in st.session_state:
36
  # Initialize Visual Engine and set OpenAI API Key
37
  if 'visual_engine' not in st.session_state:
38
  st.session_state.visual_engine = VisualEngine(output_dir="temp_cinegen_media")
39
- # --- TRY TO SET OPENAI API KEY FOR VISUAL ENGINE ---
40
  openai_key_from_secrets = None
41
  try:
42
- # Check Streamlit Cloud secrets first
43
  if "OPENAI_API_KEY" in st.secrets:
44
  openai_key_from_secrets = st.secrets["OPENAI_API_KEY"]
45
- except AttributeError: # st.secrets might not exist in all local dev environments
46
  print("st.secrets not available (likely local dev without secrets.toml). Checking environment variables.")
47
  except Exception as e:
48
  print(f"Could not access st.secrets for OPENAI_API_KEY: {e}")
49
 
50
- if not openai_key_from_secrets and "OPENAI_API_KEY" in os.environ: # Fallback to env var
51
  openai_key_from_secrets = os.environ["OPENAI_API_KEY"]
52
 
53
  if openai_key_from_secrets:
54
  st.session_state.visual_engine.set_openai_api_key(openai_key_from_secrets)
55
- # st.sidebar.caption("OpenAI API Key loaded. DALL-E ready.") # Optional UI feedback
56
  else:
57
  st.session_state.visual_engine.set_openai_api_key(None)
58
  st.sidebar.caption("OpenAI API Key for DALL-E not found. Visuals will be placeholders.")
59
- # --- END OF OPENAI API KEY SETUP ---
60
 
61
  # Story and generated content state
62
  if 'story_scenes' not in st.session_state:
@@ -81,42 +76,31 @@ def initialize_new_story():
81
 
82
  def generate_visual_for_scene_wrapper(scene_index, scene_data, is_regeneration=False, version_count=1):
83
  scene_num_for_log = scene_data.get('scene_number', scene_index + 1)
84
-
85
  textual_image_prompt = ""
86
  if is_regeneration and scene_index < len(st.session_state.scene_image_prompts) and st.session_state.scene_image_prompts[scene_index]:
87
  textual_image_prompt = st.session_state.scene_image_prompts[scene_index]
88
- # st.caption(f"Using refined prompt for Scene {scene_num_for_log}.") # Can be noisy
89
  else:
90
  textual_image_prompt = create_image_prompt_from_scene_data(
91
  scene_data,
92
  st.session_state.character_definitions,
93
  st.session_state.style_reference_description
94
  )
95
- # st.caption(f"Generated initial prompt for Scene {scene_num_for_log}.") # Can be noisy
96
-
97
  if not textual_image_prompt:
98
- # st.error(f"Failed to create/retrieve textual image prompt for Scene {scene_num_for_log}.") # Handled by status
99
  return False
100
-
101
  if scene_index >= len(st.session_state.scene_image_prompts):
102
  while len(st.session_state.scene_image_prompts) <= scene_index:
103
  st.session_state.scene_image_prompts.append("")
104
  st.session_state.scene_image_prompts[scene_index] = textual_image_prompt
105
-
106
  image_filename = f"scene_{scene_num_for_log}_visual_v{version_count}.png"
107
-
108
  generated_image_path = st.session_state.visual_engine.generate_image_visual(
109
  textual_image_prompt, image_filename
110
  )
111
-
112
  while len(st.session_state.generated_images_paths) <= scene_index:
113
  st.session_state.generated_images_paths.append(None)
114
-
115
  if generated_image_path and os.path.exists(generated_image_path):
116
  st.session_state.generated_images_paths[scene_index] = generated_image_path
117
  return True
118
  else:
119
- # st.warning(f"Visual for Scene {scene_num_for_log} (v{version_count}) failed or path invalid.") # Handled by status
120
  st.session_state.generated_images_paths[scene_index] = None
121
  return False
122
 
@@ -127,7 +111,7 @@ with st.sidebar:
127
  user_idea = st.text_area("Enter your core story idea:", "A lone astronaut discovers a glowing alien artifact on Mars, a sense of wonder and slight dread.", height=100, key="user_idea_input")
128
  genre = st.selectbox("Genre:", ["Sci-Fi", "Fantasy", "Noir", "Thriller", "Drama", "Horror", "Cyberpunk"], index=6, key="genre_select")
129
  mood = st.selectbox("Mood:", ["Suspenseful", "Mysterious", "Gritty", "Epic", "Dark", "Hopeful", "Wonder"], index=6, key="mood_select")
130
- num_scenes_val = st.slider("Number of Scenes:", 1, 5, 3, key="num_scenes_slider") # Max 5 for sensible generation times
131
 
132
  if st.button("✨ Generate Full Story Concept", type="primary", key="generate_full_story_btn", use_container_width=True):
133
  initialize_new_story()
@@ -140,18 +124,15 @@ with st.sidebar:
140
  try:
141
  st.session_state.story_scenes = st.session_state.gemini_handler.generate_story_breakdown(story_prompt_text)
142
  status_main.update(label="Script breakdown complete! βœ…", state="running", expanded=True)
143
-
144
  num_actual_scenes = len(st.session_state.story_scenes)
145
  st.session_state.scene_image_prompts = [""] * num_actual_scenes
146
  st.session_state.generated_images_paths = [None] * num_actual_scenes
147
-
148
  except Exception as e:
149
  status_main.update(label=f"Failed to generate story breakdown: {e}", state="error", expanded=True)
150
- st.session_state.story_scenes = [] # Ensure it's empty on failure
151
  st.stop()
152
-
153
  if st.session_state.story_scenes:
154
- st.write("Phase 2: Generating initial visual concepts... πŸ–ΌοΈ (This may take a few minutes per scene with DALL-E)")
155
  success_count = 0
156
  for i_loop, scene_data_loop_var in enumerate(st.session_state.story_scenes):
157
  scene_num_log = scene_data_loop_var.get('scene_number', i_loop + 1)
@@ -161,7 +142,6 @@ with st.sidebar:
161
  st.write(f"Visual for Scene {scene_num_log} done.")
162
  else:
163
  st.write(f"Visual for Scene {scene_num_log} failed.")
164
-
165
  if success_count == len(st.session_state.story_scenes):
166
  status_main.update(label="All concepts generated successfully! πŸŽ‰", state="complete", expanded=False)
167
  elif success_count > 0:
@@ -176,7 +156,6 @@ with st.sidebar:
176
  char_desc_input = st.text_area("Character Description (e.g., 'female, short red hair, green eyes, wearing a blue jumpsuit')", key="char_desc_adv_input", height=100)
177
  if st.button("Add/Update Character", key="add_char_adv_btn"):
178
  if char_name_input and char_desc_input:
179
- # Store character names in lowercase for easier matching, but keep original for display if needed
180
  st.session_state.character_definitions[char_name_input.strip().lower()] = char_desc_input.strip()
181
  st.success(f"Character '{char_name_input.strip()}' defined.")
182
  else:
@@ -184,7 +163,7 @@ with st.sidebar:
184
  if st.session_state.character_definitions:
185
  st.caption("Defined Characters:")
186
  for char_key, desc_val in st.session_state.character_definitions.items():
187
- st.markdown(f"**{char_key.title()}:** _{desc_val}_") # Display with title case
188
 
189
  with st.expander("Style Transfer", expanded=False):
190
  style_ref_text = st.text_area("Describe Visual Style (e.g., 'impressionistic oil painting, vibrant colors')", key="style_text_adv_input", height=100)
@@ -224,7 +203,8 @@ else:
224
  with col2:
225
  current_image_path = st.session_state.generated_images_paths[i] if i < len(st.session_state.generated_images_paths) else None
226
  if current_image_path and os.path.exists(current_image_path):
227
- st.image(current_image_path, caption=f"Visual Concept for Scene {scene_num_display}", use_column_width=True)
 
228
  else:
229
  if st.session_state.story_scenes:
230
  st.caption("Visual for this scene is pending or failed to generate.")
@@ -242,14 +222,12 @@ else:
242
  updated_scene_data = st.session_state.gemini_handler.regenerate_scene_script_details(regen_prompt)
243
  st.session_state.story_scenes[i] = updated_scene_data
244
  status_script_regen.update(label="Script updated! Regenerating visual...", state="running")
245
-
246
  version = 1
247
  if current_image_path:
248
  try:
249
  base, _ = os.path.splitext(os.path.basename(current_image_path))
250
  if '_v' in base: version = int(base.split('_v')[-1]) + 1
251
  except : pass
252
-
253
  if generate_visual_for_scene_wrapper(i, updated_scene_data, is_regeneration=True, version_count=version):
254
  status_script_regen.update(label="Scene script & visual updated! πŸŽ‰", state="complete", expanded=False)
255
  else:
@@ -264,7 +242,6 @@ else:
264
  prompt_for_edit_visuals = st.session_state.scene_image_prompts[i] if i < len(st.session_state.scene_image_prompts) else "No prompt text available."
265
  st.caption("Current Image Prompt Text:")
266
  st.code(prompt_for_edit_visuals, language='text')
267
-
268
  feedback_visual = st.text_area("Describe visual changes to apply to the prompt:",
269
  key=f"visual_feedback_{unique_key_part}_{i}", height=100)
270
  if st.button(f"πŸ”„ Regenerate Scene {scene_num_display} Visuals", key=f"regen_visual_btn_{unique_key_part}_{i}"):
@@ -277,15 +254,12 @@ else:
277
  refined_textual_image_prompt = st.session_state.gemini_handler.regenerate_image_prompt_from_feedback(prompt_refinement_request)
278
  st.session_state.scene_image_prompts[i] = refined_textual_image_prompt
279
  status_visual_regen.update(label="Image prompt refined! Regenerating visual...", state="running")
280
-
281
  version = 1
282
  if current_image_path:
283
  try:
284
  base, _ = os.path.splitext(os.path.basename(current_image_path))
285
  if '_v' in base: version = int(base.split('_v')[-1]) + 1
286
  except : pass
287
-
288
- # Pass current scene_data_display as scene content hasn't changed, only the prompt.
289
  if generate_visual_for_scene_wrapper(i, scene_data_display, is_regeneration=True, version_count=version):
290
  status_visual_regen.update(label="Visual for Scene updated! πŸŽ‰", state="complete", expanded=False)
291
  else:
@@ -309,7 +283,6 @@ else:
309
  'scene_num': scene_info.get('scene_number', idx + 1),
310
  'key_action': scene_info.get('key_action', '')
311
  })
312
-
313
  if image_data_for_video:
314
  st.session_state.video_path = st.session_state.visual_engine.create_video_from_images(
315
  image_data_for_video,
@@ -332,12 +305,12 @@ else:
332
  try:
333
  with open(st.session_state.video_path, 'rb') as video_file_obj:
334
  video_bytes_content = video_file_obj.read()
335
- st.video(video_bytes_content, format="video/mp4") # Specify format for better compatibility
336
  with open(st.session_state.video_path, "rb") as fp_download_video:
337
  st.download_button(
338
  label="Download Enhanced Animatic", data=fp_download_video,
339
  file_name=os.path.basename(st.session_state.video_path), mime="video/mp4",
340
- use_container_width=True, key="download_video_btn" # Added key
341
  )
342
  except Exception as e:
343
  st.error(f"Error displaying or preparing video for download: {e}")
 
9
  create_visual_regeneration_prompt
10
  )
11
  import os
 
12
 
13
  # --- Configuration & Initialization ---
14
  st.set_page_config(page_title="CineGen AI Pro", layout="wide", initial_sidebar_state="expanded")
 
35
  # Initialize Visual Engine and set OpenAI API Key
36
  if 'visual_engine' not in st.session_state:
37
  st.session_state.visual_engine = VisualEngine(output_dir="temp_cinegen_media")
 
38
  openai_key_from_secrets = None
39
  try:
 
40
  if "OPENAI_API_KEY" in st.secrets:
41
  openai_key_from_secrets = st.secrets["OPENAI_API_KEY"]
42
+ except AttributeError:
43
  print("st.secrets not available (likely local dev without secrets.toml). Checking environment variables.")
44
  except Exception as e:
45
  print(f"Could not access st.secrets for OPENAI_API_KEY: {e}")
46
 
47
+ if not openai_key_from_secrets and "OPENAI_API_KEY" in os.environ:
48
  openai_key_from_secrets = os.environ["OPENAI_API_KEY"]
49
 
50
  if openai_key_from_secrets:
51
  st.session_state.visual_engine.set_openai_api_key(openai_key_from_secrets)
 
52
  else:
53
  st.session_state.visual_engine.set_openai_api_key(None)
54
  st.sidebar.caption("OpenAI API Key for DALL-E not found. Visuals will be placeholders.")
 
55
 
56
  # Story and generated content state
57
  if 'story_scenes' not in st.session_state:
 
76
 
77
  def generate_visual_for_scene_wrapper(scene_index, scene_data, is_regeneration=False, version_count=1):
78
  scene_num_for_log = scene_data.get('scene_number', scene_index + 1)
 
79
  textual_image_prompt = ""
80
  if is_regeneration and scene_index < len(st.session_state.scene_image_prompts) and st.session_state.scene_image_prompts[scene_index]:
81
  textual_image_prompt = st.session_state.scene_image_prompts[scene_index]
 
82
  else:
83
  textual_image_prompt = create_image_prompt_from_scene_data(
84
  scene_data,
85
  st.session_state.character_definitions,
86
  st.session_state.style_reference_description
87
  )
 
 
88
  if not textual_image_prompt:
 
89
  return False
 
90
  if scene_index >= len(st.session_state.scene_image_prompts):
91
  while len(st.session_state.scene_image_prompts) <= scene_index:
92
  st.session_state.scene_image_prompts.append("")
93
  st.session_state.scene_image_prompts[scene_index] = textual_image_prompt
 
94
  image_filename = f"scene_{scene_num_for_log}_visual_v{version_count}.png"
 
95
  generated_image_path = st.session_state.visual_engine.generate_image_visual(
96
  textual_image_prompt, image_filename
97
  )
 
98
  while len(st.session_state.generated_images_paths) <= scene_index:
99
  st.session_state.generated_images_paths.append(None)
 
100
  if generated_image_path and os.path.exists(generated_image_path):
101
  st.session_state.generated_images_paths[scene_index] = generated_image_path
102
  return True
103
  else:
 
104
  st.session_state.generated_images_paths[scene_index] = None
105
  return False
106
 
 
111
  user_idea = st.text_area("Enter your core story idea:", "A lone astronaut discovers a glowing alien artifact on Mars, a sense of wonder and slight dread.", height=100, key="user_idea_input")
112
  genre = st.selectbox("Genre:", ["Sci-Fi", "Fantasy", "Noir", "Thriller", "Drama", "Horror", "Cyberpunk"], index=6, key="genre_select")
113
  mood = st.selectbox("Mood:", ["Suspenseful", "Mysterious", "Gritty", "Epic", "Dark", "Hopeful", "Wonder"], index=6, key="mood_select")
114
+ num_scenes_val = st.slider("Number of Scenes:", 1, 5, 1, key="num_scenes_slider") # Default to 1 for faster testing
115
 
116
  if st.button("✨ Generate Full Story Concept", type="primary", key="generate_full_story_btn", use_container_width=True):
117
  initialize_new_story()
 
124
  try:
125
  st.session_state.story_scenes = st.session_state.gemini_handler.generate_story_breakdown(story_prompt_text)
126
  status_main.update(label="Script breakdown complete! βœ…", state="running", expanded=True)
 
127
  num_actual_scenes = len(st.session_state.story_scenes)
128
  st.session_state.scene_image_prompts = [""] * num_actual_scenes
129
  st.session_state.generated_images_paths = [None] * num_actual_scenes
 
130
  except Exception as e:
131
  status_main.update(label=f"Failed to generate story breakdown: {e}", state="error", expanded=True)
132
+ st.session_state.story_scenes = []
133
  st.stop()
 
134
  if st.session_state.story_scenes:
135
+ st.write("Phase 2: Generating initial visual concepts... πŸ–ΌοΈ (This may take time with DALL-E)")
136
  success_count = 0
137
  for i_loop, scene_data_loop_var in enumerate(st.session_state.story_scenes):
138
  scene_num_log = scene_data_loop_var.get('scene_number', i_loop + 1)
 
142
  st.write(f"Visual for Scene {scene_num_log} done.")
143
  else:
144
  st.write(f"Visual for Scene {scene_num_log} failed.")
 
145
  if success_count == len(st.session_state.story_scenes):
146
  status_main.update(label="All concepts generated successfully! πŸŽ‰", state="complete", expanded=False)
147
  elif success_count > 0:
 
156
  char_desc_input = st.text_area("Character Description (e.g., 'female, short red hair, green eyes, wearing a blue jumpsuit')", key="char_desc_adv_input", height=100)
157
  if st.button("Add/Update Character", key="add_char_adv_btn"):
158
  if char_name_input and char_desc_input:
 
159
  st.session_state.character_definitions[char_name_input.strip().lower()] = char_desc_input.strip()
160
  st.success(f"Character '{char_name_input.strip()}' defined.")
161
  else:
 
163
  if st.session_state.character_definitions:
164
  st.caption("Defined Characters:")
165
  for char_key, desc_val in st.session_state.character_definitions.items():
166
+ st.markdown(f"**{char_key.title()}:** _{desc_val}_")
167
 
168
  with st.expander("Style Transfer", expanded=False):
169
  style_ref_text = st.text_area("Describe Visual Style (e.g., 'impressionistic oil painting, vibrant colors')", key="style_text_adv_input", height=100)
 
203
  with col2:
204
  current_image_path = st.session_state.generated_images_paths[i] if i < len(st.session_state.generated_images_paths) else None
205
  if current_image_path and os.path.exists(current_image_path):
206
+ # MODIFICATION HERE: Removed use_column_width=True
207
+ st.image(current_image_path, caption=f"Visual Concept for Scene {scene_num_display}")
208
  else:
209
  if st.session_state.story_scenes:
210
  st.caption("Visual for this scene is pending or failed to generate.")
 
222
  updated_scene_data = st.session_state.gemini_handler.regenerate_scene_script_details(regen_prompt)
223
  st.session_state.story_scenes[i] = updated_scene_data
224
  status_script_regen.update(label="Script updated! Regenerating visual...", state="running")
 
225
  version = 1
226
  if current_image_path:
227
  try:
228
  base, _ = os.path.splitext(os.path.basename(current_image_path))
229
  if '_v' in base: version = int(base.split('_v')[-1]) + 1
230
  except : pass
 
231
  if generate_visual_for_scene_wrapper(i, updated_scene_data, is_regeneration=True, version_count=version):
232
  status_script_regen.update(label="Scene script & visual updated! πŸŽ‰", state="complete", expanded=False)
233
  else:
 
242
  prompt_for_edit_visuals = st.session_state.scene_image_prompts[i] if i < len(st.session_state.scene_image_prompts) else "No prompt text available."
243
  st.caption("Current Image Prompt Text:")
244
  st.code(prompt_for_edit_visuals, language='text')
 
245
  feedback_visual = st.text_area("Describe visual changes to apply to the prompt:",
246
  key=f"visual_feedback_{unique_key_part}_{i}", height=100)
247
  if st.button(f"πŸ”„ Regenerate Scene {scene_num_display} Visuals", key=f"regen_visual_btn_{unique_key_part}_{i}"):
 
254
  refined_textual_image_prompt = st.session_state.gemini_handler.regenerate_image_prompt_from_feedback(prompt_refinement_request)
255
  st.session_state.scene_image_prompts[i] = refined_textual_image_prompt
256
  status_visual_regen.update(label="Image prompt refined! Regenerating visual...", state="running")
 
257
  version = 1
258
  if current_image_path:
259
  try:
260
  base, _ = os.path.splitext(os.path.basename(current_image_path))
261
  if '_v' in base: version = int(base.split('_v')[-1]) + 1
262
  except : pass
 
 
263
  if generate_visual_for_scene_wrapper(i, scene_data_display, is_regeneration=True, version_count=version):
264
  status_visual_regen.update(label="Visual for Scene updated! πŸŽ‰", state="complete", expanded=False)
265
  else:
 
283
  'scene_num': scene_info.get('scene_number', idx + 1),
284
  'key_action': scene_info.get('key_action', '')
285
  })
 
286
  if image_data_for_video:
287
  st.session_state.video_path = st.session_state.visual_engine.create_video_from_images(
288
  image_data_for_video,
 
305
  try:
306
  with open(st.session_state.video_path, 'rb') as video_file_obj:
307
  video_bytes_content = video_file_obj.read()
308
+ st.video(video_bytes_content, format="video/mp4")
309
  with open(st.session_state.video_path, "rb") as fp_download_video:
310
  st.download_button(
311
  label="Download Enhanced Animatic", data=fp_download_video,
312
  file_name=os.path.basename(st.session_state.video_path), mime="video/mp4",
313
+ use_container_width=True, key="download_video_btn"
314
  )
315
  except Exception as e:
316
  st.error(f"Error displaying or preparing video for download: {e}")