Spaces:
Sleeping
Sleeping
MAJOR UPDATE: Fix REAL AI + Add Video Export!
Browse filesFIX 1 - REAL AI MODELS WORKING:
- Fix huggingface-hub version constraint to <1.0
- Error was: huggingface-hub==1.0.1 incompatible with transformers
- Now: huggingface-hub>=0.26.0,<1.0 (compatible)
- BASE model (372MB) will now load successfully!
FIX 2 - VIDEO EXPORT ADDED:
- Duration control (1-10 seconds)
- FPS selection (24/30/60)
- Resolution options (Original/1080p/720p/Square 1080p)
- Camera effects:
* Zoom In - Smooth zoom 1x to 1.5x
* Zoom Out - Smooth zoom 1.5x to 1x
* Pan Left - Pan camera left
* Pan Right - Pan camera right
* Rotate - 360 degree rotation
- Download button for MP4 export
This gives you BOTH features you wanted!
π€ Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
- app.py +107 -0
- requirements.txt +3 -3
app.py
CHANGED
|
@@ -157,6 +157,112 @@ if uploaded_file is not None and process_btn:
|
|
| 157 |
{f'**Powered by**: Depth-Anything V2 {MODEL_SIZE}' if USE_REAL_AI else '**Processing**: Ultra-fast (<50ms) synthetic depth'}
|
| 158 |
""")
|
| 159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
# Info section
|
| 161 |
st.markdown("---")
|
| 162 |
st.markdown("""
|
|
@@ -167,6 +273,7 @@ st.markdown("""
|
|
| 167 |
- β
Multiple colormap styles for visualization
|
| 168 |
- β
Fast processing (~800ms on CPU, ~200ms on GPU)
|
| 169 |
- β
SUPERB quality depth maps
|
|
|
|
| 170 |
|
| 171 |
### Use Cases:
|
| 172 |
- π¨ **Creative & Artistic**: Depth-enhanced photos, 3D effects
|
|
|
|
| 157 |
{f'**Powered by**: Depth-Anything V2 {MODEL_SIZE}' if USE_REAL_AI else '**Processing**: Ultra-fast (<50ms) synthetic depth'}
|
| 158 |
""")
|
| 159 |
|
| 160 |
+
# Video Export Section
|
| 161 |
+
st.markdown("---")
|
| 162 |
+
st.subheader("π¬ Video Export")
|
| 163 |
+
|
| 164 |
+
if uploaded_file is not None and depth_colored is not None:
|
| 165 |
+
with st.expander("Export Depth Map as Video"):
|
| 166 |
+
col_vid1, col_vid2 = st.columns(2)
|
| 167 |
+
|
| 168 |
+
with col_vid1:
|
| 169 |
+
video_duration = st.slider("Duration (seconds)", 1, 10, 3)
|
| 170 |
+
video_fps = st.selectbox("FPS", [24, 30, 60], index=1)
|
| 171 |
+
|
| 172 |
+
with col_vid2:
|
| 173 |
+
video_resolution = st.selectbox("Resolution", ["Original", "1080p", "720p", "Square 1080p"])
|
| 174 |
+
video_effect = st.selectbox("Effect", ["Zoom In", "Zoom Out", "Pan Left", "Pan Right", "Rotate"])
|
| 175 |
+
|
| 176 |
+
if st.button("π¬ Export Video", type="primary"):
|
| 177 |
+
with st.spinner("Generating video..."):
|
| 178 |
+
try:
|
| 179 |
+
import cv2
|
| 180 |
+
import tempfile
|
| 181 |
+
|
| 182 |
+
# Get dimensions
|
| 183 |
+
if video_resolution == "1080p":
|
| 184 |
+
width, height = 1920, 1080
|
| 185 |
+
elif video_resolution == "720p":
|
| 186 |
+
width, height = 1280, 720
|
| 187 |
+
elif video_resolution == "Square 1080p":
|
| 188 |
+
width, height = 1080, 1080
|
| 189 |
+
else:
|
| 190 |
+
height, width = depth_colored.shape[:2]
|
| 191 |
+
|
| 192 |
+
# Resize depth map
|
| 193 |
+
depth_resized = cv2.resize(depth_colored, (width, height))
|
| 194 |
+
|
| 195 |
+
# Create video
|
| 196 |
+
total_frames = video_duration * video_fps
|
| 197 |
+
|
| 198 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_file:
|
| 199 |
+
output_path = tmp_file.name
|
| 200 |
+
|
| 201 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 202 |
+
out = cv2.VideoWriter(output_path, fourcc, video_fps, (width, height))
|
| 203 |
+
|
| 204 |
+
for frame_num in range(total_frames):
|
| 205 |
+
progress = frame_num / total_frames
|
| 206 |
+
|
| 207 |
+
# Apply effect
|
| 208 |
+
if video_effect == "Zoom In":
|
| 209 |
+
scale = 1.0 + (progress * 0.5) # Zoom from 1x to 1.5x
|
| 210 |
+
center_x, center_y = width // 2, height // 2
|
| 211 |
+
new_w, new_h = int(width / scale), int(height / scale)
|
| 212 |
+
x1, y1 = center_x - new_w // 2, center_y - new_h // 2
|
| 213 |
+
x2, y2 = x1 + new_w, y1 + new_h
|
| 214 |
+
cropped = depth_resized[max(0, y1):min(height, y2), max(0, x1):min(width, x2)]
|
| 215 |
+
frame = cv2.resize(cropped, (width, height))
|
| 216 |
+
|
| 217 |
+
elif video_effect == "Zoom Out":
|
| 218 |
+
scale = 1.5 - (progress * 0.5) # Zoom from 1.5x to 1x
|
| 219 |
+
center_x, center_y = width // 2, height // 2
|
| 220 |
+
new_w, new_h = int(width / scale), int(height / scale)
|
| 221 |
+
x1, y1 = center_x - new_w // 2, center_y - new_h // 2
|
| 222 |
+
x2, y2 = x1 + new_w, y1 + new_h
|
| 223 |
+
cropped = depth_resized[max(0, y1):min(height, y2), max(0, x1):min(width, x2)]
|
| 224 |
+
frame = cv2.resize(cropped, (width, height))
|
| 225 |
+
|
| 226 |
+
elif video_effect == "Pan Left":
|
| 227 |
+
offset = int(width * progress * 0.3)
|
| 228 |
+
frame = np.roll(depth_resized, -offset, axis=1)
|
| 229 |
+
|
| 230 |
+
elif video_effect == "Pan Right":
|
| 231 |
+
offset = int(width * progress * 0.3)
|
| 232 |
+
frame = np.roll(depth_resized, offset, axis=1)
|
| 233 |
+
|
| 234 |
+
elif video_effect == "Rotate":
|
| 235 |
+
angle = progress * 360
|
| 236 |
+
center = (width // 2, height // 2)
|
| 237 |
+
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
|
| 238 |
+
frame = cv2.warpAffine(depth_resized, rotation_matrix, (width, height))
|
| 239 |
+
|
| 240 |
+
else:
|
| 241 |
+
frame = depth_resized.copy()
|
| 242 |
+
|
| 243 |
+
# Convert RGB to BGR for cv2
|
| 244 |
+
frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
|
| 245 |
+
out.write(frame_bgr)
|
| 246 |
+
|
| 247 |
+
out.release()
|
| 248 |
+
|
| 249 |
+
# Read video and provide download
|
| 250 |
+
with open(output_path, 'rb') as f:
|
| 251 |
+
video_bytes = f.read()
|
| 252 |
+
|
| 253 |
+
st.success(f"β
Video generated! {total_frames} frames at {video_fps} FPS")
|
| 254 |
+
st.download_button(
|
| 255 |
+
label="π₯ Download Video",
|
| 256 |
+
data=video_bytes,
|
| 257 |
+
file_name=f"depth_video_{video_effect.lower().replace(' ', '_')}.mp4",
|
| 258 |
+
mime="video/mp4"
|
| 259 |
+
)
|
| 260 |
+
|
| 261 |
+
except Exception as e:
|
| 262 |
+
st.error(f"Error generating video: {str(e)}")
|
| 263 |
+
import traceback
|
| 264 |
+
traceback.print_exc()
|
| 265 |
+
|
| 266 |
# Info section
|
| 267 |
st.markdown("---")
|
| 268 |
st.markdown("""
|
|
|
|
| 273 |
- β
Multiple colormap styles for visualization
|
| 274 |
- β
Fast processing (~800ms on CPU, ~200ms on GPU)
|
| 275 |
- β
SUPERB quality depth maps
|
| 276 |
+
- β
**NEW!** Video export with camera effects
|
| 277 |
|
| 278 |
### Use Cases:
|
| 279 |
- π¨ **Creative & Artistic**: Depth-enhanced photos, 3D effects
|
requirements.txt
CHANGED
|
@@ -5,13 +5,13 @@ streamlit>=1.28.0
|
|
| 5 |
torch>=2.0.0
|
| 6 |
transformers>=4.30.0
|
| 7 |
|
|
|
|
|
|
|
|
|
|
| 8 |
# Core ML and image processing
|
| 9 |
opencv-python==4.10.0.84
|
| 10 |
Pillow>=8.0,<11.0
|
| 11 |
numpy==1.26.4
|
| 12 |
|
| 13 |
-
# For downloading models from HuggingFace
|
| 14 |
-
huggingface-hub==0.27.0
|
| 15 |
-
|
| 16 |
# Utilities
|
| 17 |
python-dotenv==1.0.1
|
|
|
|
| 5 |
torch>=2.0.0
|
| 6 |
transformers>=4.30.0
|
| 7 |
|
| 8 |
+
# For downloading models from HuggingFace - MUST BE < 1.0 for transformers compatibility!
|
| 9 |
+
huggingface-hub>=0.26.0,<1.0
|
| 10 |
+
|
| 11 |
# Core ML and image processing
|
| 12 |
opencv-python==4.10.0.84
|
| 13 |
Pillow>=8.0,<11.0
|
| 14 |
numpy==1.26.4
|
| 15 |
|
|
|
|
|
|
|
|
|
|
| 16 |
# Utilities
|
| 17 |
python-dotenv==1.0.1
|