shaheerawan3 commited on
Commit
1492cfb
·
verified ·
1 Parent(s): cdabdd7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +284 -103
app.py CHANGED
@@ -24,11 +24,126 @@ from io import BytesIO
24
 
25
  class ImageScraper:
26
  def __init__(self):
27
- self.PIXABAY_API_KEY = "48069976-37e20099248207cee12385560" # Your API key
28
  self.headers = {
29
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
30
  }
31
  self.temp_dir = Path(tempfile.mkdtemp())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  def get_pixabay_images(self, query: str) -> List[str]:
34
  """Get images from Pixabay API with enhanced error handling"""
@@ -85,29 +200,57 @@ class ImageScraper:
85
  "https://images.pexels.com/photos/5473950/pexels-photo-5473950.jpeg"
86
  ]
87
 
88
- def get_images(self, query: str, num_images: int = 15) -> List[str]:
89
- """Main method to get images with fallback options"""
90
- # First try Pixabay
91
- images = self.get_pixabay_images(query)
92
-
93
- # If no Pixabay images, try with technology-related terms
94
- if not images:
95
- print("No images found for original query, trying tech terms...")
96
- tech_terms = ["digital security", "technology", "cyber security", "data protection"]
97
- for term in tech_terms:
98
- images.extend(self.get_pixabay_images(term))
99
- if images:
100
- break
101
-
102
- # If still no images, use stock images
103
- if not images:
104
- print("Using fallback stock images...")
105
- images = self.get_stock_images()
106
-
107
- # Remove duplicates and limit to num_images
108
- unique_images = list(dict.fromkeys(images))[:num_images]
109
- print(f"Returning {len(unique_images)} images")
110
- return unique_images
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  def verify_image_url(self, url: str) -> bool:
113
  """Verify if an image URL is accessible"""
@@ -741,102 +884,140 @@ class VideoGeneratorUI:
741
  max-width: 1200px;
742
  margin: 0 auto;
743
  }
744
- .image-grid {
745
- display: grid;
746
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
747
- gap: 1rem;
 
748
  }
749
- .stButton>button {
750
- width: 100%;
 
 
751
  }
752
  </style>
