
VibeStudio
STDIOHeadless video editing server for AI assistants using FFmpeg with MCP integration.
Headless video editing server for AI assistants using FFmpeg with MCP integration.
VibeStudio is a high-performance, headless video editing server designed for AI assistants. Built entirely in Bash and based on the Model Context Protocol (MCP), it delivers advanced FFmpeg functionality with zero runtime dependencies.
💡 Note: Heads up! Make sure your volume’s on
https://github.com/user-attachments/assets/7fe093ff-0abf-43af-b2fa-34a64ebe1fe8
It exposes powerful media editing tools—video, audio, and more—as lightweight, local shell commands. This makes it ideal for AI agents needing reliable, fast, and traceable tool-based workflows.
Bash shell (version 4.0+)
jq for JSON processing
# macOS brew install jq # Ubuntu/Debian sudo apt-get install jq # CentOS/RHEL sudo yum install jq
FFmpeg with common codecs
# macOS brew install ffmpeg # Ubuntu/Debian sudo apt-get install ffmpeg # CentOS/RHEL sudo yum install ffmpeg
Clone the repository
git clone https://github.com/wizenheimer/vibestudio.git cd vibestudio
Make scripts executable
chmod +x ffmpegserver.sh mcpserver_core.sh
Get detailed information about a media file.
{ "input_file": "path/to/media.mp4" }
Convert video to different format or codec.
{ "input_file": "input.avi", "output_file": "output.mp4", "codec": "h264" // optional }
Extract audio track from video.
{ "input_file": "video.mp4", "output_file": "audio.mp3", "audio_format": "mp3" // optional, default: mp3 }
Trim video or audio to specified duration.
{ "input_file": "input.mp4", "output_file": "output.mp4", "start_time": "00:01:30", "duration": "00:00:30" }
Concatenate multiple videos.
{ "input_files": ["video1.mp4", "video2.mp4", "video3.mp4"], "output_file": "merged.mp4" }
Burn subtitles into video.
{ "input_file": "video.mp4", "subtitle_file": "subtitles.srt", "output_file": "video_with_subs.mp4" }
Change video dimensions.
{ "input_file": "input.mp4", "output_file": "output.mp4", "width": 1280, "height": 720 }
Extract frames as images.
{ "input_file": "video.mp4", "output_pattern": "frame_%04d.png", "fps": "1", // optional, default: 1 "start_time": "00:00:10", // optional "duration": "00:00:05" // optional }
Create video from image sequence.
{ "input_pattern": "frame_%04d.png", "output_file": "video.mp4", "fps": "30", // optional, default: 30 "duration": "10" // optional }
Apply FFmpeg filters.
{ "input_file": "input.mp4", "output_file": "output.mp4", "filter": "hflip,blur=5" }
Create thumbnail from video.
{ "input_file": "video.mp4", "output_file": "thumbnail.jpg", "time": "00:00:05" // optional, default: 00:00:01 }
Convert audio format.
{ "input_file": "input.wav", "output_file": "output.mp3", "audio_format": "mp3", "bitrate": "320k" // optional, default: 192k }
Normalize audio volume.
{ "input_file": "input.mp3", "output_file": "normalized.mp3" }
Update VS Code settings.json
{ "mcp": { "servers": { "vibestudio": { "type": "stdio", "command": "/absolute/path/to/vibestudio-mcp/ffmpegserver.sh", "args": [], "env": {} } } } }
Use with GitHub Copilot Chat
/mcp vibestudio get_media_info {"input_file": "video.mp4"}
/mcp vibestudio convert_video {"input_file": "input.avi", "output_file": "output.mp4"}
# Convert AVI to MP4 and resize to 720p echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "convert_video", "arguments": {"input_file": "movie.avi", "output_file": "movie_temp.mp4"}}, "id": 1}' | ./ffmpegserver.sh echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "resize_video", "arguments": {"input_file": "movie_temp.mp4", "output_file": "movie_720p.mp4", "width": 1280, "height": 720}}, "id": 2}' | ./ffmpegserver.sh
# Extract audio from video and normalize volume echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "extract_audio", "arguments": {"input_file": "video.mp4", "output_file": "audio_raw.mp3"}}, "id": 1}' | ./ffmpegserver.sh echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "normalize_audio", "arguments": {"input_file": "audio_raw.mp3", "output_file": "audio_normalized.mp3"}}, "id": 2}' | ./ffmpegserver.sh
# Extract frames and create animated sequence echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "extract_frames", "arguments": {"input_file": "video.mp4", "output_pattern": "frame_%04d.png", "fps": "10", "start_time": "00:00:05", "duration": "00:00:03"}}, "id": 1}' | ./ffmpegserver.sh
Here are some useful filters for the apply_video_filter
tool:
"blur=10"
(value: 0-100)"unsharp=5:5:1.0"
"hflip"
"vflip"
"transpose=1"
"transpose=2,transpose=2"
"colorchannelmixer=.3:.4:.3:0:.3:.4:.3:0:.3:.4:.3"
"eq=brightness=0.1"
(-1.0 to 1.0)"eq=contrast=1.5"
(0.0 to 2.0)"fade=in:0:30"
(fade in over 30 frames)"setpts=0.5*PTS"
"setpts=2.0*PTS"
"mcpserver_core.sh: No such file or directory"
curl -O https://raw.githubusercontent.com/wizenheimer/vibestudio/main/mcpserver_core.sh
"jq: command not found"
brew install jq
sudo apt-get install jq
"ffmpeg: command not found"
brew install ffmpeg
sudo apt-get install ffmpeg
Permission denied errors
chmod +x ffmpegserver.sh mcpserver_core.sh
JSON parsing errors
tail -f logs/ffmpegserver.log
echo '{"your": "json"}' | jq .
Enable verbose logging by modifying the log level in ffmpegserver.sh or checking the full logs:
# Watch logs in real-time tail -f logs/ffmpegserver.log # Check last 50 log entries tail -n 50 logs/ffmpegserver.log
Run these tests to ensure VibeStudio is properly installed:
# Check if jq is installed jq --version # Expected: jq-1.6 or higher # Check if FFmpeg is installed ffmpeg -version # Expected: ffmpeg version details # Check if mcpserver_core.sh exists ls -la mcpserver_core.sh # Expected: File should exist with execute permissions
# Test server initialization echo '{"jsonrpc": "2.0", "method": "initialize", "params": {"clientInfo": {"name": "test"}}, "id": 1}' | ./ffmpegserver.sh | jq # Expected: JSON response with serverInfo and capabilities
# List all available tools echo '{"jsonrpc": "2.0", "method": "tools/list", "id": 2}' | ./ffmpegserver.sh | jq # Expected: JSON response with array of 14 tools
# First, create a test video file ffmpeg -f lavfi -i testsrc=duration=1:size=320x240:rate=30 -f lavfi -i sine=frequency=1000:duration=1 test_video.mp4 # Test get_media_info tool echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_media_info", "arguments": {"input_file": "test_video.mp4"}}, "id": 3}' | ./ffmpegserver.sh # Expected: JSON response with media information (duration, codecs, resolution)
# Test with non-existent file echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_media_info", "arguments": {"input_file": "non_existent.mp4"}}, "id": 4}' | ./ffmpegserver.sh # Expected: JSON error response with "File not found" message # Test with invalid method echo '{"jsonrpc": "2.0", "method": "invalid_method", "id": 5}' | ./ffmpegserver.sh # Expected: JSON error response with code -32601
# Check if logging is working tail -n 20 logs/ffmpegserver.log # Expected: Log entries for all the above test commands
# Create a simple test video and process it ffmpeg -f lavfi -i testsrc=duration=3:size=640x480:rate=30 -f lavfi -i sine=frequency=1000:duration=3 test_source.mp4 # Extract a 1-second clip echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "trim_media", "arguments": {"input_file": "test_source.mp4", "output_file": "test_trimmed.mp4", "start_time": "00:00:01", "duration": "00:00:01"}}, "id": 6}' | ./ffmpegserver.sh # Check if output was created ls -la test_trimmed.mp4 # Expected: File should exist with size > 0 # Clean up test files rm -f test_video.mp4 test_source.mp4 test_trimmed.mp4
Your VibeStudio installation should have this structure:
vibestudio-mcp/
├── mcpserver_core.sh # Core MCP server (from MCP Bash SDK)
├── ffmpegserver.sh # VibeStudio main script
├── assets/
│ ├── ffmpegserver_config.json
│ └── ffmpegserver_tools.json
└── logs/
└── ffmpegserver.log # Created automatically
VibeStudio welcomes contributions! Please feel free to submit issues and enhancement requests.
This project is licensed under the MIT License, following the original MCP Server Bash SDK.