|
import streamlit as st |
|
from transformers import pipeline |
|
from PIL import Image |
|
import os |
|
import pathlib |
|
from huggingface_hub import snapshot_download |
|
from modelscope.pipelines import pipeline as modelscope_pipeline |
|
from modelscope.outputs import OutputKeys |
|
import shutil |
|
|
|
|
|
if not os.path.exists('downloads'): |
|
os.makedirs('downloads') |
|
|
|
def initialize_models(): |
|
"""Initialize and cache the models to avoid reloading.""" |
|
if 'caption_pipeline' not in st.session_state: |
|
st.session_state.caption_pipeline = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base") |
|
|
|
if 'video_pipeline' not in st.session_state: |
|
|
|
model_dir = pathlib.Path('weights') |
|
snapshot_download( |
|
'damo-vilab/modelscope-damo-text-to-video-synthesis', |
|
repo_type='model', |
|
local_dir=model_dir |
|
) |
|
st.session_state.video_pipeline = modelscope_pipeline( |
|
'text-to-video-synthesis', |
|
model_dir.as_posix() |
|
) |
|
|
|
def save_video(video_path, caption): |
|
"""Save video to downloads directory with a meaningful name.""" |
|
|
|
safe_caption = "".join(x for x in caption[:30] if x.isalnum() or x in (' ','-','_')).strip() |
|
save_name = f"video_{safe_caption}.mp4" |
|
save_path = os.path.join('downloads', save_name) |
|
|
|
|
|
shutil.copy2(video_path, save_path) |
|
return save_path |
|
|
|
def generate_video_from_image(image, progress_bar=None): |
|
"""Generate a video based on image caption using ModelScope's text-to-video model.""" |
|
try: |
|
if progress_bar: |
|
progress_bar.progress(0.1, "Generating image caption...") |
|
|
|
|
|
caption = st.session_state.caption_pipeline(image)[0]['generated_text'] |
|
st.write(f"Generated caption: *{caption}*") |
|
|
|
if progress_bar: |
|
progress_bar.progress(0.3, "Generating video...") |
|
|
|
|
|
input_text = {'text': caption} |
|
|
|
|
|
output = st.session_state.video_pipeline(input_text) |
|
video_path = output[OutputKeys.OUTPUT_VIDEO] |
|
|
|
|
|
final_path = save_video(video_path, caption) |
|
|
|
if progress_bar: |
|
progress_bar.progress(1.0, "Video generation complete!") |
|
|
|
return final_path, caption |
|
|
|
except Exception as e: |
|
st.error(f"Error generating video: {str(e)}") |
|
raise |
|
|
|
def main(): |
|
st.set_page_config(page_title="AI Video Generator", page_icon="🎥") |
|
|
|
st.title("🎥 Text-to-Video Generator") |
|
st.write(""" |
|
Upload an image to generate a video based on its content. The app will: |
|
1. Generate a caption for your image |
|
2. Create a video based on that caption |
|
3. Provide options to view and download the video |
|
""") |
|
|
|
|
|
st.warning(""" |
|
Model Limitations: |
|
- Only English text is supported |
|
- Cannot generate clear text in videos |
|
- May have limitations with complex scenes |
|
- Generation takes several minutes |
|
""") |
|
|
|
|
|
with st.spinner("Loading models... This may take a minute..."): |
|
initialize_models() |
|
|
|
|
|
uploaded_file = st.file_uploader("Choose an image", type=['png', 'jpg', 'jpeg']) |
|
|
|
if uploaded_file is not None: |
|
|
|
image = Image.open(uploaded_file) |
|
st.image(image, caption="Uploaded Image", use_column_width=True) |
|
|
|
|
|
if st.button("Generate Video"): |
|
try: |
|
|
|
progress_text = "Operation in progress. Please wait..." |
|
my_bar = st.progress(0, text=progress_text) |
|
|
|
|
|
video_path, caption = generate_video_from_image(image, my_bar) |
|
|
|
if video_path and os.path.exists(video_path): |
|
|
|
with open(video_path, 'rb') as video_file: |
|
video_bytes = video_file.read() |
|
|
|
|
|
st.success("Video generated successfully!") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
|
|
st.download_button( |
|
label="💾 Download Video", |
|
data=video_bytes, |
|
file_name=os.path.basename(video_path), |
|
mime="video/mp4", |
|
key="download1" |
|
) |
|
|
|
with col2: |
|
|
|
st.download_button( |
|
label="📥 Download with Caption", |
|
data=video_bytes, |
|
file_name=f"{caption[:30]}.mp4", |
|
mime="video/mp4", |
|
key="download2" |
|
) |
|
|
|
|
|
st.video(video_bytes) |
|
|
|
|
|
st.info(f""" |
|
Video Details: |
|
- Caption: {caption} |
|
- Filename: {os.path.basename(video_path)} |
|
- Size: {len(video_bytes)/1024/1024:.1f} MB |
|
""") |
|
|
|
else: |
|
st.error("Failed to generate video. Please try again.") |
|
|
|
except Exception as e: |
|
st.error(f"An error occurred: {str(e)}") |
|
|
|
if __name__ == "__main__": |
|
main() |