nazib61 commited on
Commit
efb68a6
Β·
verified Β·
1 Parent(s): 41f915d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -43
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import subprocess
3
  import os
4
  import uuid
 
5
 
6
  def initialize_env():
7
  if not os.path.exists("node_modules"):
@@ -9,86 +10,99 @@ def initialize_env():
9
 
10
  initialize_env()
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def process_video(query, orientation, start_time, end_time, progress=gr.Progress()):
13
  if not query:
14
  return None, "⚠️ Please enter a keyword."
15
 
16
- progress(0, desc="πŸ” Searching for High Quality Pins...")
17
  search_query = query if "video" in query.lower() else f"{query} video"
18
 
19
  try:
 
20
  result = subprocess.run(
21
  ["node", "scraper.js", search_query],
22
- capture_output=True, text=True, timeout=180
23
  )
24
 
25
- # Parse the custom output format: URL|WIDTH|HEIGHT
26
- raw_output = result.stdout.strip().split('\n')
27
- video_pool = []
28
- for line in raw_output:
29
- if '|' in line:
30
- parts = line.split('|')
31
- video_pool.append({"url": parts[0], "w": int(parts[1]), "h": int(parts[2])})
32
-
33
- if not video_pool:
34
- return None, "❌ No high-quality videos found."
35
 
36
- # Filter by orientation using Metadata (Faster than ffprobe!)
37
- selected_video = None
38
- for i, vid in enumerate(video_pool):
39
- progress((i+1)/len(video_pool), desc=f"Filtering for {orientation}...")
 
 
40
 
41
  if orientation == "Any":
42
- selected_video = vid
43
  break
44
- if orientation == "Portrait" and vid['h'] > vid['w']:
45
- selected_video = vid
 
 
46
  break
47
- if orientation == "Landscape" and vid['w'] > vid['h']:
48
- selected_video = vid
49
  break
 
50
 
51
- if not selected_video:
52
- return None, f"❌ Found {len(video_pool)} videos, but none were {orientation}."
53
 
54
- # 3. HIGH QUALITY TRIMMING
55
- progress(0.9, desc="πŸ’Ž Processing High Quality Output...")
56
- output_filename = f"hd_clip_{uuid.uuid4().hex[:8]}.mp4"
57
-
58
- # FFmpeg Pro Settings:
59
- # -crf 18: Visually lossless quality
60
- # -preset slow: Better compression/clarity
61
- # -c:v libx264: Industry standard HD codec
62
  ffmpeg_cmd = [
63
  "ffmpeg", "-ss", str(start_time), "-to", str(end_time),
64
- "-i", selected_video['url'],
65
- "-c:v", "libx264", "-crf", "18", "-preset", "slow",
66
- "-c:a", "aac", "-b:a", "192k", "-y", output_filename
67
  ]
68
 
69
  if end_time <= 0:
70
  ffmpeg_cmd.pop(3); ffmpeg_cmd.pop(3)
71
 
72
  subprocess.run(ffmpeg_cmd, check=True)
73
- return output_filename, f"βœ… HD Video Processed! (Res: {selected_video['w']}x{selected_video['h']})"
74
 
75
  except Exception as e:
76
- return None, f"❌ Error: {str(e)}"
77
 
78
- # UI remains same but works faster and better
79
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
80
- gr.Markdown("# πŸ’Ž Pinterest HD Search & Trim")
 
 
81
  with gr.Row():
82
  with gr.Column():
83
- query_input = gr.Textbox(label="Topic", placeholder="e.g. Minecraft Gameplay")
84
- filter_input = gr.Dropdown(choices=["Any", "Portrait", "Landscape"], value="Landscape", label="Orientation")
 
85
  with gr.Row():
86
  start_input = gr.Number(label="Start (sec)", value=0)
87
  end_input = gr.Number(label="End (sec, 0=full)", value=5)
88
- btn = gr.Button("πŸš€ Get HD Clip", variant="primary")
 
 
89
  with gr.Column():
90
- video_output = gr.Video(label="HD Result")
91
- status_output = gr.Textbox(label="Status")
92
 
93
  btn.click(process_video, [query_input, filter_input, start_input, end_input], [video_output, status_output])
94
 
 
2
  import subprocess
3
  import os
4
  import uuid
5
+ import json
6
 
7
  def initialize_env():
