evercontentai / app.py
sobarine's picture
Update app.py
a865715 verified
Raw
History Blame Contribute Delete
9.33 kB
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!")