James040 commited on
Commit
a07a00e
·
verified ·
1 Parent(s): 90ae7ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -37
app.py CHANGED
@@ -1,22 +1,14 @@
1
  import cv2
2
- import os
3
  import numpy as np
4
  import gradio as gr
5
- from moviepy import VideoFileClip
 
6
 
7
- # Robust MediaPipe Import
8
- try:
9
- import mediapipe as mp
10
- from mediapipe.python.solutions import pose as mp_pose
11
- from mediapipe.python.solutions import drawing_utils as mp_drawing
12
- print("MediaPipe Solutions loaded successfully!")
13
- except ImportError as e:
14
- print(f"Direct import failed, trying legacy: {e}")
15
- import mediapipe as mp
16
- mp_pose = mp.solutions.pose
17
- mp_drawing = mp.solutions.drawing_utils
18
 
19
- # Create "Meaty" drawing specs
20
  MEATY_CONNECTIONS = mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=10, circle_radius=5)
21
  MEATY_JOINTS = mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=12, circle_radius=15)
22
 
@@ -24,33 +16,31 @@ def extract_pose(video_path):
24
  if video_path is None:
25
  return None
26
 
27
- # 1. Load Video
 
 
 
28
  cap = cv2.VideoCapture(video_path)
29
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
30
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
31
  fps = cap.get(cv2.CAP_PROP_FPS)
32
 
33
- output_path = "stickman_output.mp4"
34
- temp_output = "temp_no_audio.mp4"
35
-
36
- # Define Video Writer
37
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
38
- out = cv2.VideoWriter(temp_output, fourcc, fps, (width, height))
39
 
40
- with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5, model_complexity=1) as pose:
 
41
  while cap.isOpened():
42
  ret, frame = cap.read()
43
  if not ret:
44
  break
45
 
46
- # Convert to RGB for MediaPipe
47
  rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
48
- results = pose.process(rgb_frame)
49
 
50
- # Create Black Canvas (The "Clear" Background)
51
  canvas = np.zeros((height, width, 3), dtype=np.uint8)
52
 
53
- # Draw Meaty Stickman
54
  if results.pose_landmarks:
55
  mp_drawing.draw_landmarks(
56
  canvas,
@@ -65,27 +55,36 @@ def extract_pose(video_path):
65
  cap.release()
66
  out.release()
67
 
68
- # 2. Merge Original Audio back using MoviePy v2.x syntax
69
  try:
70
- original_clip = VideoFileClip(video_path)
71
- stickman_clip = VideoFileClip(temp_output)
72
-
73
- # New MoviePy v2.x method: with_audio instead of set_audio
74
- final_video = stickman_clip.with_audio(original_clip.audio)
75
- final_video.write_videofile(output_path, codec="libx264", audio_codec="aac")
76
-
 
 
 
 
 
 
77
  return output_path
 
 
 
78
  except Exception as e:
79
- print(f"Audio merge failed: {e}")
80
- return temp_output # Fallback to silent video
81
 
82
- # Gradio UI
83
  interface = gr.Interface(
84
  fn=extract_pose,
85
  inputs=gr.Video(label="Upload Dancing Clip (15-30s)"),
86
  outputs=gr.Video(label="Meaty Stickman Output"),
87
  title="Pose-to-Stickman Extractor",
88
- description="Extracts high-thickness pose data for EbSynth & Motion Transfer."
89
  )
90
 
91
  if __name__ == "__main__":
 
1
  import cv2
 
2
  import numpy as np
3
  import gradio as gr
4
+ import subprocess
5
+ import os
6
 
7
+ # 1. Direct Imports (Bypasses the 'solutions' AttributeError bug)
8
+ from mediapipe.python.solutions import pose as mp_pose
9
+ from mediapipe.python.solutions import drawing_utils as mp_drawing
 
 
 
 
 
 
 
 
10
 
11
+ # 2. Meaty drawing specs for EbSynth tracking
12
  MEATY_CONNECTIONS = mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=10, circle_radius=5)
13
  MEATY_JOINTS = mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=12, circle_radius=15)
14
 
 
16
  if video_path is None:
17
  return None
18
 
19
+ output_path = "final_output.mp4"
20
+ temp_video = "temp_silent.mp4"
21
+
22
+ # Initialize Video Capture
23
  cap = cv2.VideoCapture(video_path)
24
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
25
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
26
  fps = cap.get(cv2.CAP_PROP_FPS)
27
 
 
 
 
 
28
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
29
+ out = cv2.VideoWriter(temp_video, fourcc, fps, (width, height))
30
 
31
+ # Process Video
32
+ with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5, model_complexity=1) as pose_tracker:
33
  while cap.isOpened():
34
  ret, frame = cap.read()
35
  if not ret:
36
  break
37
 
 
38
  rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
39
+ results = pose_tracker.process(rgb_frame)
40
 
41
+ # Pure Black Canvas
42
  canvas = np.zeros((height, width, 3), dtype=np.uint8)
43
 
 
44
  if results.pose_landmarks:
45
  mp_drawing.draw_landmarks(
46
  canvas,
 
55
  cap.release()
56
  out.release()
57
 
58
+ # 3. Native FFmpeg Audio Merge
59
  try:
60
+ # Command copies the silent stickman video and maps the original audio to it
61
+ command = [
62
+ "ffmpeg", "-y",
63
+ "-i", temp_video,
64
+ "-i", video_path,
65
+ "-c:v", "copy",
66
+ "-c:a", "aac",
67
+ "-map", "0:v:0",
68
+ "-map", "1:a:0?", # The '?' prevents a crash if the source video has no audio track
69
+ "-shortest",
70
+ output_path
71
+ ]
72
+ subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
73
  return output_path
74
+ except subprocess.CalledProcessError as e:
75
+ print("FFmpeg routing error, returning silent video.")
76
+ return temp_video
77
  except Exception as e:
78
+ print("General error:", str(e))
79
+ return temp_video
80
 
81
+ # 4. Gradio Interface
82
  interface = gr.Interface(
83
  fn=extract_pose,
84
  inputs=gr.Video(label="Upload Dancing Clip (15-30s)"),
85
  outputs=gr.Video(label="Meaty Stickman Output"),
86
  title="Pose-to-Stickman Extractor",
87
+ description="Extracts thick pose data on a solid black background for EbSynth motion tracking."
88
  )
89
 
90
  if __name__ == "__main__":