> ## Documentation Index
> Fetch the complete documentation index at: https://docs.varg.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run an ffmpeg operation

> Media processing via ffmpeg. One endpoint, four operation modes selected
by the `model` field:

| Model | Operation | Fields |
|---|---|---|
| `rendi_ffmpeg` | Generic command | `command`, `input_files`, `output_files` |
| `rendi_ffmpeg_trim` | Trim | `url`, `start`, `end` or `duration`, `precise` |
| `rendi_ffmpeg_resize` | Resize | `url`, `width`/`height`, `fit` |
| `rendi_ffmpeg_slice` | Slice into segments | `video_url`, `every`/`at`/`count`/`ranges`, `codec`, `thumbnails` |

Generic commands use placeholder references, e.g.
`-i {{in_1}} -t 5 {{out_1}}` with `input_files` mapping `in_1` to a URL
and `output_files` mapping `out_1` to an output filename.




## OpenAPI

````yaml /openapi.yaml post /ffmpeg
openapi: 3.1.0
info:
  title: varg API
  version: 2.0.0
  description: |
    Unified REST API for AI media generation at `api.varg.ai/v2`.

    One API key, ~80 models across 8 providers, async jobs, stable output URLs
    on `s3.varg.ai`, files with lineage, and transparent credit billing
    (1 credit = 1 cent = $0.01).

    **The async job pattern:** every generation request returns `202 Accepted`
    with a job object (`status: queued`). Poll `GET /jobs/{id}` until the job
    reaches a terminal status (`completed`, `failed`, or `cancelled`), then read
    `output.outputs[0].url`. Alternatively, set `options.webhook_url` in the
    request to receive an HMAC-signed callback when the job finishes.
servers:
  - url: https://api.varg.ai/v2
security:
  - bearerAuth: []
tags:
  - name: Generation
    description: >-
      Create generation jobs (image, video, speech, music, transcription,
      ffmpeg, render, pipeline)
  - name: Tools
    description: Discover tools, their schemas, and call any tool generically
  - name: Jobs
    description: Poll and manage job lifecycle
  - name: Files
    description: Upload, import, probe, and manage files
  - name: Lineage
    description: Resolve which job produced a file
  - name: Pricing
    description: Estimate costs and browse the price catalog
  - name: Billing
    description: Balance, usage, and transaction history
  - name: Account
    description: Identity and API key management
