Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ __pycache__/
*$py.class
.pytest_cache/
..mypy_cache/
.ruff_cache/
.vscode/

# poetry
.venv
Expand All @@ -30,9 +32,15 @@ __pycache__/

# Virtual environment
.venv
.sampler
venv

.DS_Store
.AppleDouble
.LSOverride
._*

docs/
notebooks/
site/
assets/
138 changes: 138 additions & 0 deletions demo_mcp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
"""
Demo script to showcase the Video Navigation MCP Server.

This script demonstrates how to interact with the MCP server programmatically
and shows the key features: video loading, search capabilities, and sampling job generation.
"""

import asyncio
import json
from video_sampler.mcp_server.server import VideoNavigationMCPServer


async def demo_mcp_server():
"""Demonstrate the MCP server functionality."""
print("🎬 Video Navigation MCP Server Demo")
print("=" * 50)

# Create server instance
server = VideoNavigationMCPServer()

# Demo 1: Video sampling job tools
print("\n1. Video Sampling Job Generation")
print("-" * 30)

# Ask for Python code
result = await server._handle_video_sampling_job(
video_path="/path/to/sample_video.mp4",
sampling_method="hash",
output_format="python",
frame_interval=2.0,
hash_size=8
)
print("Generated Python Code:")
print(result[0].text)

print("\n" + "-" * 50)

# Ask for CLI command
result = await server._handle_video_sampling_job(
video_path="/path/to/sample_video.mp4",
sampling_method="grid",
output_format="cli",
buffer_size=15
)
print("Generated CLI Command:")
print(result[0].text)

# Demo 2: Load a mock video and search
print("\n\n2. Video Loading and Search Demo")
print("-" * 30)

# Simulate loading a video with subtitles
video_id = "demo_video"
server.video_database[video_id] = {
"id": video_id,
"title": "Demo Nature Documentary",
"path": "/demo/nature_video.mp4",
"type": "local",
"subtitles": """1
00:00:05,000 --> 00:00:08,000
Welcome to this amazing nature documentary

2
00:00:12,000 --> 00:00:15,000
Here we see a beautiful cat stalking its prey

3
00:00:18,000 --> 00:00:22,000
The feline moves with incredible grace and stealth

4
00:00:30,000 --> 00:00:33,000
Now we observe different wildlife in their habitat

5
00:00:45,000 --> 00:00:48,000
The cat pounces with lightning speed"""
}

print(f"✅ Loaded video: {server.video_database[video_id]['title']}")

# Demo search for keyword
print("\n🔍 Searching for 'cat' in loaded videos...")
results = await server._handle_search("cat")
for result in results:
print(f" 📍 {result.text}")

# Demo search with time filter
print("\n🔍 Searching for 'cat' after 20 seconds...")
results = await server._handle_search("cat", start=20.0)
for result in results:
print(f" 📍 {result.text}")

# Demo 3: Resources
print("\n\n3. Available Resources")
print("-" * 30)

# Show available resources
print("📚 Video resources available:")
for video_id, video_data in server.video_database.items():
print(f" 🎥 video://{video_id} - {video_data['title']}")
print(" 🖼️ imageset://all_frames - Collection of all video frames")

# Demo 4: Show no results case
print("\n\n4. Search with No Results")
print("-" * 30)

print("🔍 Searching for 'elephant' (should find no results)...")
results = await server._handle_search("elephant")
for result in results:
print(f" 📍 {result.text}")

# Demo 5: YouTube URL detection
print("\n\n5. YouTube URL Detection")
print("-" * 30)

test_urls = [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/dQw4w9WgXcQ",
"/local/path/video.mp4",
"https://example.com/video.mp4"
]

for url in test_urls:
is_yt = server._is_youtube_url(url)
print(f" {'✅' if is_yt else '❌'} {url} -> YouTube: {is_yt}")

print("\n" + "=" * 50)
print("✨ Demo completed! The MCP server is ready for integration.")
print("\nTo run the server:")
print(" python -m video_sampler.mcp_server.server")
print("\nOr via the command line:")
print(" video_sampler_mcp")


if __name__ == "__main__":
asyncio.run(demo_mcp_server())
37 changes: 37 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: "3.8"

services:
postgres:
image: pgvector/pgvector:pg15
environment:
POSTGRES_DB: video_cache
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data

app:
build:
context: .
dockerfile: ./docker/Dockerfile.mcp
environment:
POSTGRES_HOST: postgres
POSTGRES_DB: video_cache
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
PYTHONPATH: /app
DEVELOPMENT: "true"
volumes:
- ./videos:/app/videos
- ./video_sampler:/app/video_sampler
- ./configs:/app/configs
depends_on:
- postgres
command: python -m video_sampler_mcp
ports:
- "8000:8000"

volumes:
postgres_data:
16 changes: 16 additions & 0 deletions docker/Dockerfile.mcp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM python:3.11-slim

WORKDIR /app

# Install system deps
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*

# Install Python deps
COPY requirements.txt pyproject.toml ./
RUN pip install psycopg2-binary mcp yt-dlp

# Copy code
COPY . .

# Use the script entry point or direct module execution
CMD ["python", "-m", "video_sampler_mcp"]
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Source = "https://github.com/LemurPwned/video-sampler"

[project.scripts]
video_sampler = "video_sampler.__main__:main_loop"
video_sampler_mcp = "video_sampler.__main__:mcp_server"

[project.optional-dependencies]
clip = [
Expand All @@ -68,6 +69,10 @@ gpu = [
"PyNvVideoCodec >= 1.0.2"
]

mcp = [
"mcp >= 1.13.0",
]

all = [
"open_clip_torch >= 2.23.0",
"torch >= 2.1.0",
Expand Down
Loading
Loading