Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -201,110 +201,82 @@ class ImageScraper:
|
|
| 201 |
]
|
| 202 |
|
| 203 |
def get_images(self, query: str, num_images: int = 15) -> Dict[str, List[Dict[str, str]]]:
|
| 204 |
-
"""
|
| 205 |
-
Get images from Pixabay API with enhanced error handling and categorization
|
| 206 |
-
Returns a dictionary with categorized image results
|
| 207 |
-
"""
|
| 208 |
try:
|
| 209 |
-
#
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
params = {
|
| 215 |
-
'key': self.PIXABAY_API_KEY,
|
| 216 |
-
'q': query,
|
| 217 |
-
'image_type': 'photo',
|
| 218 |
-
'per_page': num_images,
|
| 219 |
-
'safesearch': True,
|
| 220 |
-
'lang': 'en'
|
| 221 |
}
|
| 222 |
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
backup_response = requests.get(base_url, params=params, headers=self.headers)
|
| 238 |
-
if backup_response.status_code == 200:
|
| 239 |
-
backup_data = backup_response.json()
|
| 240 |
-
hits.extend(backup_data.get('hits', []))
|
| 241 |
-
if hits:
|
| 242 |
-
break
|
| 243 |
-
|
| 244 |
-
# Structure response with categories
|
| 245 |
-
result = {
|
| 246 |
-
'primary': [],
|
| 247 |
-
'secondary': [],
|
| 248 |
-
'general': []
|
| 249 |
}
|
| 250 |
|
| 251 |
-
|
| 252 |
-
if not hits:
|
| 253 |
-
stock_images = self.get_stock_images()
|
| 254 |
-
result['general'] = [
|
| 255 |
-
{
|
| 256 |
-
'url': url,
|
| 257 |
-
'keyword': 'technology',
|
| 258 |
-
'relevance': 'Fallback',
|
| 259 |
-
'tags': 'technology'
|
| 260 |
-
} for url in stock_images
|
| 261 |
-
]
|
| 262 |
-
return result
|
| 263 |
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
'url': hit['largeImageURL'],
|
| 268 |
-
'keyword': query,
|
| 269 |
-
'relevance': 'Primary match' if query.lower() in hit.get('tags', '').lower() else 'Related',
|
| 270 |
-
'tags': hit.get('tags', '')
|
| 271 |
-
}
|
| 272 |
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
except Exception as e:
|
| 293 |
print(f"Error in get_images: {str(e)}")
|
| 294 |
# Return stock images as fallback
|
| 295 |
stock_images = self.get_stock_images()
|
| 296 |
return {
|
| 297 |
-
'general': [
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
} for url in stock_images
|
| 304 |
-
]
|
| 305 |
}
|
| 306 |
-
|
| 307 |
-
|
| 308 |
def get_fallback_keywords(self) -> List[Dict[str, str]]:
|
| 309 |
"""Return fallback keywords if AI extraction fails"""
|
| 310 |
return [
|
|
@@ -820,25 +792,39 @@ class EnhancedVideoGenerator:
|
|
| 820 |
return text.strip()
|
| 821 |
|
| 822 |
def extract_key_topics(self, script: str) -> List[str]:
|
| 823 |
-
"""Extract
|
| 824 |
try:
|
| 825 |
-
#
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
# Extract potential noun phrases (pairs of words)
|
| 834 |
-
topics.append(' '.join(words[:2]))
|
| 835 |
|
| 836 |
-
#
|
| 837 |
-
return list(dict.fromkeys(topics))[:5]
|
| 838 |
|
| 839 |
except Exception as e:
|
| 840 |
-
|
| 841 |
-
return [
|
| 842 |
|
| 843 |
def generate_ai_image(self, prompt: str, style: str) -> Optional[Image.Image]:
|
| 844 |
"""Generate an AI image using Stability AI"""
|
|
@@ -976,29 +962,40 @@ class VideoGeneratorUI:
|
|
| 976 |
|
| 977 |
def display_image_grid(self, images: List[Dict[str, str]], cols: int = 3):
|
| 978 |
"""Display images in a grid with metadata"""
|
| 979 |
-
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
| 992 |
-
|
| 993 |
-
|
| 994 |
-
|
| 995 |
-
|
| 996 |
-
|
| 997 |
-
|
| 998 |
-
|
| 999 |
-
|
| 1000 |
-
|
| 1001 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1002 |
def show_video_settings(self, prompt: str, selected_images: List[str]):
|
| 1003 |
"""Show video generation settings and controls"""
|
| 1004 |
st.subheader("Video Settings")
|
|
|
|
| 201 |
]
|
| 202 |
|
| 203 |
def get_images(self, query: str, num_images: int = 15) -> Dict[str, List[Dict[str, str]]]:
|
| 204 |
+
"""Get images for either single word queries or extract keywords from long prompts"""
|
|
|
|
|
|
|
|
|
|
| 205 |
try:
|
| 206 |
+
# Initialize result structure
|
| 207 |
+
result = {
|
| 208 |
+
'primary': [],
|
| 209 |
+
'secondary': [],
|
| 210 |
+
'general': []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
}
|
| 212 |
|
| 213 |
+
# Extract keywords if query is long
|
| 214 |
+
if len(query.split()) > 3:
|
| 215 |
+
keywords = self.extract_key_topics(query)
|
| 216 |
+
print(f"Extracted keywords: {keywords}") # Debug log
|
| 217 |
+
else:
|
| 218 |
+
keywords = [query]
|
| 219 |
|
| 220 |
+
# Fetch images for each keyword
|
| 221 |
+
for keyword in keywords:
|
| 222 |
+
base_url = "https://pixabay.com/api/"
|
| 223 |
+
params = {
|
| 224 |
+
'key': self.PIXABAY_API_KEY,
|
| 225 |
+
'q': keyword,
|
| 226 |
+
'image_type': 'photo',
|
| 227 |
+
'per_page': max(3, num_images // len(keywords)), # Distribute images among keywords
|
| 228 |
+
'safesearch': True,
|
| 229 |
+
'lang': 'en'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
}
|
| 231 |
|
| 232 |
+
response = requests.get(base_url, params=params, headers=self.headers)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
| 234 |
+
if response.status_code == 200:
|
| 235 |
+
data = response.json()
|
| 236 |
+
hits = data.get('hits', [])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
|
| 238 |
+
for hit in hits:
|
| 239 |
+
image_data = {
|
| 240 |
+
'url': hit['largeImageURL'],
|
| 241 |
+
'keyword': keyword,
|
| 242 |
+
'relevance': 'Primary match',
|
| 243 |
+
'tags': hit.get('tags', '')
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
# Distribute images across categories
|
| 247 |
+
if len(result['primary']) < num_images // 3:
|
| 248 |
+
result['primary'].append(image_data)
|
| 249 |
+
elif len(result['secondary']) < num_images // 3:
|
| 250 |
+
result['secondary'].append(image_data)
|
| 251 |
+
else:
|
| 252 |
+
result['general'].append(image_data)
|
| 253 |
+
|
| 254 |
+
# If no images found, use stock images
|
| 255 |
+
if not any(result.values()):
|
| 256 |
+
stock_images = self.get_stock_images()
|
| 257 |
+
result['general'] = [{
|
| 258 |
+
'url': url,
|
| 259 |
+
'keyword': 'technology',
|
| 260 |
+
'relevance': 'Fallback',
|
| 261 |
+
'tags': 'technology'
|
| 262 |
+
} for url in stock_images[:num_images]]
|
| 263 |
+
|
| 264 |
+
return result
|
| 265 |
+
|
| 266 |
except Exception as e:
|
| 267 |
print(f"Error in get_images: {str(e)}")
|
| 268 |
# Return stock images as fallback
|
| 269 |
stock_images = self.get_stock_images()
|
| 270 |
return {
|
| 271 |
+
'general': [{
|
| 272 |
+
'url': url,
|
| 273 |
+
'keyword': 'technology',
|
| 274 |
+
'relevance': 'Fallback',
|
| 275 |
+
'tags': 'technology'
|
| 276 |
+
} for url in stock_images[:num_images]]
|
|
|
|
|
|
|
| 277 |
}
|
| 278 |
+
|
| 279 |
+
|
| 280 |
def get_fallback_keywords(self) -> List[Dict[str, str]]:
|
| 281 |
"""Return fallback keywords if AI extraction fails"""
|
| 282 |
return [
|
|
|
|
| 792 |
return text.strip()
|
| 793 |
|
| 794 |
def extract_key_topics(self, script: str) -> List[str]:
|
| 795 |
+
"""Extract key topics from a long text prompt"""
|
| 796 |
try:
|
| 797 |
+
# Common tech-related terms to look for
|
| 798 |
+
tech_terms = {
|
| 799 |
+
'security', 'digital', 'technology', 'data', 'encryption',
|
| 800 |
+
'privacy', 'protection', 'software', 'platform', 'system',
|
| 801 |
+
'AI', 'artificial intelligence', 'computing', 'cyber'
|
| 802 |
+
}
|
| 803 |
+
|
| 804 |
+
# Split into words and get unique terms
|
| 805 |
+
words = script.lower().split()
|
| 806 |
+
topics = set()
|
| 807 |
+
|
| 808 |
+
# Extract single word topics
|
| 809 |
+
for word in words:
|
| 810 |
+
if word in tech_terms:
|
| 811 |
+
topics.add(word)
|
| 812 |
+
|
| 813 |
+
# Extract two-word phrases
|
| 814 |
+
for i in range(len(words) - 1):
|
| 815 |
+
phrase = f"{words[i]} {words[i+1]}"
|
| 816 |
+
if any(term in phrase for term in tech_terms):
|
| 817 |
+
topics.add(phrase)
|
| 818 |
|
| 819 |
+
# Add some default topics if none found
|
| 820 |
+
if not topics:
|
| 821 |
+
topics = {'digital security', 'data protection', 'technology'}
|
|
|
|
|
|
|
| 822 |
|
| 823 |
+
return list(topics)[:5] # Return top 5 topics
|
|
|
|
| 824 |
|
| 825 |
except Exception as e:
|
| 826 |
+
print(f"Topic extraction error: {e}")
|
| 827 |
+
return ['digital security']
|
| 828 |
|
| 829 |
def generate_ai_image(self, prompt: str, style: str) -> Optional[Image.Image]:
|
| 830 |
"""Generate an AI image using Stability AI"""
|
|
|
|
| 962 |
|
| 963 |
def display_image_grid(self, images: List[Dict[str, str]], cols: int = 3):
|
| 964 |
"""Display images in a grid with metadata"""
|
| 965 |
+
# Ensure images is a list and not empty
|
| 966 |
+
if not images or not isinstance(images, list):
|
| 967 |
+
return
|
| 968 |
+
|
| 969 |
+
# Calculate number of rows needed
|
| 970 |
+
n_images = len(images)
|
| 971 |
+
n_rows = (n_images + cols - 1) // cols
|
| 972 |
+
|
| 973 |
+
# Create grid
|
| 974 |
+
for row in range(n_rows):
|
| 975 |
+
with st.container():
|
| 976 |
+
columns = st.columns(cols)
|
| 977 |
+
for col in range(cols):
|
| 978 |
+
idx = row * cols + col
|
| 979 |
+
if idx < n_images:
|
| 980 |
+
img = images[idx]
|
| 981 |
+
with columns[col]:
|
| 982 |
+
try:
|
| 983 |
+
st.image(img['url'], use_container_width=True)
|
| 984 |
+
st.checkbox(
|
| 985 |
+
"Select",
|
| 986 |
+
key=f"img_{img['url']}",
|
| 987 |
+
help=f"Keywords: {img['keyword']}\nTags: {img['tags']}"
|
| 988 |
+
)
|
| 989 |
+
st.markdown(
|
| 990 |
+
f"<div class='image-metadata'>"
|
| 991 |
+
f"Relevance: {img['relevance']}<br>"
|
| 992 |
+
f"Keywords: {img['keyword']}"
|
| 993 |
+
f"</div>",
|
| 994 |
+
unsafe_allow_html=True
|
| 995 |
+
)
|
| 996 |
+
except Exception as e:
|
| 997 |
+
print(f"Error displaying image: {e}")
|
| 998 |
+
|
| 999 |
def show_video_settings(self, prompt: str, selected_images: List[str]):
|
| 1000 |
"""Show video generation settings and controls"""
|
| 1001 |
st.subheader("Video Settings")
|