paths:
  /ffmpeg:
    post:
      tags:
        - Generation
      summary: Run an ffmpeg operation
      description: >
        Media processing via ffmpeg. One endpoint, four operation modes selected

        by the `model` field:


        | Model | Operation | Fields |

        |---|---|---|

        | `rendi_ffmpeg` | Generic command | `command`, `input_files`,
        `output_files` |

        | `rendi_ffmpeg_trim` | Trim | `url`, `start`, `end` or `duration`,
        `precise` |

        | `rendi_ffmpeg_resize` | Resize | `url`, `width`/`height`, `fit` |

        | `rendi_ffmpeg_slice` | Slice into segments | `video_url`,
        `every`/`at`/`count`/`ranges`, `codec`, `thumbnails` |


        Generic commands use placeholder references, e.g.

        `-i {{in_1}} -t 5 {{out_1}}` with `input_files` mapping `in_1` to a URL

        and `output_files` mapping `out_1` to an output filename.
      operationId: runFfmpeg
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FfmpegRequest'
            examples:
              trim:
                summary: Trim a video
                value:
                  model: rendi_ffmpeg_trim
                  url: https://s3.varg.ai/files/acc_x/video.mp4
                  start: 2.5
                  duration: 5
                  precise: true
              resize:
                summary: Resize to 9:16
                value:
                  model: rendi_ffmpeg_resize
                  url: https://s3.varg.ai/files/acc_x/video.mp4
                  width: 1080
                  height: 1920
                  fit: cover
              slice:
                summary: Slice every 10 seconds
                value:
                  model: rendi_ffmpeg_slice
                  video_url: https://s3.varg.ai/files/acc_x/long.mp4
                  every: 10
                  codec: copy
                  thumbnails: true
              command:
                summary: Generic ffmpeg command
                value:
                  model: rendi_ffmpeg
                  command: '-i {{in_1}} -vf scale=1280:720 -c:a copy {{out_1}}'
                  input_files:
                    in_1: https://s3.varg.ai/files/acc_x/video.mp4
                  output_files:
                    out_1: resized.mp4
      responses:
        '200':
          $ref: '#/components/responses/JobReplay'
        '202':
          $ref: '#/components/responses/JobAccepted'
        '402':
          $ref: '#/components/responses/InsufficientBalance'
        '404':
          $ref: '#/components/responses/ModelNotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/NoPricing'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
      description: |
        Any unique string. Retrying a request with the same key returns the
        existing job (HTTP 200) instead of creating and charging a new one
        (HTTP 202).
  schemas:
    FfmpegRequest:
      oneOf:
        - title: Command
          type: object
          required:
            - model
            - command
            - input_files
            - output_files
          properties:
            model:
              type: string
              const: rendi_ffmpeg
            command:
              type: string
              description: ffmpeg args with `{{in_N}}` / `{{out_N}}` placeholders
            input_files:
              type: object
              additionalProperties:
                type: string
                format: uri
            output_files:
              oneOf:
                - type: object
                  additionalProperties:
                    type: string
                - type: string
                  const: OUTPUT_FOLDER
        - title: Trim
          type: object
          required:
            - model
            - url
            - start
          properties:
            model:
              type: string
              const: rendi_ffmpeg_trim
            url:
              type: string
              format: uri
            start:
              type: number
              minimum: 0
            end:
              type: number
            duration:
              type: number
            precise:
              type: boolean
              default: false
              description: Re-encode for frame-accurate cuts (slower)
        - title: Resize
          type: object
          required:
            - model
            - url
          properties:
            model:
              type: string
              const: rendi_ffmpeg_resize
            url:
              type: string
              format: uri
            width:
              type: integer
              minimum: 1
              maximum: 7680
            height:
              type: integer
              minimum: 1
              maximum: 4320
            fit:
              type: string
              enum:
                - contain
                - cover
                - stretch
              default: cover
        - title: Slice
          type: object
          required:
            - model
            - video_url
          properties:
            model:
              type: string
              const: rendi_ffmpeg_slice
            video_url:
              type: string
              format: uri
            every:
              type: number
              minimum: 0.1
              maximum: 3600
              description: Split every N seconds
            at:
              type: array
              items:
                type: number
              description: Split at these timestamps
            count:
              type: integer
              minimum: 2
              maximum: 1000
              description: Split into N equal segments
            ranges:
              type: array
              items:
                type: object
                properties:
                  start:
                    type: number
                  end:
                    type: number
            codec:
              type: string
              enum:
                - copy
                - reencode
              default: copy
            thumbnails:
              type: boolean
              default: true
    Job:
      type: object
      properties:
        id:
          type: string
          example: job_a1b2c3d4e5f6
        status:
          $ref: '#/components/schemas/JobStatus'
        tool:
          type: string
          example: image
        input:
          type: object
          description: The request body as submitted (model, prompt, ...)
        output:
          oneOf:
            - $ref: '#/components/schemas/JobOutput'
            - type: 'null'
        error:
          type:
            - object
            - 'null'
        progress_message:
          type:
            - string
            - 'null'
          example: stitching 3/8 (40%)
        progress:
          type:
            - number
            - 'null'
          description: Fraction 0..1
        progress_metadata:
          type:
            - object
            - 'null'
        estimated_duration_ms:
          type:
            - integer
            - 'null'
        estimated_cost_cents:
          type:
            - integer
            - 'null'
        actual_cost_cents:
          type:
            - integer
            - 'null'
        pricing:
          $ref: '#/components/schemas/JobPricing'
        provider:
          type:
            - string
            - 'null'
          example: fal
        provider_model:
          type:
            - string
            - 'null'
          example: fal:flux_schnell
        provider_status:
          type:
            - string
            - 'null'
          description: The provider's raw status string
        provider_job_id:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        started_at:
          type:
            - string
            - 'null'
          format: date-time
        completed_at:
          type:
            - string
            - 'null'
          format: date-time
        urls:
          type: object
          description: Lifecycle URLs (present on creation responses)
          properties:
            self:
              type: string
            status:
              type: string
            refresh:
              type: string
            cancel:
              type: string
            retry:
              type: string
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: model_not_found
            message:
              type: string
              example: 'Unknown model: flux-shnell'
            details: {}
    JobStatus:
      type: string
      enum:
        - queued
        - submitting
        - running
        - completed
        - failed
        - cancelled
      description: |
        Lifecycle is `queued` then `submitting` then `running`, ending in a
        terminal status (`completed`, `failed`, or `cancelled`).
    JobOutput:
      type: object
      description: Canonical output envelope. Present only when the job is completed.
      properties:
        version:
          type: string
          const: v1
        outputs:
          type: array
          items:
            type: object
            properties:
              url:
                type: string
                description: Stable varg-hosted URL (s3.varg.ai)
              file_id:
                type: string
                description: The file record for this output — use with /files and /lineage
              media_type:
                type: string
                example: video/mp4
              size_bytes:
                type: integer
              thumbnail_url:
                type:
                  - string
                  - 'null'
    JobPricing:
      type: object
      description: Structured pricing. 1 credit = 1 cent = $0.01.
      properties:
        estimated:
          type:
            - integer
            - 'null'
          description: Reserved at creation (cents)
        actual:
          type:
            - integer
            - 'null'
          description: Charged at completion (cents). 0 for cache hits.
        billing:
          type:
            - string
            - 'null'
        cached:
          type:
            - boolean
            - 'null'
          description: true when the result came from cache (actual = 0)
        billed_units:
          type:
            - object
            - 'null'
          example:
            images: 1
        pricing_id:
          type:
            - string
            - 'null'
          description: The pinned pricing rule this job was charged under
  responses:
    JobReplay:
      description: >-
        Idempotency replay — the existing job for this `Idempotency-Key` (no new
        charge).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Job'
    JobAccepted:
      description: Job created and queued. Poll `urls.self` until terminal.
      headers:
        X-RateLimit-Limit:
          schema:
            type: string
        X-RateLimit-Remaining:
          schema:
            type: string
        X-RateLimit-Reset:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Job'
          examples:
            queued:
              summary: Queued job
              value:
                id: job_a1b2c3d4e5f6
                status: queued
                tool: image
                input:
                  model: flux_schnell
                  prompt: a cat astronaut
                output: null
                error: null
                estimated_cost_cents: 4
                actual_cost_cents: null
                pricing:
                  estimated: 4
                  actual: null
                  billing: metered
                  cached: null
                  billed_units: null
                  pricing_id: ppr_abc123
                provider: fal
                provider_model: fal:flux_schnell
                created_at: '2026-07-01T10:00:00Z'
                urls:
                  self: https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6
                  status: https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/status
                  refresh: https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/refresh
                  cancel: https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/cancel
                  retry: https://api.varg.ai/v2/jobs/job_a1b2c3d4e5f6/retry
    InsufficientBalance:
      description: Account balance too low to reserve the estimated cost
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            insufficient:
              value:
                error:
                  code: insufficient_balance
                  message: Insufficient balance to run this job
    ModelNotFound:
      description: Unknown model or tool
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            model:
              value:
                error:
                  code: model_not_found
                  message: 'Unknown model: flux-shnell'
    ValidationError:
      description: Request body failed validation
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalid:
              value:
                error:
                  code: invalid_request
                  message: 'Body validation failed (text: Required)'
    RateLimited:
      description: Rate limit exceeded (sliding window per API key)
      headers:
        Retry-After:
          schema:
            type: string
        X-RateLimit-Limit:
          schema:
            type: string
        X-RateLimit-Remaining:
          schema:
            type: string
        X-RateLimit-Reset:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NoPricing:
      description: No active pricing rule for this model
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        varg API key (`varg_...`). Get one at [app.varg.ai](https://app.varg.ai)
        or run `bunx vargai login`. App sessions may alternatively send a
        Supabase JWT.

````