8
  if not os.path.exists("node_modules"):
 
10
 
11
  initialize_env()
12
 
13
+ def get_video_dimensions(url):
14
+ """Checks video dimensions using ffprobe"""
15
+ try:
16
+ cmd = [
17
+ "ffprobe", "-v", "error", "-select_streams", "v:0",
18
+ "-show_entries", "stream=width,height", "-of", "json", url
19
+ ]
20
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
21
+ data = json.loads(result.stdout)
22
+ width = data['streams'][0]['width']
23
+ height = data['streams'][0]['height']
24
+ return width, height
25
+ except:
26
+ return 0, 0
27
+
28
  def process_video(query, orientation, start_time, end_time, progress=gr.Progress()):
29
  if not query:
30
  return None, "⚠️ Please enter a keyword."
31
 
32
+ progress(0, desc="πŸ” Searching Pinterest...")
33
  search_query = query if "video" in query.lower() else f"{query} video"
34
 
35
  try:
36
+ # 1. Run Node Scraper (collects many links)
37
  result = subprocess.run(
38
  ["node", "scraper.js", search_query],
39
+ capture_output=True, text=True, timeout=180 # Increased timeout for deep search
40
  )
41
 
42
+ all_urls = [line.strip() for line in result.stdout.split('\n') if line.strip().startswith("http")]
43
+
44
+ if not all_urls:
45
+ return None, "❌ No videos found in the search results."
 
 
 
 
 
 
46
 
47
+ # 2. Loop through every found URL until the orientation matches
48
+ selected_url = None
49
+ total = len(all_urls)
50
+
51
+ for i, url in enumerate(all_urls):
52
+ progress((i+1)/total, desc=f"Checking video {i+1}/{total} for {orientation}...")
53
 
54
  if orientation == "Any":
55
+ selected_url = url
56
  break
57
+
58
+ w, h = get_video_dimensions(url)
59
+ if orientation == "Portrait" and h > w:
60
+ selected_url = url
61
  break
62
+ if orientation == "Landscape" and w > h:
63
+ selected_url = url
64
  break
65
+ # If no match, the loop continues to the next URL automatically
66
 
67
+ if not selected_url:
68
+ return None, f"❌ Searched {total} videos, but none were {orientation}. Pinterest is mostly Portrait content."
69
 
70
+ # 3. Trim and return the video
71
+ progress(0.9, desc="βœ‚οΈ Trimming video...")
72
+ output_filename = f"final_{uuid.uuid4().hex[:8]}.mp4"
 
 
 
 
 
73
  ffmpeg_cmd = [
74
  "ffmpeg", "-ss", str(start_time), "-to", str(end_time),
75
+ "-i", selected_url, "-c:v", "libx264", "-c:a", "aac", "-y", output_filename
 
 
76
  ]
77
 
78
  if end_time <= 0:
79
  ffmpeg_cmd.pop(3); ffmpeg_cmd.pop(3)
80
 
81
  subprocess.run(ffmpeg_cmd, check=True)
82
+ return output_filename, f"βœ… Success! Found {orientation} video after checking {i+1} results."
83
 
84
  except Exception as e:
85
+ return None, f"❌ System Error: {str(e)}"
86
 
87
+ # --- UI Layout ---
88
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
89
+ gr.Markdown("# πŸ“Œ Pinterest Deep Search & Filter")
90
+ gr.Markdown("This app will scroll and search deep into Pinterest until it finds the orientation you want.")
91
+
92
  with gr.Row():
93
  with gr.Column():
94
+ query_input = gr.Textbox(label="Topic", placeholder="e.g. Ocean Nature")
95
+ filter_input = gr.Dropdown(choices=["Any", "Portrait", "Landscape"], value="Landscape", label="Required Orientation")
96
+
97
  with gr.Row():
98
  start_input = gr.Number(label="Start (sec)", value=0)
99
  end_input = gr.Number(label="End (sec, 0=full)", value=5)
100
+
101
+ btn = gr.Button("πŸš€ Deep Search & Process", variant="primary")
102
+
103
  with gr.Column():
104
+ video_output = gr.Video(label="Trimmed Result")
105
+ status_output = gr.Textbox(label="Search Progress / Status")
106
 
107
  btn.click(process_video, [query_input, filter_input, start_input, end_input], [video_output, status_output])
108