Skip to main content
Glama

extract_frames

Extract frames from video files as sequential images, allowing control over frame rate, format, quality, and time segments for analysis or processing.

Instructions

Extract frames from a video as sequential image files

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputPathYesPath to the input video file
outputDirNoDirectory to save the extracted frames (default: 'output')
frameRateNoFrame extraction rate (e.g., '1' for every frame, '0.5' for every 2nd frame, '1/30' for 1 frame per 30 seconds)
formatNoOutput image format (jpg, png, etc., default: jpg)
qualityNoImage quality for jpg format (1-100, default: 95)
startTimeNoStart time to begin extraction (format: HH:MM:SS.mmm or seconds)
durationNoDuration to extract frames (format: HH:MM:SS.mmm or seconds)

Implementation Reference

  • The switch case in handleToolCall that implements the extract_frames tool. It validates input, constructs an FFmpeg command to extract frames at specified rate/format/quality, ensures output directory exists, runs the command, and returns success message with result.
    case "extract_frames": {
      const inputPath = validatePath(String(args?.inputPath), true);
      const outputDir = String(args?.outputDir || "output");
      const frameRate = String(args?.frameRate || "1");
      const format = String(args?.format || "jpg");
      const quality = Number(args?.quality || 95);
      const startTime = args?.startTime ? String(args?.startTime) : "";
      const duration = args?.duration ? String(args?.duration) : "";
      
      // Create output directory if it doesn't exist
      await ensureDirectoryExists(join(outputDir, "dummy.txt"));
      
      // Build the FFmpeg command
      let command = `-i "${inputPath}"`;
      
      // Add start time if provided
      if (startTime) {
        command += ` -ss ${startTime}`;
      }
      
      // Add duration if provided
      if (duration) {
        command += ` -t ${duration}`;
      }
      
      // Set frame extraction rate
      command += ` -vf "fps=${frameRate}"`;
      
      // Set quality based on format
      if (format.toLowerCase() === "jpg" || format.toLowerCase() === "jpeg") {
        // For JPEG, use a better quality setting (lower values = higher quality in FFmpeg's scale)
        // Convert 1-100 scale to FFmpeg's 1-31 scale (inverted, where 1 is best quality)
        const ffmpegQuality = Math.max(1, Math.min(31, Math.round(31 - ((quality / 100) * 30))));
        command += ` -q:v ${ffmpegQuality}`;
      } else if (format.toLowerCase() === "png") {
        // For PNG, use compression level (0-9, where 0 is no compression)
        const compressionLevel = Math.min(9, Math.max(0, Math.round(9 - ((quality / 100) * 9))));
        command += ` -compression_level ${compressionLevel}`;
      }
      
      // Set output pattern with 5-digit numbering
      const outputPattern = join(outputDir, `%05d.${format}`);
      command += ` "${outputPattern}" -y`;
      
      const result = await runFFmpegCommand(command);
      
      return {
        content: [{
          type: "text",
          text: `Frames extracted from video: ${inputPath} → ${outputDir}/*.${format}\n\n${result}`
        }]
      };
    }
  • The input schema and metadata definition for the 'extract_frames' tool within the toolDefinitions array.
    {
      name: "extract_frames",
      description: "Extract frames from a video as sequential image files",
      inputSchema: {
        type: "object",
        properties: {
          inputPath: {
            type: "string",
            description: "Path to the input video file"
          },
          outputDir: {
            type: "string",
            description: "Directory to save the extracted frames (default: 'output')"
          },
          frameRate: {
            type: "string",
            description: "Frame extraction rate (e.g., '1' for every frame, '0.5' for every 2nd frame, '1/30' for 1 frame per 30 seconds)"
          },
          format: {
            type: "string",
            description: "Output image format (jpg, png, etc., default: jpg)"
          },
          quality: {
            type: "number",
            description: "Image quality for jpg format (1-100, default: 95)"
          },
          startTime: {
            type: "string",
            description: "Start time to begin extraction (format: HH:MM:SS.mmm or seconds)"
          },
          duration: {
            type: "string",
            description: "Duration to extract frames (format: HH:MM:SS.mmm or seconds)"
          }
        },
        required: ["inputPath"]
      }
    }
  • src/index.ts:46-50 (registration)
    Registration of the list tools handler that exposes all tool definitions, including 'extract_frames', via toolDefinitions.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: toolDefinitions
      };
    });
  • src/index.ts:56-58 (registration)
    Registration of the call tool handler that dispatches to handleToolCall, which implements the 'extract_frames' logic.
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
      try {
        return await handleToolCall(request.params.name, request.params.arguments);
  • Imports of helper functions used in the extract_frames handler: validatePath and ensureDirectoryExists from file.ts, runFFmpegCommand from ffmpeg.ts.
    import { validatePath } from "../utils/file.js";
    import { getVideoInfo, runFFmpegCommand } from "../utils/ffmpeg.js";
    import { ensureDirectoryExists } from "../utils/file.js";
    import { join } from "path";
    
    /**
     * Handles all FFmpeg tool requests
     */
    export async function handleToolCall(toolName: string, args: any) {
      switch (toolName) {
        case "get_video_info": {
          const filePath = validatePath(String(args?.filePath), true);
          const info = await getVideoInfo(filePath);
          return {
            content: [{
              type: "text",
              text: info
            }]
          };
        }
    
        case "convert_video": {
          const inputPath = validatePath(String(args?.inputPath), true);

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/sworddut/mcp-ffmpeg-helper'

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