753
  """, unsafe_allow_html=True)
754
 
755
- # Header
756
  st.title("VaultGenix Video Generator")
757
  st.markdown("Create professional videos for your digital legacy management platform")
758
 
759
- # Input Section
760
  with st.container():
761
  prompt = st.text_area("Enter your video script", height=200)
762
 
763
  if prompt:
764
- with st.spinner("Fetching images..."):
765
  try:
766
- st.subheader("Select Images for Your Video")
767
- images = self.generator.image_scraper.get_images(prompt)
768
-
769
- if not images:
770
- st.warning("No images found. Loading default technology images...")
771
- images = self.generator.image_scraper.get_stock_images()
772
-
773
- # Image Selection Grid
774
- selected_images = []
775
- cols = st.columns(3)
776
-
777
- for idx, img_url in enumerate(images):
778
- with cols[idx % 3]:
779
- try:
780
- # Verify image URL before displaying
781
- if self.generator.image_scraper.verify_image_url(img_url):
782
- st.image(img_url, use_container_width=True)
783
- if st.checkbox(f"Select Image {idx + 1}", key=f"img_{idx}"):
784
- selected_images.append(img_url)
785
- except Exception as e:
786
- print(f"Error displaying image {idx}: {str(e)}")
787
- continue
788
 
789
- # Only show video settings if images are available
790
- if selected_images:
791
- st.subheader("Video Settings")
792
- col1, col2 = st.columns(2)
793
- with col1:
794
- style = st.selectbox(
795
- "Choose style",
796
- options=["Professional", "Creative", "Educational"],
797
- index=0
798
- )
799
- with col2:
800
- duration = st.slider(
801
- "Video duration (seconds)",
802
- min_value=30,
803
- max_value=180,
804
- value=60,
805
- step=30
806
- )
807
-
808
- if st.button("Generate Video", type="primary"):
809
- with st.spinner("Generating your video..."):
810
- try:
811
- output_path = f"vaultgenix_video_{int(time.time())}.mp4"
812
- video_path = self.generator.create_video(
813
- prompt,
814
- style,
815
- duration,
816
- output_path,
817
- selected_images
818
- )
819
-
820
- if os.path.exists(video_path):
821
- st.success("✨ Video generated successfully!")
822
- st.video(video_path)
823
-
824
- with open(video_path, 'rb') as video_file:
825
- st.download_button(
826
- "⬇️ Download Video",
827
- video_file.read(),
828
- file_name=output_path,
829
- mime="video/mp4"
830
- )
831
- except Exception as e:
832
- st.error(f"Failed to generate video: {str(e)}")
833
- print(f"Video generation error: {str(e)}")
834
  else:
835
- st.error("No valid images found. Please try a different search term.")
836
-
837
  except Exception as e:
838
  st.error(f"An error occurred: {str(e)}")
839
- print(f"Setup error: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
 
841
  if __name__ == "__main__":
842
  ui = VideoGeneratorUI()
 
24
 
25
  class ImageScraper:
26
  def __init__(self):
27
+ self.PIXABAY_API_KEY = "48069976-37e20099248207cee12385560"
28
  self.headers = {
29
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
30
  }
31
  self.temp_dir = Path(tempfile.mkdtemp())
32
+
33
+ # Initialize keyword extractor model
34
+ try:
35
+ self.keyword_model = pipeline(
36
+ "text-classification",
37
+ model="facebook/bart-large-mnli",
38
+ device=0 if torch.cuda.is_available() else -1
39
+ )
40
+ except Exception as e:
41
+ print(f"Failed to load keyword model: {e}")
42
+ self.keyword_model = None
43
+
44
+ def extract_keywords(self, text: str) -> List[Dict[str, str]]:
45
+ """Extract relevant keywords and categories from text using AI"""
46
+ keywords = []
47
+
48
+ try:
49
+ # Define candidate labels for classification
50
+ candidate_labels = [
51
+ "technology", "science", "education", "business",
52
+ "health", "nature", "people", "urban", "abstract",
53
+ "sports", "food", "travel", "architecture", "art",
54
+ "music", "fashion", "medical", "industrial", "space",
55
+ "environmental", "historical", "cultural", "professional"
56
+ ]
57
+
58
+ # Use model to classify text against each label
59
+ if self.keyword_model:
60
+ results = self.keyword_model(text, candidate_labels, multi_label=True)
61
+
62
+ # Filter results with high confidence
63
+ for score, label in zip(results['scores'], results['labels']):
64
+ if score > 0.3: # Confidence threshold
65
+ keywords.append({
66
+ 'keyword': label,
67
+ 'confidence': score,
68
+ 'category': self.categorize_keyword(label)
69
+ })
70
+
71
+ # Extract additional keywords using NLP
72
+ additional_keywords = self.extract_noun_phrases(text)
73
+ for keyword in additional_keywords:
74
+ keywords.append({
75
+ 'keyword': keyword,
76
+ 'confidence': 0.5,
77
+ 'category': 'content_specific'
78
+ })
79
+
80
+ # Sort by confidence
81
+ keywords = sorted(keywords, key=lambda x: x['confidence'], reverse=True)
82
+
83
+ return keywords
84
+
85
+ except Exception as e:
86
+ print(f"Keyword extraction error: {e}")
87
+ return self.get_fallback_keywords()
88
+
89
+ def extract_noun_phrases(self, text: str) -> List[str]:
90
+ """Extract important noun phrases from text"""
91
+ words = text.lower().split()
92
+ phrases = []
93
+
94
+ # Common adjectives that might indicate important concepts
95
+ adjectives = {'digital', 'smart', 'modern', 'advanced', 'innovative',
96
+ 'technical', 'professional', 'creative', 'strategic'}
97
+
98
+ for i in range(len(words)-1):
99
+ if words[i] in adjectives:
100
+ phrases.append(f"{words[i]} {words[i+1]}")
101
+
102
+ return list(set(phrases))
103
+
104
+ def categorize_keyword(self, keyword: str) -> str:
105
+ """Categorize keyword into general themes"""
106
+ categories = {
107
+ 'technical': {'technology', 'digital', 'software', 'computer', 'cyber'},
108
+ 'scientific': {'science', 'research', 'laboratory', 'experiment'},
109
+ 'business': {'business', 'professional', 'corporate', 'office'},
110
+ 'educational': {'education', 'learning', 'teaching', 'academic'},
111
+ 'creative': {'art', 'design', 'creative', 'innovation'},
112
+ }
113
+
114
+ for category, terms in categories.items():
115
+ if any(term in keyword.lower() for term in terms):
116
+ return category
117
+ return 'general'
118
+
119
+ def get_images_for_keyword(self, keyword: str) -> List[Dict[str, str]]:
120
+ """Get images for a specific keyword with metadata"""
121
+ try:
122
+ base_url = "https://pixabay.com/api/"
123
+ params = {
124
+ 'key': self.PIXABAY_API_KEY,
125
+ 'q': keyword,
126
+ 'image_type': 'photo',
127
+ 'per_page': 5,
128
+ 'safesearch': True,
129
+ 'lang': 'en'
130
+ }
131
+
132
+ response = requests.get(base_url, params=params, headers=self.headers)
133
+
134
+ if response.status_code == 200:
135
+ data = response.json()
136
+ if 'hits' in data and data['hits']:
137
+ return [{
138
+ 'url': img['largeImageURL'],
139
+ 'keyword': keyword,
140
+ 'relevance': 'Primary match' if keyword in img['tags'] else 'Related',
141
+ 'tags': img['tags']
142
+ } for img in data['hits']]
143
+ return []
144
+ except Exception as e:
145
+ print(f"Error fetching images for keyword {keyword}: {e}")
146
+ return []
147
 
148
  def get_pixabay_images(self, query: str) -> List[str]:
149
  """Get images from Pixabay API with enhanced error handling"""
 
200
  "https://images.pexels.com/photos/5473950/pexels-photo-5473950.jpeg"
201
  ]
202
 
203
+ def get_images(self, prompt: str, num_images: int = 15) -> Dict[str, List[Dict[str, str]]]:
204
+ """Get images with AI-powered keyword extraction and categorization"""
205
+ try:
206
+ # Extract keywords from prompt
207
+ keywords = self.extract_keywords(prompt)
208
+
209
+ # Dictionary to store categorized images
210
+ categorized_images = {
211
+ 'primary': [], # Most relevant images
212
+ 'secondary': [], # Related images
213
+ 'general': [] # Generic/fallback images
214
+ }
215
+
216
+ # Get images for each keyword
217
+ for kw_data in keywords:
218
+ keyword = kw_data['keyword']
219
+ images = self.get_images_for_keyword(keyword)
220
+
221
+ # Categorize images based on confidence
222
+ for img in images:
223
+ if kw_data['confidence'] > 0.7:
224
+ categorized_images['primary'].extend(images)
225
+ elif kw_data['confidence'] > 0.4:
226
+ categorized_images['secondary'].extend(images)
227
+ else:
228
+ categorized_images['general'].extend(images)
229
+
230
+ # If no images found, use fallback
231
+ if not any(categorized_images.values()):
232
+ categorized_images['general'] = [{
233
+ 'url': url,
234
+ 'keyword': 'generic',
235
+ 'relevance': 'Fallback',
236
+ 'tags': ''
237
+ } for url in self.get_stock_images()]
238
+
239
+ return categorized_images
240
+
241
+ except Exception as e:
242
+ print(f"Error in get_images: {e}")
243
+ return {'general': [{'url': url, 'keyword': 'fallback', 'relevance': 'Fallback', 'tags': ''}
244
+ for url in self.get_stock_images()]}
245
+
246
+ def get_fallback_keywords(self) -> List[Dict[str, str]]:
247
+ """Return fallback keywords if AI extraction fails"""
248
+ return [
249
+ {'keyword': 'technology', 'confidence': 1.0, 'category': 'technical'},
250
+ {'keyword': 'business', 'confidence': 0.8, 'category': 'business'},
251
+ {'keyword': 'professional', 'confidence': 0.8, 'category': 'business'},
252
+ {'keyword': 'digital', 'confidence': 0.7, 'category': 'technical'}
253
+ ]
254
 
255
  def verify_image_url(self, url: str) -> bool:
256
  """Verify if an image URL is accessible"""
 
884
  max-width: 1200px;
885
  margin: 0 auto;
886
  }
887
+ .image-category {
888
+ margin-top: 2rem;
889
+ padding: 1rem;
890
+ border-radius: 0.5rem;
891
+ background: #f8f9fa;
892
  }
893
+ .image-metadata {
894
+ font-size: 0.8rem;
895
+ color: #666;
896
+ margin-top: 0.5rem;
897
  }
898
  </style>
899
  """, unsafe_allow_html=True)
