ノート

Gradioを使用したローカル深度ビデオコンバーターを構築する

フリーのプロンプト百科事典 Wikiprompt より

Larus Canus

2026年7月20日

Gradioを使用したローカル深度ビデオコンバーターを構築する GradioとDepth Anything V2を使用してローカルなDepthビデオ変換アプリケーションを作成するための詳細なプロンプト。クロスプラットフォームのアクセラレーションサポートと複数のカスタマイズオプションを備えています。

プロンプト内容保存

🌐
""" Depth Video Converter - Local Depth Estimation Video Tool Converts regular videos into grayscale depth videos using Depth Anything V2. Supports Windows (CUDA) and macOS (Apple Silicon / CPU). """ import os import sys import tempfile import subprocess import shutil import numpy as np import cv2 import torch import gradio as gr from PIL import Image from transformers import pipeline from transformers import AutoModelForDepthEstimation, AutoProcessor import ffmpeg import json import time from pathlib import Path # ============================================================ # Configuration & Constants # ============================================================ MODEL_IDS = { "v2-small": "depth-anything/Depth-Anything-V2-Small-hf", "v2-base": "depth-anything/Depth-Anything-V2-Base-hf", "v2-large": "depth-anything/Depth-Anything-V2-Large-hf", } SUPPORTED_INPUT_FORMATS = [".mp4", ".mov"] SUPPORTED_OUTPUT_FORMATS = [".mp4"] DEFAULT_OUTPUT_RESOLUTION = 720 DEFAULT_MODEL_SIZE = "v2-base" DEFAULT_TEMPORAL_SMOOTHING = 0.5 DEFAULT_INVERT = False DEFAULT_PRESERVE_AUDIO = True # ============================================================ # Device Detection # ============================================================ def detect_device(): """Detect the best available device for inference.""" if torch.cuda.is_available(): return "cuda" elif sys.platform == "darwin" and torch.backends.mps.is_available(): return "mps" else: return "cpu" def get_device_name(device): """Return a human-readable device name.""" if device == "cuda": return f"CUDA ({torch.cuda.get_device_name(0)})" elif device == "mps": return "Apple Silicon (MPS)" else: return "CPU" # ============================================================ # Depth Estimation Model # ============================================================ class DepthEstimator: """Wrapper for Depth Anything V2 model.""" def __init__(self, model_size="v2-base", device=None): self.device = device or detect_device() self.model_id = MODEL_IDS[model_size] self.pipe = None self.processor = None self.model = None self.load_model() def load_model(self): """Load the depth estimation model.""" print(f"Loading Depth Anything V2 model ({self.model_id}) on {get_device_name(self.device)}...") # Load processor and model self.processor = AutoProcessor.from_pretrained(self.model_id) self.model = AutoModelForDepthEstimation.from_pretrained(self.model_id) # Move model to device if self.device == "cuda": self.model = self.model.to("cuda") elif self.device == "mps": self.model = self.model.to("mps") self.model.eval() print("Model loaded successfully.") def estimate_depth(self, image): """ Estimate depth map for a single image. Returns a grayscale numpy array (0-255). """ # Convert BGR to RGB if len(image.shape) == 3 and image.shape[2] == 3: image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) else: image_rgb = image # Convert to PIL pil_image = Image.fromarray(image_rgb) # Process inputs = self.processor(images=pil_image, return_tensors="pt") # Move inputs to device if self.device == "cuda": inputs = {k: v.to("cuda") for k, v in inputs.items()} elif self.device == "mps": inputs = {k: v.to("mps") for k, v in inputs.items()} # Inference with torch.no_grad(): outputs = self.model(**inputs) predicted_depth = outputs.predicted_depth # Interpolate to original size prediction = torch.nn.functional.interpolate( predicted_depth.unsqueeze(1), size=pil_image.size[::-1], mode="bicubic", align_corners=False, ) # Convert to numpy and normalize depth = prediction.squeeze().cpu().numpy() # Normalize to 0-255 depth_min = depth.min() depth_max = depth.max() if depth_max - depth_min > 1e-6: depth_normalized = (depth - depth_min) / (depth_max - depth_min) else: depth_normalized = np.zeros_like(depth) depth_uint8 = (depth_normalized * 255).astype(np.uint8) return depth_uint8 # ============================================================ # Video Processing # ============================================================ class VideoProcessor: """Handles video frame extraction, processing, and reassembly.""" def __init__(self, depth_estimator, output_resolution=720, temporal_smoothing=0.5, invert=False): self.depth_estimator = depth_estimator self.output_resolution = output_resolution self.temporal_smoothing = temporal_smoothing self.invert = invert self.prev_depth = None def process_frame(self, frame): """Process a single frame and return the depth map.""" # Estimate depth depth = self.depth_estimator.estimate_depth(frame) # Apply temporal smoothing if self.prev_depth is not None and self.temporal_smoothing > 0: alpha = self.temporal_smoothing depth = (alpha * self.prev_depth + (1 - alpha) * depth).astype(np.uint8) self.prev_depth = depth # Invert if requested if self.invert: depth = 255 - depth # Resize to output resolution h, w = depth.shape target_h = self.output_resolution target_w = int(w * (target_h / h)) depth_resized = cv2.resize(depth, (target_w, target_h), interpolation=cv2.INTER_LINEAR) # Convert to BGR for video writing depth_bgr = cv2.cvtColor(depth_resized, cv2.COLOR_GRAY2BGR) return depth_bgr def process_video(self, input_path, output_path, preserve_audio=True): """Process an entire video file.""" # Open video cap = cv2.VideoCapture(input_path) if not cap.isOpened(): raise ValueError(f"Could not open video: {input_path}") # Get video properties fps = cap.get(cv2.CAP_PROP_FPS) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # Calculate output dimensions target_h = self.output_resolution target_w = int(width * (target_h / height)) # Create video writer fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(output_path, fourcc, fps, (target_w, target_h)) if not out.isOpened(): raise ValueError(f"Could not create output video: {output_path}") print(f"Processing video: {total_frames} frames at {fps} FPS") print(f"Output resolution: {target_w}x{target_h}") # Process frames frame_count = 0 start_time = time.time() while True: ret, frame = cap.read() if not ret: break # Process frame depth_frame = self.process_frame(frame) out.write(depth_frame) frame_count += 1 # Progress update if frame_count % 30 == 0 or frame_count == total_frames: elapsed = time.time() - start_time fps_processed = frame_count / elapsed if elapsed > 0 else 0 progress = frame_count / total_frames * 100 if total_frames > 0 else 0 print(f"Progress: {progress:.1f}% ({frame_count}/{total_frames}) - {fps_processed:.1f} FPS") # Cleanup cap.release() out.release() # Handle audio preservation if preserve_audio: self.preserve_audio(input_path, output_path) print(f"Video processing complete: {output_path}") return output_path def preserve_audio(self, input_path, output_path): """Copy audio from input to output using ffmpeg.""" temp_output = output_path + ".temp.mp4" try: # Use ffmpeg to copy audio cmd = [ "ffmpeg", "-y", "-i", output_path, "-i", input_path, "-map", "0:v:0", "-map", "1:a:0?", "-c:v", "copy", "-c:a", "aac", "-shortest", temp_output ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0 and os.path.exists(temp_output): os.replace(temp_output, output_path) print("Audio preserved successfully.") else: print("Warning: Could not preserve audio. Using video without audio.") if os.path.exists(temp_output): os.remove(temp_output) except Exception as e: print(f"Warning: Audio preservation failed: {e}") if os.path.exists(temp_output): os.remove(temp_output) # ============================================================ # Main Processing Function # ============================================================ def process_video_file(input_file, model_size, output_resolution, temporal_smoothing, invert, preserve_audio): """ Main processing function called by Gradio. """ try: # Validate input if input_file is None: return None, "Error: No input file provided." input_path = input_file.name if hasattr(input_file, 'name') else str(input_file) # Check file extension ext = os.path.splitext(input_path)[1].lower() if ext not in SUPPORTED_INPUT_FORMATS: return None, f"Error: Unsupported format {ext}. Please use MP4 or MOV." # Create output path output_dir = tempfile.mkdtemp(prefix="depth_video_") output_filename = f"depth_{os.path.splitext(os.path.basename(input_path))[0]}.mp4" output_path = os.path.join(output_dir, output_filename) # Initialize depth estimator depth_estimator = DepthEstimator(model_size=model_size) # Initialize video processor processor = VideoProcessor( depth_estimator=depth_estimator, output_resolution=output_resolution, temporal_smoothing=temporal_smoothing, invert=invert ) # Process video result_path = processor.process_video( input_path, output_path, preserve_audio=preserve_audio ) return result_path, f"Success! Depth video created: {os.path.basename(result_path)}" except Exception as e: import traceback traceback.print_exc() return None, f"Error: {str(e)}" # ============================================================ # Gradio Interface # ============================================================ def create_interface(): """Create the Gradio web interface.""" device = detect_device() device_name = get_device_name(device) with gr.Blocks(title="Depth Video Converter") as demo: gr.Markdown(""" # 🎥 Depth Video Converter Convert regular videos into grayscale depth videos using **Depth Anything V2**. Upload an MP4 or MOV file, configure the settings, and generate a depth video. """) with gr.Row(): with gr.Column(scale=1): # Input input_video = gr.Video( label="Input Video (MP4/MOV)", sources=["upload"], format="mp4" ) # Settings model_size = gr.Dropdown( choices=list(MODEL_IDS.keys()), value=DEFAULT_MODEL_SIZE, label="Model Size", info="Larger models are more accurate but slower" ) output_resolution = gr.Slider( minimum=240, maximum=1080, value=DEFAULT_OUTPUT_RESOLUTION, step=60, label="Output Resolution (height in pixels)" ) temporal_smoothing = gr.Slider( minimum=0.0, maximum=1.0, value=DEFAULT_TEMPORAL_SMOOTHING, step=0.1, label="Temporal Smoothing", info="Higher values reduce flicker but may cause lag" ) invert = gr.Checkbox( value=DEFAULT_INVERT, label="Invert Depth (white = far, black = near)" ) preserve_audio = gr.Checkbox( value=DEFAULT_PRESERVE_AUDIO, label="Preserve Original Audio" ) process_btn = gr.Button("🎬 Generate Depth Video", variant="primary") with gr.Column(scale=1): # Output output_video = gr.Video( label="Depth Video Output", interactive=False ) status = gr.Textbox( label="Status", interactive=False ) # Device info gr.Markdown(f"**Device:** {device_name}") # Event handlers process_btn.click( fn=process_video_file, inputs=[ input_video, model_size, output_resolution, temporal_smoothing, invert, preserve_audio ], outputs=[output_video, status] ) return demo # ============================================================ # Main Entry Point # ============================================================ if __name__ == "__main__": print("=" * 60) print("Depth Video Converter") print("=" * 60) # Check ffmpeg availability if shutil.which("ffmpeg") is None: print("Warning: ffmpeg not found in PATH. Audio preservation will be disabled.") # Detect device device = detect_device() print(f"Using device: {get_device_name(device)}") # Create and launch interface demo = create_interface() demo.launch( server_name="127.0.0.1", server_port=7860, share=False, inbrowser=True ) ``` ```text # requirements.txt # Core dependencies torch>=2.0.0 torchvision>=0.15.0 transformers>=4.36.0 gradio>=4.0.0 opencv-python>=4.8.0 numpy>=1.24.0 Pillow>=10.0.0 # Video processing ffmpeg-python>=0.2.0 # Optional: CUDA support on Windows # Uncomment the following line if you have NVIDIA GPU: # torch-cuda>=2.0.0 # Optional: Apple Silicon support on macOS # Uncomment the following line if you have Apple Silicon: # torch-mps>=2.0.0 ``` ```markdown # Depth Video Converter Convert regular videos into grayscale depth videos using **Depth Anything V2**. This tool runs locally on your machine and provides a simple web interface. ## Features - 🎥 **Video Input**: Supports MP4 and MOV formats - 🤖 **Depth Estimation**: Uses Depth Anything V2 (Small, Base, Large models) - 🚀 **Hardware Acceleration**: - NVIDIA CUDA on Windows - Apple Silicon (MPS) on macOS - CPU fallback - 🎛️ **Customizable Settings**: - Model size selection - Output resolution - Black/white inversion - Temporal smoothing to reduce flicker - Audio preservation - 📦 **Export**: Compatible MP4 output ## Installation ### Prerequisites - Python 3.9 or higher - [ffmpeg](https://ffmpeg.org/download.html) (for audio preservation) ### Windows ```bash # 1. Create virtual environment python -m venv venv venv\Scripts\activate # 2. Install PyTorch with CUDA support (if you have NVIDIA GPU) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 3. Install other dependencies pip install -r requirements.txt # 4. Run the application python depth_video_converter.py ``` ### macOS (Apple Silicon) ```bash # 1. Create virtual environment python3 -m venv venv source venv/bin/activate # 2. Install PyTorch with MPS support pip install torch torchvision # 3. Install other dependencies pip install -r requirements.txt # 4. Run the application python depth_video_converter.py ``` ### macOS (Intel) / Linux ```bash # 1. Create virtual environment python3 -m venv venv source venv/bin/activate # 2. Install PyTorch (CPU version) pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 3. Install other dependencies pip install -r requirements.txt # 4. Run the application python depth_video_converter.py ``` ## Usage 1. Run the application 2. Open your browser to `http://127.0.0.1:7860` 3. Upload an MP4 or MOV video 4. Configure settings: - **Model Size**: Small (fast), Base (balanced), Large (accurate) - **Output Resolution**: Height in pixels (240-1080) - **Temporal Smoothing**: 0-1, higher reduces flicker - **Invert Depth**: Swap black/white - **Preserve Audio**: Keep original audio track 5. Click "Generate Depth Video" 6. Download the result ## How It Works 1. **Frame Extraction**: Video is read frame by frame using OpenCV 2. **Depth Estimation**: Each frame is processed by Depth Anything V2 3. **Post-processing**: - Temporal smoothing reduces flicker between frames - Resolution adjustment to match output settings - Optional inversion 4. **Video Assembly**: Depth frames are written to a new MP4 5. **Audio Preservation**: Original audio is copied using ffmpeg ## Model Information | Model | Size | Speed | Accuracy | |-------|------|-------|----------| | v2-small | ~25MB | Fast | Good | | v2-base | ~90MB | Medium | Better | | v2-large | ~300MB | Slow | Best | ## Troubleshooting ### CUDA not detected on Windows - Ensure NVIDIA drivers are installed - Install PyTorch with CUDA: `pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118` ### MPS not detected on macOS - Ensure you have Apple Silicon (M1/M2/M3) - Update macOS to latest version - Install latest PyTorch ### ffmpeg not found - Download from [ffmpeg.org](https://ffmpeg.org/download.html) - Add to system PATH - Audio preservation will be disabled if ffmpeg is not available ### Out of memory - Use smaller model (v2-small) - Reduce output resolution - Process shorter videos ## License This project uses: - [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2) (Apache 2.0) - [Gradio](https://gradio.app/) (Apache 2.0) - [PyTorch](https://pytorch.org/) (BSD-style) ## Disclaimer This tool is for educational and creative purposes. Depth estimation results may vary depending on video content and quality.

ログインして完全なプロンプトを表示

次で続行:

ログインすると、次に同意したことになります: 利用規約 プライバシーポリシー

使い方

このプロンプトは coding 向けに設計されています。上の内容をコピーして、お好みの AI ツールに貼り付けてください。

最良の結果を得るには、プレースホルダー(角括弧や大文字で示された部分)を具体的な要件に置き換えてください。

参考資料

カテゴリ:coding| twitter| python| gradio

ノート