File size: 4,603 Bytes
fed2287 4887e95 efb68a6 a4b5d8d f6e88f5 2da681a 17e1071 efb68a6 f6e88f5 efb68a6 17e1071 f6e88f5 6d9efef d56f850 f6e88f5 d56f850 f6e88f5 d56f850 f6e88f5 d56f850 f6e88f5 6dc2268 17e1071 f6e88f5 120d8f4 f6e88f5 17e1071 d56f850 f6e88f5 d56f850 f6e88f5 d56f850 17e1071 d56f850 f6e88f5 d56f850 f6e88f5 d56f850 fed2287 f6e88f5 d56f850 f6e88f5 d56f850 17e1071 d56f850 f6e88f5 d56f850 b331259 17e1071 120d8f4 d56f850 f6e88f5 fed2287 4887e95 f6e88f5 17e1071 4887e95 f6e88f5 17e1071 f6e88f5 4887e95 17e1071 120d8f4 17e1071 fed2287 17e1071 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | import gradio as gr
import subprocess
import os
import uuid
import json
# Auto-install Node modules
if not os.path.exists("node_modules"):
subprocess.run(["npm", "install"], check=True)
def get_video_dimensions(url):
try:
cmd = [
"ffprobe", "-v", "error", "-select_streams", "v:0",
"-show_entries", "stream=width,height", "-of", "json", url
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
data = json.loads(result.stdout)
return data['streams'][0]['width'], data['streams'][0]['height']
except:
return 0, 0
def run_scraper(mode, query, orientation="Any"):
"""Helper to run the Node.js scraper in specific mode"""
try:
# Calls: node scraper.js [mode] [query] [orientation]
cmd = ["node", "scraper.js", mode, query, orientation]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=240)
urls = [line.strip() for line in result.stdout.split('\n') if line.strip().startswith("http")]
return urls
except Exception as e:
print(f"Scraper Error ({mode}): {e}")
return []
def process_video(query, orientation, start_time, end_time, mute_audio, progress=gr.Progress()):
if not query:
return None, "β οΈ Enter a keyword."
search_query = query if "video" in query.lower() else f"{query} video"
# --- PHASE 1: PINTEREST SEARCH ---
progress(0.1, desc="π Searching Pinterest...")
all_urls = run_scraper("pinterest", search_query)
# Filter Pinterest Results
selected_url = None
for i, url in enumerate(all_urls):
progress(0.3 + (i/len(all_urls)*0.1), desc=f"Checking Pinterest {i+1}...")
if orientation == "Any": selected_url = url; break
w, h = get_video_dimensions(url)
if orientation == "Portrait" and h > w: selected_url = url; break
if orientation == "Landscape" and w > h: selected_url = url; break
# --- PHASE 2: PEXELS FALLBACK ---
if not selected_url:
progress(0.5, desc=f"β οΈ No {orientation} videos on Pinterest. Switching to Pexels Fallback...")
# We pass the orientation to Pexels so it filters efficiently
pexels_urls = run_scraper("pexels", query, orientation)
for i, url in enumerate(pexels_urls):
progress(0.6 + (i/len(pexels_urls)*0.1), desc=f"Checking Pexels {i+1}...")
# Double check dimensions just to be safe
if orientation == "Any": selected_url = url; break
w, h = get_video_dimensions(url)
if orientation == "Portrait" and h > w: selected_url = url; break
if orientation == "Landscape" and w > h: selected_url = url; break
if not selected_url:
return None, f"β Failed. Searched Pinterest & Pexels, but found no {orientation} videos."
# --- PHASE 3: PROCESSING ---
progress(0.8, desc="βοΈ Processing Video...")
output_filename = f"final_{uuid.uuid4().hex[:5]}.mp4"
ffmpeg_cmd = [
"ffmpeg",
"-ss", str(start_time),
"-to", str(end_time) if end_time > 0 else "999",
"-i", selected_url,
"-vf", "unsharp=3:3:1.2:3:3:0.0,format=yuv420p",
"-c:v", "libx264",
"-crf", "18",
"-preset", "veryfast",
"-y", output_filename
]
if mute_audio:
ffmpeg_cmd.insert(-1, "-an")
else:
ffmpeg_cmd.insert(-1, "-c:a")
ffmpeg_cmd.insert(-1, "aac")
subprocess.run(ffmpeg_cmd, check=True)
source_name = "Pinterest" if "pinimg" in selected_url else "Pexels"
return output_filename, f"β
Success! Source: {source_name} ({orientation})"
# --- UI ---
with gr.Blocks(theme=gr.themes.Default()) as demo:
gr.Markdown("# π Pinterest + Pexels (Auto-Fallback)")
with gr.Row():
with gr.Column():
q = gr.Textbox(label="Topic", placeholder="e.g. Ocean Waves")
o = gr.Dropdown(choices=["Any", "Portrait", "Landscape"], value="Portrait", label="Orientation")
with gr.Row():
s = gr.Number(label="Start (sec)", value=0)
e = gr.Number(label="End (sec)", value=5)
mute = gr.Checkbox(label="Mute Audio", value=False)
btn = gr.Button("π Search & Process", variant="primary")
with gr.Column():
out_v = gr.Video(label="Result Video")
out_s = gr.Textbox(label="Status")
btn.click(process_video, [q, o, s, e, mute], [out_v, out_s])
if __name__ == "__main__":
demo.launch() |