{
  "info": {
    "name": "FFmpeGo — FFmpeg API",
    "description": "Runnable requests for the FFmpeGo serverless FFmpeg API.\n\n**Setup**\n1. Create an API key at https://ffmpego.com/dashboard/keys.\n2. Open the collection variables and set `apiKey` to your `ffc_live_...` key.\n3. Send any request. `baseUrl` defaults to `https://ffmpego.com`.\n\nEvery successful request returns `X-Compute-Seconds`. Failed jobs are not billed. Binary responses are shown in the response body; use **Send and Download** to save the file.\n\nDocs: https://ffmpego.com/docs · OpenAPI: https://ffmpego.com/openapi.json",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "e6b6f2c8-6f0b-4a3e-9f2a-ff6d9e1c4b21"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "const key = pm.collectionVariables.get(\"apiKey\");",
          "if (!key || key === \"ffc_live_replace_me\") {",
          "  throw new Error(\"Set the `apiKey` collection variable to your ffc_live_ key (https://ffmpego.com/dashboard/keys).\");",
          "}"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://ffmpego.com",
      "type": "string"
    },
    {
      "key": "apiKey",
      "value": "ffc_live_replace_me",
      "type": "string"
    },
    {
      "key": "sampleVideo",
      "value": "https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4",
      "type": "string"
    },
    {
      "key": "sampleVideo2",
      "value": "https://cdn.pixabay.com/video/2025/06/24/287510_tiny.mp4",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Encode",
      "item": [
        {
          "name": "Transcode to MP4",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"Compute seconds are reported\", () => {",
                  "  pm.expect(pm.response.headers.has(\"X-Compute-Seconds\")).to.be.true;",
                  "  pm.expect(Number(pm.response.headers.get(\"X-Compute-Seconds\"))).to.be.at.least(1);",
                  "});",
                  "pm.test(\"Response is a video\", () => {",
                  "  pm.expect(pm.response.headers.get(\"Content-Type\") || \"\").to.include(\"video/mp4\");",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"inputs\": [{ \"url\": \"{{sampleVideo}}\" }],\n  \"args\": [\"-c:v\", \"libx264\", \"-preset\", \"veryfast\", \"-crf\", \"23\", \"-c:a\", \"aac\", \"-movflags\", \"+faststart\", \"-f\", \"mp4\"],\n  \"outputFilename\": \"out.mp4\",\n  \"outputContentType\": \"video/mp4\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/v2/run",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v2",
                "run"
              ]
            },
            "description": "Transcodes a public sample clip to H.264/AAC MP4. The response body is the file itself; use **Send and Download** to save `out.mp4`."
          },
          "response": []
        },
        {
          "name": "Video to GIF",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"Compute seconds are reported\", () => {",
                  "  pm.expect(pm.response.headers.has(\"X-Compute-Seconds\")).to.be.true;",
                  "});",
                  "pm.test(\"Response is a GIF\", () => {",
                  "  pm.expect(pm.response.headers.get(\"Content-Type\") || \"\").to.include(\"image/gif\");",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"inputs\": [{ \"url\": \"{{sampleVideo}}\" }],\n  \"args\": [\"-vf\", \"fps=10,scale=320:-1:flags=lanczos\", \"-c:v\", \"gif\"],\n  \"outputFilename\": \"output.gif\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/v2/run",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v2",
                "run"
              ]
            },
            "description": "Builds a 320 px wide, 10 fps GIF. The `Content-Type` is inferred from `outputFilename`, so no `outputContentType` is needed."
          },
          "response": []
        },
        {
          "name": "Concatenate two videos (filter_complex)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"Compute seconds are reported\", () => {",
                  "  pm.expect(pm.response.headers.has(\"X-Compute-Seconds\")).to.be.true;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"inputs\": [\n    { \"url\": \"{{sampleVideo2}}\", \"filename\": \"video1.mp4\" },\n    { \"url\": \"{{sampleVideo}}\", \"filename\": \"video2.mp4\" }\n  ],\n  \"args\": [\"-filter_complex\", \"[0:v][1:v]concat=n=2:v=1:a=0[outv]\", \"-map\", \"[outv]\"],\n  \"outputFilename\": \"concatenated.mp4\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/v2/run",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v2",
                "run"
              ]
            },
            "description": "Two inputs, a `filter_complex` concat graph, and one output. `inputs[i]` is FFmpeg input `i`, so `[0:v]` and `[1:v]` refer to the files in array order."
          },
          "response": []
        },
        {
          "name": "Upload result to a signed URL",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"Returns an upload receipt\", () => {",
                  "  pm.response.to.be.json;",
                  "  pm.expect(pm.response.json().uploaded).to.be.true;",
                  "});",
                  "pm.test(\"Compute seconds are reported\", () => {",
                  "  pm.expect(pm.response.headers.has(\"X-Compute-Seconds\")).to.be.true;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"inputs\": [{ \"url\": \"{{sampleVideo}}\" }],\n  \"args\": [\"-c:v\", \"libx264\", \"-f\", \"mp4\"],\n  \"outputFilename\": \"export.mp4\",\n  \"upload\": {\n    \"url\": \"https://your-bucket.example.com/upload/sign/export.mp4?token=...\",\n    \"method\": \"PUT\",\n    \"headers\": {\n      \"Content-Type\": \"video/mp4\"\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/v2/run",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v2",
                "run"
              ]
            },
            "description": "Replaces the placeholder `upload.url` with a one-shot signed PUT URL (S3 presigned, Supabase signed upload, or similar). The response is JSON metadata instead of video bytes. `upload.headers` must include `Content-Type`."
          },
          "response": [
            {
              "name": "Upload receipt",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"inputs\": [{ \"url\": \"https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4\" }],\n  \"args\": [\"-c:v\", \"libx264\", \"-f\", \"mp4\"],\n  \"outputFilename\": \"export.mp4\",\n  \"upload\": {\n    \"url\": \"https://your-bucket.example.com/upload/sign/export.mp4?token=...\",\n    \"method\": \"PUT\",\n    \"headers\": { \"Content-Type\": \"video/mp4\" }\n  }\n}"
                },
                "url": {
                  "raw": "https://ffmpego.com/v2/run",
                  "protocol": "https",
                  "host": [
                    "ffmpego",
                    "com"
                  ],
                  "path": [
                    "v2",
                    "run"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json; charset=utf-8"
                },
                {
                  "key": "X-Compute-Seconds",
                  "value": "3"
                }
              ],
              "body": "{\n  \"ok\": true,\n  \"uploaded\": true,\n  \"bytes\": 21375689,\n  \"contentType\": \"video/mp4\",\n  \"outputFilename\": \"export.mp4\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "YouTube",
      "item": [
        {
          "name": "Clip a YouTube video",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"200 OK\", () => pm.response.to.have.status(200));",
                  "pm.test(\"Compute seconds are reported\", () => {",
                  "  pm.expect(pm.response.headers.has(\"X-Compute-Seconds\")).to.be.true;",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://www.youtube.com/watch?v=VIDEO_ID\",\n  \"start\": \"1:30\",\n  \"end\": \"2:00\",\n  \"args\": [\"-c:v\", \"libx264\", \"-preset\", \"veryfast\", \"-crf\", \"24\", \"-c:a\", \"aac\", \"-vf\", \"scale=-2:720\", \"-f\", \"mp4\"],\n  \"outputFilename\": \"clip.mp4\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/v2/youtube-clip",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v2",
                "youtube-clip"
              ]
            },
            "description": "Downloads only 1:30–2:00 with yt-dlp, then encodes it to a 720p MP4. Replace `VIDEO_ID` with a public video. `X-Compute-Seconds` covers download plus encode.\n\n`502` means YouTube blocked the download (bot check, private, age-restricted, or timeout) or the upload was rejected. Those jobs are not billed."
          },
          "response": []
        }
      ]
    }
  ]
}
