test1 / app.py
testdeep123's picture
Update app.py
3e3c550 verified
raw
history blame
10.1 kB
# Import necessary libraries (assuming all your imports remain the same)
import gradio as gr
import os
import tempfile
import shutil
from moviepy.editor import concatenate_videoclips, CompositeVideoClip, AudioFileClip, TextClip
# Your existing helper functions (generate_script, parse_script, etc.) remain unchanged
# Ensure TEMP_FOLDER, TARGET_RESOLUTION, and CAPTION_COLOR are set within functions as needed
# Define maximum number of clips to handle in the UI
MAX_CLIPS = 10
def process_script(topic, script_input):
"""Process the topic or script and return updates for the UI."""
if script_input.strip():
raw_script = script_input
else:
raw_script = generate_script(topic)
if not raw_script:
return "Failed to generate script", 0, [], [], [], []
elements = parse_script(raw_script)
paired_elements = [(elements[i], elements[i + 1]) for i in range(0, len(elements) - 1, 2)]
num_clips = min(len(paired_elements), MAX_CLIPS)
# Prepare updates for clip editor
accordion_updates = []
prompt_updates = []
narration_updates = []
media_updates = []
for i in range(MAX_CLIPS):
if i < num_clips:
media_elem, tts_elem = paired_elements[i]
accordion_updates.append(gr.update(visible=True, label=f"Clip {i+1}: {media_elem['prompt'][:20]}..."))
prompt_updates.append(gr.update(value=media_elem['prompt']))
narration_updates.append(gr.update(value=tts_elem['text']))
media_updates.append(gr.update(value=None)) # Reset file upload
else:
accordion_updates.append(gr.update(visible=False))
prompt_updates.append(gr.update(value=""))
narration_updates.append(gr.update(value=""))
media_updates.append(gr.update(value=None))
return raw_script, num_clips, accordion_updates, prompt_updates, narration_updates, media_updates
def generate_video_full(resolution, render_speed, video_clip_percent, zoom_pan_effect,
bgm_upload, bgm_volume, subtitles_enabled, font, font_size,
outline_width, font_color, outline_color, position, num_clips,
*clip_inputs):
"""Generate the video using all settings and edited clip data."""
global TARGET_RESOLUTION, CAPTION_COLOR, TEMP_FOLDER
# Set resolution
TARGET_RESOLUTION = (1080, 1920) if resolution == "Short (1080x1920)" else (1920, 1080)
# Set caption settings
CAPTION_COLOR = font_color if subtitles_enabled else "transparent"
# Create temporary folder
TEMP_FOLDER = tempfile.mkdtemp()
# Parse clip inputs (visual_prompt, narration, custom_media for each clip)
clips_data = []
for i in range(num_clips):
idx = i * 3
visual_prompt = clip_inputs[idx]
narration = clip_inputs[idx + 1]
custom_media = clip_inputs[idx + 2]
clips_data.append({
'visual_prompt': visual_prompt,
'narration': narration,
'custom_media': custom_media
})
# Generate clips
clips = []
for idx, clip_data in enumerate(clips_data):
# Use custom media if provided, otherwise generate media
if clip_data['custom_media']:
media_path = clip_data['custom_media']
asset_type = 'video' if media_path.endswith(('.mp4', '.avi', '.mov')) else 'image'
else:
media_asset = generate_media(clip_data['visual_prompt'], current_index=idx, total_segments=num_clips)
if not media_asset:
continue
media_path = media_asset['path']
asset_type = media_asset['asset_type']
# Adjust video clip percentage
original_random = random.random()
adjusted_random = original_random * (video_clip_percent / 100)
if adjusted_random < (video_clip_percent / 100) and not clip_data['custom_media']:
media_asset = generate_media(clip_data['visual_prompt'], current_index=idx, total_segments=num_clips)
if media_asset and media_asset['asset_type'] == 'video':
media_path = media_asset['path']
asset_type = 'video'
# Generate TTS
tts_path = generate_tts(clip_data['narration'], 'en')
if not tts_path:
continue
# Create clip
duration = max(3, len(clip_data['narration'].split()) * 0.5)
clip = create_clip(
media_path=media_path,
asset_type=asset_type,
tts_path=tts_path,
duration=duration,
effects='fade-in',
narration_text=clip_data['narration'],
segment_index=idx
)
if clip and zoom_pan_effect and asset_type == 'image':
clip = apply_kenburns_effect(clip, TARGET_RESOLUTION)
if clip:
clips.append(clip)
if not clips:
shutil.rmtree(TEMP_FOLDER)
return None, None
# Concatenate clips
final_video = concatenate_videoclips(clips, method="compose")
# Add background music if uploaded
if bgm_upload:
bg_music = AudioFileClip(bgm_upload).volumex(bgm_volume)
if bg_music.duration < final_video.duration:
bg_music = bg_music.loop(duration=final_video.duration)
else:
bg_music = bg_music.subclip(0, final_video.duration)
final_video = final_video.set_audio(CompositeVideoClip([final_video.audio, bg_music]))
# Export video
output_path = "final_video.mp4"
final_video.write_videofile(output_path, codec='libx264', fps=24, preset=render_speed)
# Clean up
shutil.rmtree(TEMP_FOLDER)
return output_path, output_path
# Gradio Blocks Interface
with gr.Blocks(title="πŸš€ Orbit Video Engine") as demo:
gr.Markdown("# πŸš€ Orbit Video Engine")
gr.Markdown("Create funny documentary-style videos with ease!")
with gr.Row():
# Column 1: Content Input & Script Generation
with gr.Column(scale=1):
gr.Markdown("### 1. Content Input")
topic_input = gr.Textbox(label="Topic", placeholder="e.g., Funny Cat Facts")
script_input = gr.Textbox(label="Or Paste Full Script", lines=10, placeholder="[Title]\nNarration...")
generate_button = gr.Button("πŸ“ Generate Script & Load Clips")
script_display = gr.Textbox(label="Generated Script", interactive=False, visible=False)
# Column 2: Clip Editor
with gr.Column(scale=2):
gr.Markdown("### 2. Edit Clips")
gr.Markdown("Modify prompts, narration, or upload custom media below.")
with gr.Column() as clip_editor:
clip_accordions = []
for i in range(MAX_CLIPS):
with gr.Accordion(f"Clip {i+1}", visible=False) as acc:
visual_prompt = gr.Textbox(label="Visual Prompt")
narration = gr.Textbox(label="Narration", lines=3)
custom_media = gr.File(label="Upload Custom Media (Image/Video)")
clip_accordions.append((acc, visual_prompt, narration, custom_media))
# Column 3: Settings & Output
with gr.Column(scale=1):
gr.Markdown("### 3. Video Settings")
resolution = gr.Radio(["Short (1080x1920)", "Full HD (1920x1080)"], label="Resolution", value="Full HD (1920x1080)")
render_speed = gr.Dropdown(["ultrafast", "faster", "fast", "medium", "slow", "slower", "veryslow"], label="Render Speed", value="fast")
video_clip_percent = gr.Slider(0, 100, value=25, label="Video Clip Percentage")
zoom_pan_effect = gr.Checkbox(label="Add Zoom/Pan Effect (Images)", value=True)
with gr.Accordion("Background Music", open=False):
bgm_upload = gr.Audio(label="Upload Background Music", type="filepath")
bgm_volume = gr.Slider(0.0, 1.0, value=0.15, label="BGM Volume")
with gr.Accordion("Subtitle Settings", open=True):
subtitles_enabled = gr.Checkbox(label="Enable Subtitles", value=True)
font = gr.Dropdown(["Impact", "Arial", "Times New Roman"], label="Font", value="Arial")
font_size = gr.Number(label="Font Size", value=45)
outline_width = gr.Number(label="Outline Width", value=2)
font_color = gr.ColorPicker(label="Font Color", value="#FFFFFF")
outline_color = gr.ColorPicker(label="Outline Color", value="#000000")
position = gr.Radio(["center", "bottom", "top"], label="Position", value="bottom")
generate_video_button = gr.Button("🎬 Generate Video")
gr.Markdown("### 4. Output")
output_video = gr.Video(label="Generated Video")
download_button = gr.File(label="Download Video")
# State to track number of clips
num_clips_state = gr.State(value=0)
# Event handlers
generate_button.click(
fn=process_script,
inputs=[topic_input, script_input],
outputs=[script_display, num_clips_state] +
[comp for acc in clip_accordions for comp in [acc[0], acc[1], acc[2], acc[3]]],
_js="() => {return [document.querySelector('#topic_input textarea').value, document.querySelector('#script_input textarea').value]}"
).then(
fn=lambda x: gr.update(visible=True),
inputs=[script_display],
outputs=[script_display]
)
generate_video_button.click(
fn=generate_video_full,
inputs=[resolution, render_speed, video_clip_percent, zoom_pan_effect,
bgm_upload, bgm_volume, subtitles_enabled, font, font_size,
outline_width, font_color, outline_color, position, num_clips_state] +
[comp for acc in clip_accordions for comp in acc[1:]], # visual_prompt, narration, custom_media
outputs=[output_video, download_button]
)
# Launch the interface
demo.launch(share=True)