---
url: /docs/tasks.md
description: >-
  Detailed FFmate task documentation: Understand the complete task lifecycle,
  statuses, and API usage for creating, monitoring, managing, and batching
  FFmpeg jobs
---

# Understanding Tasks in FFmate

A **task** in FFmate represents an `FFmpeg` command execution such as transcoding a video, extracting audio, or applying filters.

When you submit a task, FFmate triggers `FFmpeg` under the hood to perform the media processing. Tasks can be submitted on their own or grouped into `batches` to handle multiple files efficiently in one go.

Every task follows a structured **lifecycle**, progressing from submission to execution and ultimately reaching completion or failure.

Before diving into task execution, let's first go through the **lifecycle** of tasks and their corresponding **statuses** in FFmate.

| Status            | Description                                       |
|-------------------|---------------------------------------------------|
| `QUEUED`          | The task is waiting in the processing queue      |
| `PRE_PROCESSING`  | The task's pre-processing script is running      |
| `RUNNING`         | The main FFmpeg command is currently executing   |
| `POST_PROCESSING` | The task's post-processing script is running     |
| `DONE_SUCCESSFUL` | The task completed successfully                  |
| `DONE_ERROR`      | The task encountered an error and failed         |
| `DONE_CANCELED`   | The task was manually canceled before completion |

### Task Flow:

The diagram below shows how a task progresses through its lifecycle in FFmate

```mermaid
graph TD;
    queued -->|Starts processing| processing;
    processing -->|Finishes successfully| completed;
    processing -->|Fails| failed;
    queued -->|Canceled| canceled;
    processing -->|Canceled| canceled;

    classDef queued fill:#fdf6b2,stroke:#facc15,stroke-width:2px,color:#000;
    classDef processing fill:#bfdbfe,stroke:#3b82f6,stroke-width:2px,color:#000;
    classDef completed fill:#bbf7d0,stroke:#22c55e,stroke-width:2px,color:#000;
    classDef failed fill:#fecaca,stroke:#ef4444,stroke-width:2px,color:#000;
    classDef canceled fill:#e0e7ff,stroke:#6366f1,stroke-width:2px,color:#000;

    class queued queued;
    class processing processing;
    class completed completed;
    class failed failed;
    class canceled canceled;
```

Next, let's explore how to trigger and manage single tasks in FFmate

## Creating a Task

To create a task, send a `POST` request to the FFmate API:

```sh
curl -X POST http://localhost:3000/api/v1/tasks \
     -H "Content-Type: application/json" \
     -d '{
       "name": "Final Render for Summer Ad Campaign",
       "command": "-y -i ${INPUT_FILE} -c:v libx264 -preset fast -crf 23 -vf \"drawtext=text='${METADATA_project_name}':x=10:y=10:fontsize=24:fontcolor=white\" -c:a aac -b:a 128k ${OUTPUT_FILE}",
       "inputFile": "/media/source/client_project_final_v1.mov",
       "outputFile": "/media/deliverables/${METADATA_client_id}/final_ad_spot.mp4",
       "priority": 10,
       "metadata": {
         "project_name": "Summer Ad Campaign",
         "client_id": "CUST-12345",
         "editor": "jane.doe"
       },
       "preProcessing": {
         "scriptPath": "/opt/ffmate/scripts/verify_source.sh --input ${INPUT_FILE} --sidecar /var/tmp/ffmate_sidecar_${UUID}.json",
         "sidecarPath": "/var/tmp/ffmate_sidecar_${UUID}.json",
         "importSidecar": true
       },
       "postProcessing": {
         "scriptPath": "/opt/ffmate/scripts/upload_to_s3.sh --file ${OUTPUT_FILE} --client ${METADATA_client_id}"
       },
       "webhooks": [
         {
           "event": "task.updated",
           "url": "https://my-project-manager.com/api/hooks/ffmate-status"
         }
       ]
     }'
```

