Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import random | |
| import os | |
| from moviepy.editor import * | |
| from moviepy.video.fx.all import fadein, fadeout, speedx | |
| import fitz # PyMuPDF | |
| from gtts import gTTS | |
| from PIL import Image, ImageDraw, ImageFont, ImageFilter | |
| import textwrap | |
| import emoji | |
| # Constants | |
| CHARACTER_LIMIT = 2000 | |
| # Utility Functions | |
| def pdf_to_text(pdf_file): | |
| """Extract text from a PDF file with a character limit.""" | |
| doc = fitz.open(stream=pdf_file.read(), filetype="pdf") | |
| text = "" | |
| for page in doc: | |
| text += page.get_text() | |
| if len(text) >= CHARACTER_LIMIT: | |
| break | |
| return text[:CHARACTER_LIMIT] | |
| def create_audio_from_text(text, lang='en'): | |
| """Create audio from text using gTTS.""" | |
| tts = gTTS(text=text, lang=lang, slow=False) | |
| audio_path = "output_audio.mp3" | |
| tts.save(audio_path) | |
| return audio_path | |
| def create_custom_text_image(text, size=(640, 480), font_size=24): | |
| """Create an image with custom text.""" | |
| image = Image.new("RGB", size, (255, 255, 255)) | |
| draw = ImageDraw.Draw(image) | |
| font = ImageFont.load_default() | |
| wrapped_text = textwrap.fill(text, width=30) | |
| draw.text((10, 10), wrapped_text, fill="black", font=font) | |
| return image | |
| def create_video_with_transitions(thumbnails, audio_path, durations, text_overlays): | |
| """Create a video with transitions and audio.""" | |
| clips = [] | |
| audio_clip = AudioFileClip(audio_path) | |
| for idx, thumbnail in enumerate(thumbnails): | |
| duration = durations[idx] | |
| image = ImageClip(thumbnail).set_duration(duration).fx(fadein, 1).fx(fadeout, 1) | |
| if text_overlays and idx < len(text_overlays): | |
| text_image = create_custom_text_image(text_overlays[idx], size=image.size) | |
| text_image_path = "temp_text_image.png" | |
| text_image.save(text_image_path) | |
| text_clip = ImageClip(text_image_path).set_duration(duration).set_position('bottom') | |
| clips.append(text_clip) | |
| clips.append(image) | |
| video = concatenate_videoclips(clips, method="compose").set_audio(audio_clip) | |
| return video | |
| def add_background_effects(video, background_path): | |
| """Add a background image to the video.""" | |
| background = ImageClip(background_path).set_duration(video.duration) | |
| return CompositeVideoClip([background, video]) | |
| def create_image_collage(images, size=(1280, 720)): | |
| """Create a collage from a list of images.""" | |
| collage = Image.new("RGB", size, (255, 255, 255)) | |
| for idx, img in enumerate(images): | |
| image = Image.open(img).resize((200, 200)) | |
| x_offset = (idx % 5) * 200 | |
| y_offset = (idx // 5) * 200 | |
| collage.paste(image, (x_offset, y_offset)) | |
| return collage | |
| def mix_audio_tracks(audio_paths): | |
| """Mix multiple audio tracks.""" | |
| audio_clips = [AudioFileClip(path) for path in audio_paths] | |
| final_audio = concatenate_audioclips(audio_clips) | |
| return final_audio | |
| def add_dynamic_speed(video, speed_segments): | |
| """Apply different speeds to different segments.""" | |
| clips = [] | |
| for start, end, speed in speed_segments: | |
| subclip = video.subclip(start, end).fx(speedx, speed) | |
| clips.append(subclip) | |
| return concatenate_videoclips(clips) | |
| def apply_filter(image, filter_type): | |
| """Apply a filter to an image.""" | |
| if filter_type == "Sepia": | |
| sepia_image = image.convert("RGB") | |
| width, height = sepia_image.size | |
| pixels = sepia_image.load() | |
| for py in range(height): | |
| for px in range(width): | |
| r, g, b = sepia_image.getpixel((px, py)) | |
| tr = int(0.393 * r + 0.769 * g + 0.189 * b) | |
| tg = int(0.349 * r + 0.686 * g + 0.168 * b) | |
| tb = int(0.272 * r + 0.534 * g + 0.131 * b) | |
| pixels[px, py] = (min(tr, 255), min(tg, 255), min(tb, 255)) | |
| return sepia_image | |
| elif filter_type == "Blur": | |
| return image.filter(ImageFilter.GaussianBlur(radius=5)) | |
| return image | |
| def convert_text_to_emojis(text): | |
| """Convert text to emojis.""" | |
| return emoji.emojize(text, use_aliases=True) | |
| def share_video_on_socials(video_path): | |
| """Provide links to share the video.""" | |
| st.write("Share your video:") | |
| st.write(f"[Twitter](https://twitter.com/intent/tweet?url={video_path})") | |
| st.write(f"[Facebook](https://www.facebook.com/sharer/sharer.php?u={video_path})") | |
| def overlay_random_shapes(image): | |
| """Overlay random shapes on the given image.""" | |
| draw = ImageDraw.Draw(image) | |
| width, height = image.size | |
| # Define number of shapes to overlay | |
| num_shapes = random.randint(1, 5) | |
| for _ in range(num_shapes): | |
| shape_type = random.choice(['circle', 'rectangle']) | |
| x1 = random.randint(0, width) | |
| y1 = random.randint(0, height) | |
| x2 = random.randint(x1, width) | |
| y2 = random.randint(y1, height) | |
| if shape_type == 'circle': | |
| draw.ellipse([x1, y1, x2, y2], fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), 128)) | |
| elif shape_type == 'rectangle': | |
| draw.rectangle([x1, y1, x2, y2], fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), 128)) | |
| return image | |
| # Streamlit UI | |
| st.set_page_config(page_title="๐ฌ Create Youtube Videos effortlessly", layout="wide") | |
| st.title("๐ฌ Sobarine Content Technologies ๐") | |
| st.markdown("<h2 style='color: #66ccff; text-align: center;'>Create Stunning Videos Effortlessly!</h2>", unsafe_allow_html=True) | |
| # Main content | |
| st.header("Upload Your Content") | |
| pdf_file = st.file_uploader("Upload your PDF ๐ (max 2000 characters)", type="pdf") | |
| thumbnails = st.file_uploader("Upload images ๐ผ๏ธ", type=["png", "jpg", "jpeg"], accept_multiple_files=True) | |
| background_music = st.file_uploader("Upload background music ๐ถ (optional)", type=["mp3", "wav"], accept_multiple_files=True) | |
| background_image = st.file_uploader("Upload a background image ๐ผ๏ธ (optional)", type=["png", "jpg", "jpeg"]) | |
| watermark_image = st.file_uploader("Upload a watermark image (optional)", type=["png", "jpg", "jpeg"]) | |
| sound_effects = st.file_uploader("Upload sound effects (optional)", type=["mp3", "wav"], accept_multiple_files=True) | |
| # Text input with character limit | |
| text_input = st.text_area("Paste your content (max 2000 characters)", max_chars=CHARACTER_LIMIT) | |
| st.write(f"Characters used: {len(text_input)}") | |
| # Video customization options | |
| st.header("Customize Your Video") | |
| text_overlays = st.text_area("Enter custom text for overlays (one per thumbnail)").splitlines() | |
| apply_shapes = st.checkbox("Overlay random shapes on images") | |
| apply_glitch = st.checkbox("Apply glitch effect on video") | |
| filter_option = st.selectbox("Select an image filter for thumbnails:", ["None", "Sepia", "Blur"]) | |
| language_option = st.selectbox("Select TTS language:", ['en', 'es', 'fr', 'de', 'it']) | |
| # Image collage option | |
| if st.checkbox("Create an image collage"): | |
| collage = create_image_collage(thumbnails) | |
| collage_path = "collage.png" | |
| collage.save(collage_path) | |
| st.image(collage_path, caption='Generated Collage', use_column_width=True) | |
| # Adding a button to generate video | |
| if st.button("Generate Video"): | |
| if pdf_file or text_input: | |
| try: | |
| # Extract text from PDF if uploaded | |
| if pdf_file: | |
| extracted_text = pdf_to_text(pdf_file) | |
| else: | |
| extracted_text = text_input | |
| # Convert text to audio | |
| audio_path = create_audio_from_text(extracted_text, lang=language_option) | |
| st.success("Audio file created successfully!") | |
| # Process thumbnails | |
| processed_thumbnails = [] | |
| for thumbnail in thumbnails: | |
| image = Image.open(thumbnail) | |
| if apply_shapes: | |
| image = overlay_random_shapes(image) | |
| if filter_option != "None": | |
| image = apply_filter(image, filter_option) | |
| processed_image_path = f"processed_{thumbnail.name}" | |
| image.save(processed_image_path) | |
| processed_thumbnails.append(processed_image_path) | |
| st.success("Thumbnails processed successfully!") | |
| # Create the video | |
| durations = [5] * len(processed_thumbnails) # Default duration of 5 seconds per image | |
| video = create_video_with_transitions( | |
| thumbnails=processed_thumbnails, | |
| audio_path=audio_path, | |
| durations=durations, | |
| text_overlays=text_overlays | |
| ) | |
| # Add background image if provided | |
| if background_image: | |
| background_path = background_image.name | |
| background_video = add_background_effects(video, background_path) | |
| final_video = background_video | |
| else: | |
| final_video = video | |
| # Save the final video | |
| final_video_path = "final_video.mp4" | |
| final_video.write_videofile(final_video_path, codec="libx264") | |
| st.success("Video generated successfully!") | |
| st.video(final_video_path) | |
| except Exception as e: | |
| st.error(f"An error occurred: {e}") | |
| else: | |
| st.warning("Please upload a PDF or enter text to generate the video!") | |