Skip to main content
Glama
bitscorp-mcp

MCP FFmpeg Video Processor

by bitscorp-mcp

resize-video

Resize videos to standard resolutions like 360p, 480p, 720p, or 1080p for compatibility across devices and platforms.

Instructions

Resize a video to one or more standard resolutions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
videoPathYesPath to the video file to resize
resolutionsYesResolutions to convert the video to
outputDirNoOptional directory to save the output files (defaults to a temporary directory)

Implementation Reference

  • The core handler function that implements the resize-video tool logic. It resolves paths, checks existence and permissions, requests user permission, runs FFmpeg scale commands for each specified resolution, and returns formatted results or errors.
    async ({ videoPath, resolutions, outputDir }) => { try { // Resolve the absolute path const absVideoPath = path.resolve(videoPath); // Check if file exists try { await fs.access(absVideoPath); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Video file not found at ${absVideoPath}` }] }; } // Determine output directory let outputDirectory = outputDir ? path.resolve(outputDir) : await ensureDirectoriesExist(); // Check if output directory exists and is writable try { await fs.access(outputDirectory, fs.constants.W_OK); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Output directory ${outputDirectory} does not exist or is not writable` }] }; } // Format command for permission request const resolutionsStr = resolutions.join(', '); const permissionMessage = `Resize video ${path.basename(absVideoPath)} to ${resolutionsStr}`; // Ask for permission const permitted = await askPermission(permissionMessage); if (!permitted) { return { isError: true, content: [{ type: "text" as const, text: "Permission denied by user" }] }; } // Get video filename without extension const videoFilename = path.basename(absVideoPath, path.extname(absVideoPath)); // Define the type for our results type ResizeResult = { resolution: "360p" | "480p" | "720p" | "1080p"; outputPath: string; success: boolean; error?: string; }; // Process each resolution const results: ResizeResult[] = []; for (const resolution of resolutions) { const { width, height } = RESOLUTIONS[resolution as keyof typeof RESOLUTIONS]; const outputFilename = `${videoFilename}_${resolution}${path.extname(absVideoPath)}`; const outputPath = path.join(outputDirectory, outputFilename); // Build FFmpeg command const command = `ffmpeg -i "${absVideoPath}" -vf "scale=${width}:${height}" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k "${outputPath}"`; try { // Execute FFmpeg command const { stdout, stderr } = await execAsync(command); results.push({ resolution, outputPath, success: true }); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); results.push({ resolution, outputPath, success: false, error: errorMessage }); } } // Format results const successCount = results.filter(r => r.success).length; const failCount = results.length - successCount; let resultText = `Processed ${results.length} resolutions (${successCount} successful, ${failCount} failed)\n\n`; results.forEach(result => { if (result.success) { resultText += `✅ ${result.resolution}: ${result.outputPath}\n`; } else { resultText += `❌ ${result.resolution}: Failed - ${result.error}\n`; } }); return { content: [{ type: "text" as const, text: resultText }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: "text" as const, text: `Error resizing video: ${errorMessage}` }] }; } }
  • Zod input schema defining parameters for the resize-video tool: videoPath (required string), resolutions (array of specific enums), outputDir (optional string).
    { videoPath: z.string().describe("Path to the video file to resize"), resolutions: z.array(z.enum(["360p", "480p", "720p", "1080p"])).describe("Resolutions to convert the video to"), outputDir: z.string().optional().describe("Optional directory to save the output files (defaults to a temporary directory)") },
  • Registration of the resize-video tool on the MCP server using server.tool(), providing name, description, input schema, and handler function.
    server.tool( "resize-video", "Resize a video to one or more standard resolutions", { videoPath: z.string().describe("Path to the video file to resize"), resolutions: z.array(z.enum(["360p", "480p", "720p", "1080p"])).describe("Resolutions to convert the video to"), outputDir: z.string().optional().describe("Optional directory to save the output files (defaults to a temporary directory)") }, async ({ videoPath, resolutions, outputDir }) => { try { // Resolve the absolute path const absVideoPath = path.resolve(videoPath); // Check if file exists try { await fs.access(absVideoPath); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Video file not found at ${absVideoPath}` }] }; } // Determine output directory let outputDirectory = outputDir ? path.resolve(outputDir) : await ensureDirectoriesExist(); // Check if output directory exists and is writable try { await fs.access(outputDirectory, fs.constants.W_OK); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Output directory ${outputDirectory} does not exist or is not writable` }] }; } // Format command for permission request const resolutionsStr = resolutions.join(', '); const permissionMessage = `Resize video ${path.basename(absVideoPath)} to ${resolutionsStr}`; // Ask for permission const permitted = await askPermission(permissionMessage); if (!permitted) { return { isError: true, content: [{ type: "text" as const, text: "Permission denied by user" }] }; } // Get video filename without extension const videoFilename = path.basename(absVideoPath, path.extname(absVideoPath)); // Define the type for our results type ResizeResult = { resolution: "360p" | "480p" | "720p" | "1080p"; outputPath: string; success: boolean; error?: string; }; // Process each resolution const results: ResizeResult[] = []; for (const resolution of resolutions) { const { width, height } = RESOLUTIONS[resolution as keyof typeof RESOLUTIONS]; const outputFilename = `${videoFilename}_${resolution}${path.extname(absVideoPath)}`; const outputPath = path.join(outputDirectory, outputFilename); // Build FFmpeg command const command = `ffmpeg -i "${absVideoPath}" -vf "scale=${width}:${height}" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k "${outputPath}"`; try { // Execute FFmpeg command const { stdout, stderr } = await execAsync(command); results.push({ resolution, outputPath, success: true }); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); results.push({ resolution, outputPath, success: false, error: errorMessage }); } } // Format results const successCount = results.filter(r => r.success).length; const failCount = results.length - successCount; let resultText = `Processed ${results.length} resolutions (${successCount} successful, ${failCount} failed)\n\n`; results.forEach(result => { if (result.success) { resultText += `✅ ${result.resolution}: ${result.outputPath}\n`; } else { resultText += `❌ ${result.resolution}: Failed - ${result.error}\n`; } }); return { content: [{ type: "text" as const, text: resultText }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: "text" as const, text: `Error resizing video: ${errorMessage}` }] }; } } );
  • Helper constant mapping resolution names to width/height dimensions, used exclusively by the resize-video tool handler.
    const RESOLUTIONS = { "360p": { width: 640, height: 360 }, "480p": { width: 854, height: 480 }, "720p": { width: 1280, height: 720 }, "1080p": { width: 1920, height: 1080 } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bitscorp-mcp/mcp-ffmpeg'

If you have feedback or need assistance with the MCP directory API, please join our Discord server