{
  "openapi": "3.1.0",
  "info": {
    "title": "FFMPEG API",
    "version": "1.0.0",
    "description": "FFmpeg-powered video and audio processing API.",
    "contact": {
      "url": "https://ffmpegapi.net/contact"
    }
  },
  "servers": [
    {
      "url": "https://ffmpegapi.net"
    }
  ],
  "paths": {
    "/api/merge_image_audio": {
      "post": {
        "operationId": "mergeImageAudio",
        "summary": "Create an MP4 video from an image and an audio track.",
        "description": "Combines a static image with an audio file. JSON requests use public URLs; multipart form requests can upload image and audio files.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "image",
                  "audio"
                ],
                "properties": {
                  "image": {
                    "type": "string",
                    "description": "Image URL for JSON requests, or image file in multipart form data."
                  },
                  "audio": {
                    "type": "string",
                    "description": "Audio URL for JSON requests, or audio file in multipart form data."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "image": "https://example.com/cover.jpg",
                "audio": "https://example.com/audio.mp3",
                "async": false
              }
            }
          }
        }
      }
    },
    "/api/merge_videos": {
      "post": {
        "operationId": "mergeVideos",
        "summary": "Concatenate videos into a single MP4.",
        "description": "Downloads one or more videos, normalizes them when needed, and concatenates them. Optional audio replacement, output dimensions, subtitle burn-in, and watermark overlay are supported.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_urls"
                ],
                "properties": {
                  "video_urls": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "Video URLs to merge. Use at least one URL."
                  },
                  "audio_url": {
                    "type": "string",
                    "description": "Optional replacement audio URL."
                  },
                  "dimensions": {
                    "type": "string",
                    "description": "Optional output dimensions such as 1920x1080."
                  },
                  "subtitle_url": {
                    "type": "string",
                    "description": "Optional ASS/SSA subtitle URL to burn into the merged video."
                  },
                  "watermark_url": {
                    "type": "string",
                    "description": "Optional watermark image URL."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "video_urls": [
                  "https://example.com/intro.mp4",
                  "https://example.com/main.mp4"
                ],
                "dimensions": "1920x1080"
              }
            }
          }
        }
      }
    },
    "/api/video_loop": {
      "post": {
        "operationId": "videoLoop",
        "summary": "Loop a video by count or until it matches an audio track.",
        "description": "Repeats one video a fixed number of times, or calculates the loop count needed to match a provided audio track. Optional watermark overlay is supported.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL to loop."
                  },
                  "number_of_loops": {
                    "type": "integer",
                    "description": "Positive number of times to repeat the video."
                  },
                  "audio_url": {
                    "type": "string",
                    "description": "Optional audio URL. Required if number_of_loops is omitted."
                  },
                  "watermark_url": {
                    "type": "string",
                    "description": "Optional watermark image URL."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/clip.mp4",
                "number_of_loops": 3
              }
            }
          }
        }
      }
    },
    "/api/picture_in_picture": {
      "post": {
        "operationId": "pictureInPicture",
        "summary": "Overlay one video on another.",
        "description": "Creates a picture-in-picture composition using a main video and an overlay video with configurable position, scale, and audio source.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "main_video_url",
                  "pip_video_url"
                ],
                "properties": {
                  "main_video_url": {
                    "type": "string",
                    "description": "Main/background video URL."
                  },
                  "pip_video_url": {
                    "type": "string",
                    "description": "Overlay/PiP video URL."
                  },
                  "position": {
                    "type": "string",
                    "description": "Overlay position. Common values: top-left, top-right, bottom-left, bottom-right, center."
                  },
                  "scale": {
                    "type": "string",
                    "description": "FFmpeg scale expression for the overlay."
                  },
                  "audio_option": {
                    "type": "string",
                    "description": "Audio source: video1, video2, or mute."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "main_video_url": "https://example.com/main.mp4",
                "pip_video_url": "https://example.com/overlay.mp4",
                "position": "top-right"
              }
            }
          }
        }
      }
    },
    "/api/add_watermark": {
      "post": {
        "operationId": "addWatermark",
        "summary": "Overlay a watermark image onto a video.",
        "description": "Adds a watermark image to a video with configurable placement and scale.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url",
                  "watermark_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "watermark_url": {
                    "type": "string",
                    "description": "Watermark image URL."
                  },
                  "position": {
                    "type": "string",
                    "description": "One of top-left, top-center, top-right, middle-left, middle, middle-right, bottom-left, bottom-center, bottom-right."
                  },
                  "scale": {
                    "type": "number",
                    "description": "Watermark width as a fraction of video width, from 0.05 to 1.0."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "watermark_url": "https://example.com/logo.png",
                "position": "bottom-right",
                "scale": 0.2
              }
            }
          }
        }
      }
    },
    "/api/add_subtitles": {
      "post": {
        "operationId": "addSubtitles",
        "summary": "Burn ASS subtitles into a video.",
        "description": "Downloads a video and an ASS/SSA subtitle file, then burns the subtitles into the output video.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url",
                  "subtitle_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "subtitle_url": {
                    "type": "string",
                    "description": "ASS/SSA subtitle file URL."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "subtitle_url": "https://example.com/subtitles.ass"
              }
            }
          }
        }
      }
    },
    "/api/split_audio": {
      "post": {
        "operationId": "splitAudio",
        "summary": "Split audio into equal parts.",
        "description": "Splits an audio file into a requested number of equal-duration parts.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "audio_url"
                ],
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "description": "Audio URL."
                  },
                  "parts": {
                    "type": "integer",
                    "description": "Number of equal parts, from 2 to 20."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "audio_url": "https://example.com/podcast.mp3",
                "parts": 3
              }
            }
          }
        }
      }
    },
    "/api/split_audio_segments": {
      "post": {
        "operationId": "splitAudioSegments",
        "summary": "Split audio into fixed-duration segments.",
        "description": "Creates audio segments of a specified length in seconds.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "audio_url"
                ],
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "description": "Audio URL."
                  },
                  "segment_duration": {
                    "type": "number",
                    "description": "Segment duration in seconds, from 1 to 3600."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "audio_url": "https://example.com/podcast.mp3",
                "segment_duration": 10
              }
            }
          }
        }
      }
    },
    "/api/split_audio_time": {
      "post": {
        "operationId": "splitAudioTime",
        "summary": "Extract one audio range by millisecond timestamps.",
        "description": "Returns the audio between start_time and end_time, both in milliseconds.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "audio_url",
                  "start_time",
                  "end_time"
                ],
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "description": "Audio URL."
                  },
                  "start_time": {
                    "type": "number",
                    "description": "Start time in milliseconds."
                  },
                  "end_time": {
                    "type": "number",
                    "description": "End time in milliseconds. Must be greater than start_time."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "audio_url": "https://example.com/audio.mp3",
                "start_time": 1000,
                "end_time": 11000
              }
            }
          }
        }
      }
    },
    "/api/trim_audio": {
      "post": {
        "operationId": "trimAudio",
        "summary": "Trim audio to a desired length.",
        "description": "Downloads an audio file and trims it to the requested duration, with optional fade-out.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "audio_url",
                  "desired_length"
                ],
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "description": "Audio URL."
                  },
                  "desired_length": {
                    "type": "number",
                    "description": "Output length in seconds."
                  },
                  "fade_duration": {
                    "type": "number",
                    "description": "Optional fade-out duration in seconds."
                  }
                }
              },
              "example": {
                "audio_url": "https://example.com/song.mp3",
                "desired_length": 30,
                "fade_duration": 2
              }
            }
          }
        }
      }
    },
    "/api/trim_video": {
      "post": {
        "operationId": "trimVideo",
        "summary": "Trim video by start and end timestamps.",
        "description": "Downloads a video and returns the segment between start_time and end_time in seconds.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url",
                  "start_time",
                  "end_time"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "start_time": {
                    "type": "number",
                    "description": "Start time in seconds."
                  },
                  "end_time": {
                    "type": "number",
                    "description": "End time in seconds. Must be greater than start_time."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "start_time": 5,
                "end_time": 20
              }
            }
          }
        }
      }
    },
    "/api/split_video": {
      "post": {
        "operationId": "splitVideo",
        "summary": "Split a video into two parts.",
        "description": "Splits a video at split_at_seconds. If omitted, the split point defaults to half of the video duration.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "split_at_seconds": {
                    "type": "number",
                    "description": "Split point in seconds."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "split_at_seconds": 12.5
              }
            }
          }
        }
      }
    },
    "/api/get_first_frame_image": {
      "post": {
        "operationId": "getFirstFrameImage",
        "summary": "Extract the first frame of a video as a JPEG.",
        "description": "Downloads a video and returns an image URL for the first frame.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4"
              }
            }
          }
        }
      }
    },
    "/api/get_last_frame_image": {
      "post": {
        "operationId": "getLastFrameImage",
        "summary": "Extract the last frame of a video as a JPEG.",
        "description": "Downloads a video and returns an image URL for the last frame.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4"
              }
            }
          }
        }
      }
    },
    "/api/convert_to_vertical": {
      "post": {
        "operationId": "convertToVertical",
        "summary": "Convert a horizontal video to vertical format.",
        "description": "Creates a mobile-oriented vertical output and can apply an optional watermark.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "watermark_url": {
                    "type": "string",
                    "description": "Optional watermark image URL."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/landscape.mp4",
                "watermark_url": "https://example.com/logo.png"
              }
            }
          }
        }
      }
    },
    "/api/convert_to_tiktok_portrait": {
      "post": {
        "operationId": "convertToTiktokPortrait",
        "summary": "Convert a video to full-bleed 9:16 TikTok-style portrait.",
        "description": "Crops and scales source video into 1080x1920 portrait format, with optional watermark and outro video.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "watermark_url": {
                    "type": "string",
                    "description": "Optional watermark image URL."
                  },
                  "outro_video_url": {
                    "type": "string",
                    "description": "Optional outro video URL to append."
                  },
                  "async": {
                    "type": "boolean",
                    "description": "Return a job_id immediately and process in the background."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/landscape.mp4",
                "outro_video_url": "https://example.com/outro.mp4"
              }
            }
          }
        }
      }
    },
    "/api/extract_audio_mp3": {
      "post": {
        "operationId": "extractAudioMp3",
        "summary": "Extract a video's audio track as MP3.",
        "description": "Downloads a video and returns an MP3 audio file.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "bitrate": {
                    "type": "string",
                    "description": "MP3 bitrate: 96k, 128k, 192k, 256k, or 320k."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "bitrate": "192k"
              }
            }
          }
        }
      }
    },
    "/api/convert_video_to_gif": {
      "post": {
        "operationId": "convertVideoToGif",
        "summary": "Encode a video as an animated GIF.",
        "description": "Downloads a video and creates a GIF. Optional chroma key transparency supports solid-color backgrounds such as green screen.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "transparent_background": {
                    "type": "boolean",
                    "description": "Apply chroma key transparency."
                  },
                  "chromakey_color": {
                    "type": "string",
                    "description": "Color to key out, such as 0x00FF00 or #00FF00."
                  },
                  "similarity": {
                    "type": "number",
                    "description": "Chroma key similarity from 0.01 to 1.0."
                  },
                  "blend": {
                    "type": "number",
                    "description": "Transparency edge softness from 0.0 to 1.0."
                  },
                  "fps": {
                    "type": "integer",
                    "description": "Output frame rate from 1 to 30."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/clip.mp4",
                "transparent_background": true,
                "chromakey_color": "0x00FF00",
                "fps": 10
              }
            }
          }
        }
      }
    },
    "/api/videos/add-tiktok-captions": {
      "post": {
        "operationId": "addTiktokCaptions",
        "summary": "Transcribe a video and render TikTok-style captions.",
        "description": "Extracts audio, transcribes it with word timestamps, and renders styled captions into a video. Also returns caption artifact URLs when available.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "subtitle_style": {
                    "type": "string",
                    "description": "plain-white, yellow-bg, pink-bg, blue-bg, or red-bg."
                  },
                  "language": {
                    "type": "string",
                    "description": "Language code or auto."
                  },
                  "aspect_ratio": {
                    "type": "string",
                    "description": "16:9, 9:16, 4:3, or 3:4."
                  },
                  "max_chars_per_line": {
                    "type": "integer",
                    "description": "Caption wrapping limit from 5 to 80."
                  },
                  "max_lines": {
                    "type": "integer",
                    "description": "Maximum caption lines from 1 to 4."
                  },
                  "position": {
                    "type": "string",
                    "description": "top, center, or bottom."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "subtitle_style": "yellow-bg",
                "position": "bottom"
              }
            }
          }
        }
      }
    },
    "/api/videos/add-text-overlay-captions": {
      "post": {
        "operationId": "addTextOverlayCaptions",
        "summary": "Render supplied text lines as timed caption overlays.",
        "description": "Displays user-provided text lines over a video, one line every duration_per_line seconds.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_url",
                  "text"
                ],
                "properties": {
                  "video_url": {
                    "type": "string",
                    "description": "Video URL."
                  },
                  "text": {
                    "type": "string",
                    "description": "One or more caption lines separated by newlines."
                  },
                  "subtitle_style": {
                    "type": "string",
                    "description": "plain-white, yellow-bg, pink-bg, blue-bg, or red-bg."
                  },
                  "aspect_ratio": {
                    "type": "string",
                    "description": "16:9, 9:16, 4:3, or 3:4."
                  },
                  "position": {
                    "type": "string",
                    "description": "top, center, or bottom."
                  },
                  "duration_per_line": {
                    "type": "integer",
                    "description": "Seconds per text line from 1 to 30."
                  }
                }
              },
              "example": {
                "video_url": "https://example.com/video.mp4",
                "text": "First line\nSecond line",
                "duration_per_line": 4
              }
            }
          }
        }
      }
    },
    "/api/youtube_to_mp4": {
      "post": {
        "operationId": "youtubeToMp4",
        "summary": "Return an MP4 download URL for a YouTube video.",
        "description": "Accepts a standard YouTube watch URL, youtu.be URL, Shorts URL, embed URL, or /v/ URL and returns a downloadable MP4 URL.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "youtube_url"
                ],
                "properties": {
                  "youtube_url": {
                    "type": "string",
                    "description": "Single YouTube video URL. Playlists are not supported."
                  }
                }
              },
              "example": {
                "youtube_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
              }
            }
          }
        }
      }
    },
    "/api/job/{job_id}/status": {
      "get": {
        "operationId": "getJobStatus",
        "summary": "Check asynchronous job status.",
        "description": "Returns pending, processing, completed, or failed status for a background job submitted with async=true.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "500": {
            "description": "Processing error"
          }
        },
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Async job ID."
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "ApiResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "download_url": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    }
  }
}