FFmate responds with a JSON object that contains the newly created task, including its `uuid`. This `uuid` is used to monitor the task’s progress in the next section. A `task.created` event is also fired via [Global webhooks](/docs/webhooks#task-events) and [Direct webhooks](/docs/webhooks#task-events).

### Task Properties

These are the properties that can be set when creating a task in FFmate:

* **`name`** *\[mandatory]* - A short, descriptive name to help identify and track the task in the web UI and API (e.g., "Final Render for Summer Ad Campaign"). Requests without a `name` are rejected with `422`.

* **`command`** — The custom command FFmate will use to run `FFmpeg`. This field is **mandatory** unless a `preset` is set. When a `preset` is set, the preset's command is always used and the task's `command` is ignored.

  ⚠️ **Important details about how `command` works:**

  * You don’t need to add `ffmpeg` at the start of the command. FFmate automatically prepends it. By default, FFmate uses the `ffmpeg` binary in your system’s `PATH`. If you want to use a different version, you can override the default with the `--ffmpeg <path>` [command-line flag](/docs/flags.md#server-command-flags).

  * FFmate also implicitly adds the `-stats_period 1` [option](https://ffmpeg.org/ffmpeg-all.html#Advanced-options) to every command, which limits FFmpeg’s progress output to one update per second.

    You can override this by explicitly adding your own `-stats_period x` to the command.

    * This setting directly affects:
      * how often `task.updated` [Global webhook](/docs/webhooks#task-events-1) and [Direct webhook](/docs/webhooks#task-events) are sent, and
      * how often the job dashboard refreshes progress updates.

    * [Wildcards](/docs/wildcards.md) like `${INPUT_FILE}` and `${OUTPUT_FILE}` can be used inside the command string. FFmate replaces them with the actual file paths when the task runs.

    * The `command` field also supports chaining several `FFmpeg` commands with `&&`, for example for **two-pass encoding**. Start every command after an `&&` with the `${FFMPEG}` wildcard (see [FFmpeg Path](/docs/wildcards.md#ffmpeg-path)).

  ::: tip Not sure which `FFmpeg` commands to use?

  * [OSTechNix – 20+ FFmpeg Commands For Beginners](https://ostechnix.com/20-ffmpeg-commands-beginners/)
  * [Abyssale – Top 20 best commands for FFmpeg](https://www.abyssale.com/blog/top-20-best-commands-for-ffmpeg)
  * [VideoProc – 31 Must-Haves FFmpeg Commands for Beginners](https://www.videoproc.com/resource/ffmpeg-commands.htm)
  * [GorillaSun – A Simple Guide to FFMPEG](https://www.gorillasun.de/blog/a-simple-guide-to-ffmpeg/)
  * [Bannerbear – Top 10 FFmpeg Command Options You Need to Know](https://www.bannerbear.com/blog/ffmpeg-101-top-10-command-options-you-need-to-know-with-examples/)
  * Ask ChatGPT
    :::

* **`inputFile`** *\[optional]* – The path to the input media file that will be processed.

* **`outputFile`** *\[optional]* – The path where the transcoded file should be saved. If the specified directory does not exist, FFmate will **create it automatically**.

::: tip Handling Input and Output Files

* The **`inputFile`** and **`outputFile`** properties are **optional** and should only be used if your command includes the placeholders `${INPUT_FILE}` and `${OUTPUT_FILE}`.

* FFmate **automatically replaces** these placeholders with the actual file paths during execution.

* If your command **directly specifies input and output paths**, you do **not** need to provide these properties separately.
  :::

* **`priority`** *\[optional]* – Sets the task's priority in the processing queue. Higher numbers mean higher priority — for example, a task with priority `100` will be processed before one with `10`. Tasks with the same priority run in the order they were created.

* **`preset`** - The UUID of a pre-configured [Preset](/docs/presets.md) to use for this task. This field is **mandatory** unless a `command` is set. See [Using a Preset](#using-a-preset) for which settings the task takes from the preset.

* **`labels`** *\[optional]* – Up to 5 labels, each 1 to 32 characters long. Only an FFmate instance with at least one matching label picks up the task. A task without labels runs on any FFmate instance. Labels can use `*` as a wildcard, for example `gpu-*`. See [`--labels`](/docs/flags.md#server-command-flags).

* **`retries`** *\[optional]* – How many times FFmate retries the task if it fails (`DONE_ERROR`). Each retry starts 3 seconds after the failure and puts the task back into `QUEUED`. The response field `retried` shows how many retries have run so far. Canceled tasks are not retried. Default: `0`.

* **`preProcessing`** *\[optional]* – Defines a [Pre-Processing Script](/docs/pre-post-prcessing.md) to run before the task starts. Useful for preparing files, validating input, or setting up the environment.
  * **`scriptPath`**: The full path to the script or executable to run.
  * **`sidecarPath`**: The full path to the JSON file that contains all task data.
  * **`importSidecar`**: Defines if the task will [re-import the sidecar](/docs/pre-post-prcessing.md#importing-a-task-s-sidecar) JSON after the pre-processing script finishes.

* **`postProcessing`** *\[optional]* – Defines a [Post-Processing Script](/docs/pre-post-prcessing.md) to run after the task completes. Useful for cleanup, moving output files, or triggering follow-up actions.
  * **`scriptPath`**: The full path to the script or executable to run.
  * **`sidecarPath`**: The full path to the JSON file that contains all task data.

* **`webhooks`** *\[optional]* – Direct webhook targets tied only to this task, for example to notify a project management tool whenever the task's status changes. Each entry needs an `event` and a `url`. Only `task.created`, `task.updated` and `task.deleted` are sent for direct task webhooks.

* **`metadata`** *\[optional]* — Any JSON object you want to attach to the task. Common uses include adding context, referencing source files, or integrating with external systems.

::: details **Example:** {open}

A sample `metadata` object containing useful context about the source file, provided as key-value pairs:

```json
"metadata": {
  "original_filename": "interview_session_03_cam_A.mxf",
  "project_code": "PROJ-SUMMER2025",
  "editor_notes": "Needs color correction pass after this transcode."
}
```

:::

This is a powerful feature for:

##### Example 1:

1. Your upstream system (CMS/PAM/DAM/MAM/workflow manager) creates a task in FFmate and includes its own identifiers in `metadata` (e.g., `assetId`, `jobId`).
2. FFmate queues the task, then starts processing it.
3. When the task finishes, FFmate sends a `task.updated` webhook whose `status` is `DONE_SUCCESSFUL`, `DONE_ERROR` or `DONE_CANCELED`.
4. The original `metadata` you sent is returned in the webhook payload, so your system can correlate it back to the `assetId` / `jobId` that originated the task.

##### Example 2:

1. A file is dropped into a watchfolder.
2. FFmate creates a task and adds **watchfolder file metadata** to the task’s `metadata` JSON object.
3. In the task, use the **Task Metadata** wildcard `${METADATA_<json-path>}` to read those values, for example, to recreate the input folder structure in your `outputFile`.

```json
"outputFile": "/volumes/ffmate/processed/${METADATA_ffmate.watchfolder.relativeDir}/${INPUT_FILE_BASENAME}.mp4"
```

### Using a Preset

When a task sets a `preset`, FFmate fills in the task from the preset as follows:

| Setting | Result |
|---|---|
| `command` | Always taken from the preset. The task's own `command` is ignored. |
| `inputFile`, `name`, `metadata` | Always taken from the task. |
| `outputFile`, `priority`, `preProcessing`, `postProcessing` | Taken from the preset only if the task doesn't set them. |
| `labels`, `retries` | The task inherits them from the preset only if it doesn't set them. |
| `webhooks` | Preset and task webhooks are combined. Only `task.*` events are kept. |

## Monitoring a Task

After submitting a task, you can check its current status by sending a `GET` request to the FFmate API:

```sh
curl -X GET 'http://localhost:3000/api/v1/tasks/{taskId}'
```

Replace `{taskId}` with the actual task UUID returned in the response when the task was created.

FFmate responds with a JSON object containing the full details of the task.

💡 Tip: You can also check the status of each task directly in the FFmate Web UI [FFmate Web UI](/docs/web-ui.md#monitoring-tasks)

## Monitoring All Tasks

FFmate lets you retrieve a list of all tasks, no matter their current state—queued, processing, completed, or failed.

To get a list of all tasks, send a `GET` request to the FFmate API:

```sh
curl -X GET 'http://localhost:3000/api/v1/tasks?page=0&perPage=100'
```

FFmate returns a JSON array containing all configured tasks. The `X-Total` response header provides the total number of tasks.

**Query Parameters:**

* **`page`** *\[optional]* – Specifies which page of results to retrieve. Default: `0`.
* **`perPage`** *\[optional]* – Defines how many tasks should be included in each page. Default: `100`.
* **`status`** *\[optional]* – Only returns tasks with this status, e.g. `?status=DONE_ERROR`. Use one of the statuses from the [table above](#understanding-tasks-in-ffmate).

💡 Tip: You can also check the status of all tasks: queued, processing, completed, or failed directly in the [FFmate Web UI](/docs/web-ui.md#monitoring-tasks)

## Canceling a Task

FFmate lets you to cancel a task that is currently **queued** or **processing**. Once canceled, the task will not be executed or will be stopped if already in progress.

To cancel a task, send a `PATCH` request to the FFmate API by including the task's `taskID` in the path:

```sh
curl -X PATCH 'http://localhost:3000/api/v1/tasks/{taskId}/cancel'
```

FFmate responds with a JSON object containing the updated details of the task. The task's status will be changed to `DONE_CANCELED`, and the progress will be set to 100. A `task.updated` event is also fired via [Global webhook](/docs/webhooks#task-events-1) and [Direct webhook](/docs/webhooks#task-events), with `status` set to `DONE_CANCELED`. There is no separate cancel event. If this was the last unfinished task of a batch, `batch.finished` is fired too.

If `FFmpeg` is already running, FFmate stops it. A [pre- or post-processing script](/docs/pre-post-prcessing.md) that is already running isn't stopped. It runs to the end, and the task stays `DONE_CANCELED`.

💡 Tip: You can also cancel a running task directly from the [FFmate Web UI](/docs/web-ui.md#canceling-tasks) with a single click—no API call needed.

## Restarting a Task

If a task has failed or been canceled, FFmate allows you to restart it without needing to resubmit the job manually.

To restart a task, send a `PATCH` request to the FFmate API by including the task's `ID` in the path:

```sh
curl -X PATCH 'http://localhost:3000/api/v1/tasks/{taskId}/restart'
```

FFmate responds with a JSON object containing the updated details of the task. The task's `status` will be reset to `QUEUED`, `progress` to `0`, `error` cleared, `startedAt`/`finishedAt` timestamps reset, and `retried` set back to `0`. The task will then be re-added to the processing queue according to its priority.

> \[!Note]
>
> * Restarting a task will **re-run the exact same command** using the original input and output paths.
> * If the task was previously processing, it will start from the beginning.

Once restarted, the task will move back into the **queued** state and follow the standard [task lifecycle](#task-flow). A `task.updated` event is also fired via [Global webhook](/docs/webhooks#task-events-1) and [Direct webhook](/docs/webhooks#task-events), with `status` set to `QUEUED`.

💡 Tip: Need to rerun a task? You can restart it directly in the [FFmate Web UI](/docs/web-ui.md#restarting-tasks)

## Deleting a Task

Once a task is completed, canceled, or no longer needed, you can **permanently remove** it from FFmate.

To delete a task, send a `DELETE` request to the FFmate API by including the task's `ID` in the path:

```sh
curl -X DELETE 'http://localhost:3000/api/v1/tasks/{taskId}'
```

FFmate responds with a `204` No Content status. The task will be removed from the system. A `task.deleted` event is also fired via [Global webhook](/docs/webhooks#task-events-1) and [Direct webhook](/docs/webhooks#task-events).

::: warning Important

* Deleting a task **removes the database entry** from FFmate but **does not** delete the input or output files.
* Deleting a task doesn't stop it. To remove a running task, cancel it first and then delete it.
  :::

💡 Tip: Tasks can also be deleted from the [FFmate Web UI](/docs/web-ui.md#deleting-tasks)

## Submitting Multiple Tasks as a Batch

FFmate allows you to submit multiple transcoding tasks in a single request, referred to as a `batch`. This is ideal when processing a set of files—whether they use the same settings or different ones—as it simplifies submission and keeps related tasks grouped together.

Each batch is automatically assigned a unique `batch ID`, making it easy to monitor, manage, and reference the entire group of tasks as a single unit. While a batch groups multiple task submissions together, each task within it remains fully independent.

Every task in the batch is submitted as a standalone task in FFmate. This means:

* Each task follows its own lifecycle (`Queued`, `Running`, `Done`).
* Each is executed independently by `ffmpeg`, based on its own command or preset.
* Each task maintains its own progress, status, and error reporting.
* A task's success or failure does not affect others in the same batch.

::: info
FFmate processes batch tasks concurrently (up to the `max-concurrent-tasks` limit) or sequentially, based on priority and queue order.
:::

### How to Submit a Batch of Tasks

You submit a batch by sending a `POST` request to the `/api/v1/batches` endpoint.

The request body must be a **JSON object** with a single key, `tasks`, which contains an array of standard task objects (the same object you'd use for creating a single task via [/api/v1/tasks](#creating-a-task).

To submit multiple tasks as a batch, send a `POST` request to the FFmate API:

```bash
curl -X POST http://localhost:3000/api/v1/batches \
     -H "Content-Type: application/json" \
     -d '{
       "tasks": [
         {
           "name": "Convert Episode 1 to WebM",
           "inputFile": "/mnt/source_videos/seriesA/episode_01.mov",
           "preset": "uuid-of-webm-720p-preset",
           "priority": 20
         },
         {
           "name": "Convert Episode 2 to WebM",
           "inputFile": "/mnt/source_videos/seriesA/episode_02.mov",
           "preset": "uuid-of-webm-720p-preset",
           "priority": 20
         },
         {
           "name": "Extract Thumbnail for Promo Image",
           "command": "-i ${INPUT_FILE} -frames:v 1 -q:v 2 ${OUTPUT_FILE}",
           "inputFile": "/mnt/source_videos/seriesA/promo_material.mp4",
           "outputFile": "/mnt/output_images/promo_thumb.jpg",
           "priority": 50
         }
       ]
     }'
```

The server will respond with a **JSON object** containing the unique `uuid` of the batch and a `tasks` array with the full details of each newly created task.

```json{2}
{
"uuid": "c4e8f12a-3b7d-4c9f-a1e8-5d0f2b3c4a9e",
"tasks": [
  {
    "uuid": "task-uuid-1",
    "batch": "c4e8f12a-3b7d-4c9f-a1e8-5d0f2b3c4a9e",
    "name": "Convert Episode 1 to WebM",
    "status": "QUEUED",
    // ... other task details
  },
  {
    "uuid": "task-uuid-2",
    "batch": "c4e8f12a-3b7d-4c9f-a1e8-5d0f2b3c4a9e",
    "name": "Convert Episode 2 to WebM",
    "status": "QUEUED",
    // ... other task details
  }
]
}
```

A `batch.created` event is fired when the batch is submitted, and a `batch.finished` event is fired once the last task in the batch is complete. [See batch webhook events](/docs/webhooks#batch-events)

### Managing and Monitoring Batches

While FFmate treats each task in a batch individually for processing, the `batch ID` allows you to group and monitor them as a unit.

**Listing Tasks by Batch ID**

You can retrieve all tasks that belong to a specific batch by sending a `GET` request with the batch's `uuid`.

```sh
curl -X GET 'http://localhost:3000/api/v1/batches/{batch_uuid}?page=0&perPage=10'
```

FFmate returns a **JSON object** containing the batch `uuid` and a paginated `tasks` array. The `X-Total` response header provides the total number of tasks in the batch.

**Query Parameters:**

* **`page`** *\[optional]* – Specifies which page of results to retrieve. Default: `0`.
* **`perPage`** *\[optional]* – Defines how many tasks should be included in each page. Default: `100`.

::: tip 💡 Webhook Notifications for Batches

**Webhooks Aren’t Just for single Tasks — Use Them to Track Batches Too**

* **`batch.created`** – Triggered once when a batch of tasks is successfully submitted. The payload includes an array of the created task objects.

* **`batch.finished`** – Triggered when all tasks in the batch have finished processing (either successfully, with errors, or canceled).

  The payload is the task that finished **last**, not a summary of the batch. To get the final status of every task, call [`GET /api/v1/batches/{batch_uuid}`](#managing-and-monitoring-batches) with the `batch` value from that task.

:::

### Common Use Cases for Batch Submission

* **Bulk Transcoding** – Convert an entire folder of videos to a new format or resolution in one go.

* **Multi-Renditions** – Generate multiple versions of the same source file (e.g., different bitrates or resolutions). Each rendition is submitted as an individual task within the batch.

* **Sequential Asset Processing** – Submit tasks that represent different steps in a media pipeline (e.g., clean audio, transcode video, apply watermark). While FFmate handles each task independently based on queue rules, you can still track them together as part of a single batch. While FFmate processes them based on queue rules, you can monitor them as a batch.
