{
  "openapi": "3.0.1",
  "info": {
    "title": "Video Frame Extractor: Frames, Keyframes & Scenes for AI Vision",
    "description": "Extract frames from video files for AI vision (GPT-4o, Claude, Gemini): every N seconds, N evenly spaced, scene-change keyframes or exact timestamps. JPG/PNG/WebP, base64 or URLs, contact sheet, timecodes. Video to images, $1.50 per 1,000 frames.",
    "version": "1.0",
    "x-build-id": "0E0z4WRYD0lao0O0S"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/terracotta_hauyne~video-frame-extractor-for-ai-vision/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-terracotta_hauyne-video-frame-extractor-for-ai-vision",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/terracotta_hauyne~video-frame-extractor-for-ai-vision/runs": {
      "post": {
        "operationId": "runs-sync-terracotta_hauyne-video-frame-extractor-for-ai-vision",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/terracotta_hauyne~video-frame-extractor-for-ai-vision/run-sync": {
      "post": {
        "operationId": "run-sync-terracotta_hauyne-video-frame-extractor-for-ai-vision",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "videoUrls": {
            "title": "Video URLs",
            "type": "array",
            "description": "Direct links to video files (.mp4, .webm, .mov, .mkv, .avi, .m4v, .ts). The link must open the file itself, without login. Page URLs of YouTube, TikTok, Instagram, Facebook, X, Vimeo and similar platforms are not supported: their terms forbid downloading.",
            "items": {
              "type": "string"
            }
          },
          "uploadedVideo": {
            "title": "Upload a video",
            "type": "string",
            "description": "Optional. Upload one video file here (it is stored in Apify and read like a URL). For several private files use the key-value store fields below."
          },
          "sourceKeyValueStoreId": {
            "title": "Key-value store ID or name",
            "type": "string",
            "description": "Optional. Key-value store that holds your video files, used with \"Record keys\". Leave empty to read the keys from this run's default store."
          },
          "sourceKeys": {
            "title": "Record keys",
            "type": "array",
            "description": "Keys of binary video records in the key-value store above. Each record is one video.",
            "items": {
              "type": "string"
            }
          },
          "mode": {
            "title": "What to extract",
            "enum": [
              "interval",
              "count",
              "scenes",
              "timestamps"
            ],
            "type": "string",
            "description": "interval: one frame every \"Seconds between frames\". count: \"Number of frames\" spread evenly (the middle of equal slices). scenes: the first frame plus a frame at each detected shot change (strongest first when over the cap). timestamps: the times listed in \"Timestamps\".",
            "default": "interval"
          },
          "intervalSeconds": {
            "title": "Seconds between frames",
            "minimum": 0.04,
            "maximum": 86400,
            "type": "number",
            "description": "Interval mode: 1 = one frame per second, 0.5 = two per second. Frames start at the start time.",
            "default": 10
          },
          "frameCount": {
            "title": "Number of frames",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Count mode: how many frames, evenly spaced. 8-20 is usually enough for an AI model to follow a video.",
            "default": 10
          },
          "timestamps": {
            "title": "Timestamps",
            "type": "array",
            "description": "Timestamps mode: seconds (90.5), clock time (1:30, 00:01:30.250) or 1m30s. You get the frame on screen at that time. Times beyond the video are skipped with a warning.",
            "items": {
              "type": "string"
            }
          },
          "sceneThreshold": {
            "title": "Scene threshold",
            "minimum": 0.01,
            "maximum": 0.99,
            "type": "number",
            "description": "Scenes mode: ffmpeg scene score (0-1) that counts as a cut. Lower finds more, subtler changes (0.2 sensitive, 0.4 only hard cuts). Each frame reports its score as \"sceneScore\".",
            "default": 0.3
          },
          "minSceneGapSeconds": {
            "title": "Minimum seconds between scenes",
            "minimum": 0,
            "maximum": 3600,
            "type": "number",
            "description": "Scenes mode: ignore cuts closer than this to a stronger cut (stops flashes and fast edits from flooding the result).",
            "default": 1
          },
          "includeFirstFrame": {
            "title": "Include the first frame",
            "type": "boolean",
            "description": "Scenes mode: also return the opening frame (sceneScore 0), so a video without any cut still gives one image.",
            "default": true
          },
          "fastSceneScan": {
            "title": "Fast scene scan",
            "type": "boolean",
            "description": "Scenes mode: look only at keyframes (I-frames). Several times faster on long or high-resolution videos, but cuts that do not fall on a keyframe are missed. Off = frame-exact detection.",
            "default": false
          },
          "startTime": {
            "title": "Start time",
            "type": "string",
            "description": "Optional. Ignore everything before this time (seconds, 1:30 or 1m30s). Applies to interval, count and scenes modes."
          },
          "endTime": {
            "title": "End time",
            "type": "string",
            "description": "Optional. Ignore everything after this time. Empty = to the end of the video."
          },
          "imageFormat": {
            "title": "Image format",
            "enum": [
              "jpg",
              "png",
              "webp"
            ],
            "type": "string",
            "description": "File format of the saved frames.",
            "default": "jpg"
          },
          "imageQuality": {
            "title": "Quality",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "JPG and WebP quality, 1-100. 80-90 is a good balance for AI vision. Ignored for PNG.",
            "default": 85
          },
          "maxWidth": {
            "title": "Max width (px)",
            "minimum": 0,
            "maximum": 8192,
            "type": "integer",
            "description": "Frames wider than this are scaled down, aspect ratio kept, never enlarged. 0 = keep the original size. 1280 is enough for vision models and keeps tokens and file sizes low.",
            "default": 1280
          },
          "maxHeight": {
            "title": "Max height (px)",
            "minimum": 0,
            "maximum": 8192,
            "type": "integer",
            "description": "Frames taller than this are scaled down. 0 = no limit.",
            "default": 0
          },
          "skipBlankFrames": {
            "title": "Skip black frames",
            "type": "boolean",
            "description": "If a chosen frame is black (fade, black intro) or pure white, step forward up to 2 x 0.5 s to a real picture. The reported timestamp is the frame you got.",
            "default": true
          },
          "contactSheet": {
            "title": "Contact sheet",
            "type": "boolean",
            "description": "Also save one grid image per video with all frames and their timecodes (up to 100). Free. Its link is in every frame item and in the run summary.",
            "default": true
          },
          "contactSheetColumns": {
            "title": "Contact sheet columns",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Thumbnails per row on the contact sheet.",
            "default": 5
          },
          "includeBase64": {
            "title": "Include base64 in the dataset",
            "type": "boolean",
            "description": "Add the image as base64 text (\"imageBase64\", with \"mimeType\") to each item, ready to send to a vision API. Makes items large; for big batches use \"imageUrl\" instead.",
            "default": false
          },
          "maxFramesPerVideo": {
            "title": "Max frames per video",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Hard cap per video in every mode. For scenes the strongest cuts are kept; for interval and timestamps the earliest frames are kept and a warning is added.",
            "default": 100
          },
          "maxTotalFrames": {
            "title": "Max frames per run",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Stop when this many frames have been returned in total. You can also set a maximum cost per run in Apify.",
            "default": 1000
          },
          "maxDurationMinutes": {
            "title": "Max video length (minutes)",
            "minimum": 1,
            "maximum": 480,
            "type": "integer",
            "description": "Videos (or the start/end range) longer than this fail with a clear message and are not charged. Use start and end time to process a part of a long video.",
            "default": 30
          },
          "maxVideoSizeMb": {
            "title": "Max video size (MB)",
            "minimum": 1,
            "maximum": 4000,
            "type": "integer",
            "description": "Larger videos are rejected (free). Frames are decoded locally, so the whole file is downloaded first.",
            "default": 500
          },
          "downloadTimeoutSecs": {
            "title": "Download timeout (seconds)",
            "minimum": 10,
            "maximum": 3600,
            "type": "integer",
            "description": "Give up on a video that has not downloaded in this time.",
            "default": 300
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}