900
 
 
901
  st.title("VaultGenix Video Generator")
902
  st.markdown("Create professional videos for your digital legacy management platform")
903
 
 
904
  with st.container():
905
  prompt = st.text_area("Enter your video script", height=200)
906
 
907
  if prompt:
908
+ with st.spinner("Analyzing prompt and fetching relevant images..."):
909
  try:
910
+ # Get categorized images
911
+ image_categories = self.generator.image_scraper.get_images(prompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
 
913
+ if any(image_categories.values()):
914
+ # Display primary matches
915
+ if image_categories['primary']:
916
+ st.subheader("Most Relevant Images")
917
+ self.display_image_grid(image_categories['primary'])
918
+
919
+ # Display secondary matches
920
+ if image_categories['secondary']:
921
+ st.subheader("Related Images")
922
+ self.display_image_grid(image_categories['secondary'])
923
+
924
+ # Display general/fallback images
925
+ if image_categories['general']:
926
+ st.subheader("Additional Suggested Images")
927
+ self.display_image_grid(image_categories['general'])
928
+
929
+ # Collect selected images
930
+ selected_images = []
931
+ for category in image_categories.values():
932
+ for img in category:
933
+ key = f"img_{img['url']}"
934
+ if st.session_state.get(key, False):
935
+ selected_images.append(img['url'])
936
+
937
+ # Video generation section
938
+ if selected_images:
939
+ self.show_video_settings(prompt, selected_images)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  else:
941
+ st.warning("No images found. Please try a different prompt.")
942
+
943
  except Exception as e:
944
  st.error(f"An error occurred: {str(e)}")
945
+ print(f"Error in UI: {str(e)}")
946
+
947
+ def display_image_grid(self, images: List[Dict[str, str]], cols: int = 3):
948
+ """Display images in a grid with metadata"""
949
+ for i in range(0, len(images), cols):
950
+ cols = st.columns(cols)
951
+ for j, col in enumerate(cols):
952
+ if i + j < len(images):
953
+ img = images[i + j]
954
+ with col:
955
+ try:
956
+ st.image(img['url'], use_container_width=True)
957
+ st.checkbox(
958
+ "Select",
959
+ key=f"img_{img['url']}",
960
+ help=f"Keywords: {img['keyword']}\nTags: {img['tags']}"
961
+ )
962
+ st.markdown(
963
+ f"<div class='image-metadata'>"
964
+ f"Relevance: {img['relevance']}<br>"
965
+ f"Keywords: {img['keyword']}"
966
+ f"</div>",
967
+ unsafe_allow_html=True
968
+ )
969
+ except Exception as e:
970
+ print(f"Error displaying image: {e}")
971
+
972
+ def show_video_settings(self, prompt: str, selected_images: List[str]):
973
+ """Show video generation settings and controls"""
974
+ st.subheader("Video Settings")
975
+ col1, col2 = st.columns(2)
976
+ with col1:
977
+ style = st.selectbox(
978
+ "Choose style",
979
+ options=["Professional", "Creative", "Educational"],
980
+ index=0
981
+ )
982
+ with col2:
983
+ duration = st.slider(
984
+ "Video duration (seconds)",
985
+ min_value=30,
986
+ max_value=180,
987
+ value=60,
988
+ step=30
989
+ )
990
+
991
+ if st.button("Generate Video", type="primary"):
992
+ self.generate_video(prompt, style, duration, selected_images)
993
+
994
+ def generate_video(self, prompt: str, style: str, duration: int, selected_images: List[str]):
995
+ """Handle video generation"""
996
+ with st.spinner("Generating your video..."):
997
+ try:
998
+ output_path = f"vaultgenix_video_{int(time.time())}.mp4"
999
+ video_path = self.generator.create_video(
1000
+ prompt,
1001
+ style,
1002
+ duration,
1003
+ output_path,
1004
+ selected_images
1005
+ )
1006
+
1007
+ if os.path.exists(video_path):
1008
+ st.success("✨ Video generated successfully!")
1009
+ st.video(video_path)
1010
+
1011
+ with open(video_path, 'rb') as video_file:
1012
+ st.download_button(
1013
+ "⬇️ Download Video",
1014
+ video_file.read(),
1015
+ file_name=output_path,
1016
+ mime="video/mp4"
1017
+ )
1018
+ except Exception as e:
1019
+ st.error(f"Failed to generate video: {str(e)}")
1020
+ print(f"Video generation error: {str(e)}")
1021
 
1022
  if __name__ == "__main__":
1023
  ui = VideoGeneratorUI()