Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -24,26 +24,31 @@ from io import BytesIO
|
|
| 24 |
|
| 25 |
class ImageScraper:
|
| 26 |
def __init__(self):
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
def get_images(self, query: str, num_images: int = 15) -> List[str]:
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
search_query = f"{query} digital technology security"
|
| 34 |
-
|
| 35 |
-
url = f"https://pixabay.com/api/?key={self.PIXABAY_API_KEY}&q={search_query.replace(' ', '+')}&image_type=photo&per_page={num_images}"
|
| 36 |
-
|
| 37 |
-
response = requests.get(url)
|
| 38 |
-
data = response.json()
|
| 39 |
-
|
| 40 |
-
if 'hits' in data:
|
| 41 |
-
return [img['largeImageURL'] for img in data['hits']]
|
| 42 |
-
return []
|
| 43 |
-
|
| 44 |
-
except Exception as e:
|
| 45 |
-
print(f"Pixabay API error: {e}")
|
| 46 |
-
return []
|
| 47 |
|
| 48 |
def scrape_pexels(self, query: str) -> List[str]:
|
| 49 |
urls = []
|
|
@@ -557,60 +562,98 @@ class VideoGeneratorUI:
|
|
| 557 |
self.setup_ui()
|
| 558 |
|
| 559 |
def setup_ui(self):
|
| 560 |
-
st.
|
| 561 |
|
| 562 |
-
#
|
| 563 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 564 |
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
st.
|
| 568 |
-
images = self.generator.image_scraper.get_images(prompt)
|
| 569 |
|
| 570 |
-
if
|
| 571 |
-
st.
|
| 572 |
-
|
| 573 |
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
)
|
| 612 |
-
|
| 613 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 614 |
|
| 615 |
if __name__ == "__main__":
|
| 616 |
ui = VideoGeneratorUI()
|
|
|
|
| 24 |
|
| 25 |
class ImageScraper:
|
| 26 |
def __init__(self):
|
| 27 |
+
self.headers = {
|
| 28 |
+
'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',
|
| 29 |
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
| 30 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
| 31 |
+
'Connection': 'keep-alive',
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
def get_stock_images(self) -> List[str]:
|
| 35 |
+
"""Return preset stock images relevant to digital security and technology"""
|
| 36 |
+
return [
|
| 37 |
+
"https://images.pexels.com/photos/60504/security-protection-anti-virus-software-60504.jpeg",
|
| 38 |
+
"https://images.pexels.com/photos/5380642/pexels-photo-5380642.jpeg",
|
| 39 |
+
"https://images.pexels.com/photos/2582937/pexels-photo-2582937.jpeg",
|
| 40 |
+
"https://images.pexels.com/photos/7319074/pexels-photo-7319074.jpeg",
|
| 41 |
+
"https://images.pexels.com/photos/4164418/pexels-photo-4164418.jpeg",
|
| 42 |
+
"https://images.pexels.com/photos/3861969/pexels-photo-3861969.jpeg",
|
| 43 |
+
"https://images.pexels.com/photos/5473298/pexels-photo-5473298.jpeg",
|
| 44 |
+
"https://images.pexels.com/photos/4348401/pexels-photo-4348401.jpeg",
|
| 45 |
+
"https://images.pexels.com/photos/8386440/pexels-photo-8386440.jpeg",
|
| 46 |
+
"https://images.pexels.com/photos/5473950/pexels-photo-5473950.jpeg"
|
| 47 |
+
]
|
| 48 |
+
|
| 49 |
def get_images(self, query: str, num_images: int = 15) -> List[str]:
|
| 50 |
+
# Return preset stock images regardless of query
|
| 51 |
+
return self.get_stock_images()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
def scrape_pexels(self, query: str) -> List[str]:
|
| 54 |
urls = []
|
|
|
|
| 562 |
self.setup_ui()
|
| 563 |
|
| 564 |
def setup_ui(self):
|
| 565 |
+
st.set_page_config(layout="wide")
|
| 566 |
|
| 567 |
+
# Custom CSS
|
| 568 |
+
st.markdown("""
|
| 569 |
+
<style>
|
| 570 |
+
.stApp {
|
| 571 |
+
max-width: 1200px;
|
| 572 |
+
margin: 0 auto;
|
| 573 |
+
}
|
| 574 |
+
.image-grid {
|
| 575 |
+
display: grid;
|
| 576 |
+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
| 577 |
+
gap: 1rem;
|
| 578 |
+
}
|
| 579 |
+
.stButton>button {
|
| 580 |
+
width: 100%;
|
| 581 |
+
}
|
| 582 |
+
</style>
|
| 583 |
+
""", unsafe_allow_html=True)
|
| 584 |
+
|
| 585 |
+
# Header
|
| 586 |
+
st.title("VaultGenix Video Generator")
|
| 587 |
+
st.markdown("Create professional videos for your digital legacy management platform")
|
| 588 |
|
| 589 |
+
# Input Section
|
| 590 |
+
with st.container():
|
| 591 |
+
prompt = st.text_area("Enter your video script", height=200)
|
|
|
|
| 592 |
|
| 593 |
+
if prompt:
|
| 594 |
+
st.subheader("Select Images for Your Video")
|
| 595 |
+
images = self.generator.image_scraper.get_images(prompt)
|
| 596 |
|
| 597 |
+
if not images:
|
| 598 |
+
st.warning("Loading default technology images...")
|
| 599 |
+
images = self.generator.image_scraper.get_stock_images()
|
| 600 |
+
|
| 601 |
+
# Image Selection Grid
|
| 602 |
+
selected_images = []
|
| 603 |
+
cols = st.columns(3)
|
| 604 |
+
for idx, img_url in enumerate(images):
|
| 605 |
+
with cols[idx % 3]:
|
| 606 |
+
try:
|
| 607 |
+
st.image(img_url, use_column_width=True)
|
| 608 |
+
if st.checkbox(f"Select Image {idx + 1}", key=f"img_{idx}"):
|
| 609 |
+
selected_images.append(img_url)
|
| 610 |
+
except:
|
| 611 |
+
continue
|
| 612 |
+
|
| 613 |
+
# Video Generation Settings
|
| 614 |
+
if selected_images:
|
| 615 |
+
st.subheader("Video Settings")
|
| 616 |
+
col1, col2 = st.columns(2)
|
| 617 |
+
with col1:
|
| 618 |
+
style = st.selectbox(
|
| 619 |
+
"Choose style",
|
| 620 |
+
options=["Professional", "Creative", "Educational"],
|
| 621 |
+
index=0
|
| 622 |
+
)
|
| 623 |
+
with col2:
|
| 624 |
+
duration = st.slider(
|
| 625 |
+
"Video duration (seconds)",
|
| 626 |
+
min_value=30,
|
| 627 |
+
max_value=180,
|
| 628 |
+
value=60,
|
| 629 |
+
step=30
|
| 630 |
+
)
|
| 631 |
+
|
| 632 |
+
if st.button("Generate Video", type="primary"):
|
| 633 |
+
with st.spinner("Generating your video..."):
|
| 634 |
+
try:
|
| 635 |
+
output_path = f"vaultgenix_video_{int(time.time())}.mp4"
|
| 636 |
+
video_path = self.generator.create_video(
|
| 637 |
+
prompt,
|
| 638 |
+
style,
|
| 639 |
+
duration,
|
| 640 |
+
output_path,
|
| 641 |
+
selected_images
|
| 642 |
)
|
| 643 |
+
|
| 644 |
+
if os.path.exists(video_path):
|
| 645 |
+
st.success("✨ Video generated successfully!")
|
| 646 |
+
st.video(video_path)
|
| 647 |
+
|
| 648 |
+
with open(video_path, 'rb') as video_file:
|
| 649 |
+
st.download_button(
|
| 650 |
+
"⬇️ Download Video",
|
| 651 |
+
video_file.read(),
|
| 652 |
+
file_name=output_path,
|
| 653 |
+
mime="video/mp4"
|
| 654 |
+
)
|
| 655 |
+
except Exception as e:
|
| 656 |
+
st.error(f"Failed to generate video: {str(e)}")
|
| 657 |
|
| 658 |
if __name__ == "__main__":
|
| 659 |
ui = VideoGeneratorUI()
|