403Webshell
Server IP : 198.71.58.22  /  Your IP : 216.73.216.72
Web Server : Apache/2.4.62 (AlmaLinux) OpenSSL/3.2.2
System : Linux localhost 5.14.0-570.33.2.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Aug 14 07:37:35 EDT 2025 x86_64
User : root ( 0)
PHP Version : 8.3.24
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/html/lesliepobee.com/artifacts/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/lesliepobee.com/artifacts/generate_video.py
#!/usr/bin/env python3
"""
Leslie Pobee homepage video generator.
Step 1: Upload image + audio to fal.ai storage
Step 2: Generate lip-sync video (photo + full audio)
Step 3: Generate star intro (text-to-video)
Step 4: Combine with FFmpeg (star intro → crossfade → lip-sync)
"""

import os
import sys
import json
import time
import subprocess
import urllib.request

os.environ['FAL_KEY'] = '05ea151f-8f29-4608-8c55-1080548e8b03:87942e7b7d0313b9824be4af371683ba'

import fal_client

ARTIFACTS = '/var/www/html/lesliepobee.com/artifacts'
IMAGE_PATH = f'{ARTIFACTS}/LeslieSingingArmsOut.jpg'
AUDIO_PATH = f'{ARTIFACTS}/homepageaudio.mp3.wav'
STAR_VIDEO_PATH = f'{ARTIFACTS}/star_intro.mp4'
LIPSYNC_VIDEO_PATH = f'{ARTIFACTS}/lipsync_output.mp4'
FINAL_VIDEO_PATH = f'{ARTIFACTS}/leslie_homepage_video.mp4'

STAR_PROMPT = (
    "Stars in a dark, deep space sky slowly streaming and sparkling, "
    "cinematic slow motion, dark atmospheric background, ethereal glow, "
    "4K quality, smooth motion"
)

LIPSYNC_NEGATIVE = (
    "static, whispering mouth, minimal jaw movement, robotic, frozen eyes, "
    "distorted face, extra limbs, blurred background"
)


def download(url, dest):
    print(f"  Downloading to {dest} ...")
    urllib.request.urlretrieve(url, dest)
    size = os.path.getsize(dest)
    print(f"  Saved: {size/1024:.1f} KB")


def upload(path, label):
    print(f"Uploading {label} ...")
    url = fal_client.upload_file(path)
    print(f"  URL: {url}")
    return url


def on_queue_update(update):
    if isinstance(update, fal_client.InProgress):
        for log in update.logs:
            print(f"  [log] {log['message']}")


# ── Step 1: Upload files ──────────────────────────────────────────────────────
print("\n=== STEP 1: Upload files to fal.ai storage ===")
image_url = upload(IMAGE_PATH, 'LeslieSingingArmsOut.jpg')
audio_url  = upload(AUDIO_PATH,  'homepageaudio.mp3.wav')

# ── Step 2: Lip-sync video ────────────────────────────────────────────────────
print("\n=== STEP 2: Generate lip-sync video (sync-lipsync) ===")
try:
    result = fal_client.subscribe(
        'fal-ai/sync-lipsync',
        arguments={
            'video_url': image_url,
            'audio_url': audio_url,
            'model': 'lipsync-2',
            'sync_mode': 'bounce',
        },
        with_logs=True,
        on_queue_update=on_queue_update,
    )
    lipsync_url = result.get('video', {}).get('url') or result.get('url')
    print(f"Lip-sync URL: {lipsync_url}")
    download(lipsync_url, LIPSYNC_VIDEO_PATH)
except Exception as e:
    print(f"sync-lipsync failed ({e}), trying sadtalker ...")
    result = fal_client.subscribe(
        'fal-ai/sadtalker',
        arguments={
            'source_image_url': image_url,
            'driven_audio_url': audio_url,
            'still_mode': False,
            'preprocess': 'crop',
            'size': 512,
        },
        with_logs=True,
        on_queue_update=on_queue_update,
    )
    lipsync_url = result.get('video', {}).get('url') or result.get('url')
    print(f"SadTalker URL: {lipsync_url}")
    download(lipsync_url, LIPSYNC_VIDEO_PATH)

# ── Step 3: Star intro (text-to-video) ───────────────────────────────────────
print("\n=== STEP 3: Generate star intro (kling text-to-video) ===")
try:
    result = fal_client.subscribe(
        'fal-ai/kling-video/v1.6/standard/text-to-video',
        arguments={
            'prompt': STAR_PROMPT,
            'duration': '5',
            'aspect_ratio': '16:9',
        },
        with_logs=True,
        on_queue_update=on_queue_update,
    )
    star_url = (result.get('video') or {}).get('url') or result.get('url')
    print(f"Star intro URL: {star_url}")
    download(star_url, STAR_VIDEO_PATH)
except Exception as e:
    print(f"Kling failed ({e}), trying minimax ...")
    result = fal_client.subscribe(
        'fal-ai/minimax-video/video-01-live',
        arguments={
            'prompt': STAR_PROMPT,
            'prompt_optimizer': True,
        },
        with_logs=True,
        on_queue_update=on_queue_update,
    )
    star_url = (result.get('video') or {}).get('url') or result.get('url')
    print(f"Minimax URL: {star_url}")
    download(star_url, STAR_VIDEO_PATH)

# ── Step 4: Combine with FFmpeg ───────────────────────────────────────────────
print("\n=== STEP 4: Combine star intro + lip-sync with FFmpeg ===")

# Get star intro duration
probe = subprocess.run(
    ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format', STAR_VIDEO_PATH],
    capture_output=True, text=True
)
star_duration = float(json.loads(probe.stdout)['format']['duration'])
print(f"Star intro duration: {star_duration:.2f}s")

# Get lipsync duration
probe2 = subprocess.run(
    ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format', LIPSYNC_VIDEO_PATH],
    capture_output=True, text=True
)
lipsync_duration = float(json.loads(probe2.stdout)['format']['duration'])
print(f"Lip-sync duration: {lipsync_duration:.2f}s")

CROSSFADE = 1.0  # seconds of overlap crossfade

# Combine: star intro crossfades into lipsync, audio from lipsync plays throughout
# Strategy: use xfade filter for video, amix or adelay for audio
ffmpeg_cmd = [
    'ffmpeg', '-y',
    '-i', STAR_VIDEO_PATH,
    '-i', LIPSYNC_VIDEO_PATH,
    '-filter_complex',
    (
        f'[0:v]scale=1280:720,fps=25[v0];'
        f'[1:v]scale=1280:720,fps=25[v1];'
        f'[v0][v1]xfade=transition=fade:duration={CROSSFADE}:offset={star_duration - CROSSFADE}[vout];'
        f'[1:a]adelay={(int((star_duration - CROSSFADE) * 1000))}|{int((star_duration - CROSSFADE) * 1000)}[aout]'
    ),
    '-map', '[vout]',
    '-map', '[aout]',
    '-c:v', 'libx264',
    '-c:a', 'aac',
    '-shortest',
    FINAL_VIDEO_PATH,
]

print("Running FFmpeg combine ...")
r = subprocess.run(ffmpeg_cmd, capture_output=True, text=True)
if r.returncode != 0:
    print("FFmpeg stderr:", r.stderr[-2000:])
    sys.exit(1)

final_size = os.path.getsize(FINAL_VIDEO_PATH)
print(f"\nFinal video: {FINAL_VIDEO_PATH}")
print(f"Size: {final_size / 1024 / 1024:.2f} MB")
print("Done.")

Youez - 2016 - github.com/yon3zu
LinuXploit