Skip to content

Convert, package & upload with Trapper-Tools

At a glance

Ingest a real camera-trap dataset end-to-end — from raw SD-card files to a populated Classification Project — using trapper-tools.

  • Time: ~20 minutes plus upload time (scales with data volume)
  • Who: anyone ingesting field data, especially large batches
  • Prerequisites: see the checklist below

Full CLI reference lives in trapper-tools itself

This page covers the workflow; for the complete flag reference run trapper-tools COMMAND --help or see the trapper-tools repository. Run a small test dataset through this flow before applying it to a season's worth of data.

Before you begin

  • A Research Project exists in TRAPPER (see Your first research project) — note its project ID, you'll need it for packaging
  • The Locations you plan to associate with deployments are imported
  • Your TRAPPER user account has an FTP account (admin: see Users & roles)
  • trapper-tools is installed and a project configured — trapper-tools config init <name> creates ~/.trapper-tools/<name>.toml and sets it active; trapper-tools helpers test-connection verifies the API/FTPS connection
  • ExifTool and FFmpeg are on PATHtrapper-tools helpers test-tools checks this

Steps

1. Lay out the data on disk

trapper-tools expects two directory levels under --data-path: collection, then deployment. Each top-level subdirectory becomes a TRAPPER Collection (named after the directory, unless you restrict to specific ones with --collection); each subdirectory inside it becomes a Deployment (slugified — camera_alpha_2025_06_01 and Camera Alpha 2025-06-01 both produce a usable deployment_id).

/data/2025_summer/                          <-- data-path root
└── Summer 2025 — main grid/                <-- becomes the Collection name
    ├── camera_alpha_2025_06_01_2025_06_30/  <-- becomes a Deployment
    │   ├── IMG_0001.JPG
    │   ├── IMG_0002.JPG
    │   └── ...
    ├── camera_alpha_2025_07_01_2025_07_30/
    │   └── ...
    └── camera_beta_2025_06_01_2025_07_15/
        ├── VID_0001.MP4
        └── ...

If you skip the collection level and put deployment folders straight under --data-path, each of those becomes its own one-deployment Collection instead — fine for a quick test, but usually not what you want for a season's worth of data.

2. Generate a deployments CSV

If you haven't imported deployments for this collection yet:

trapper-tools helpers template --data-path /data/2025_summer

This walks the two-level collection/deployment tree, reads EXIF/video timestamps per deployment folder, and writes deployments.csv directly into /data/2025_summer/ with columns deploymentID, locationID, deploymentStart, deploymentEnd, cameraModel. deploymentID is the slugified folder name; locationID is guessed as everything after the first hyphen in that slug — so name deployment folders <location>-<rest> (or <location>_<rest>, slugify turns _/spaces into -) if you want this guess to be usable as-is. Pass --collection NAME (repeatable) to limit it to specific collection subsets instead of the whole tree.

Edit the CSV — fill in locationID properly if the guessed value is wrong, match it against your already-imported Locations — then import via Geomap → Deployments, then Import deployments from CSV — see Import locations & deployments.

3. Convert media to web-friendly formats

trapper-tools convert --data-path /data/2025_summer --mp4 --resize-img --resize-img-size 1920 1080

--mp4 re-encodes videos to H.264/MP4 (--webm for VP9/AV1 instead); --resize-img/--resize-img-size downscale images. Useful tuning flags: --crf (quality, default 21), --preset (libx264 speed/quality trade-off), --hwaccel auto|nvenc|none (GPU encoding when available), --jobs N (parallel conversions). Originals are left untouched; output goes to --output-path (defaults to --data-path). Run trapper-tools convert --help for the full list.

4. Package the data

trapper-tools package --data-path /data/2025_summer --project-id 42 --collection "Summer 2025 — main grid" --package-name summer2025

Packaging walks the data path (or just the named --collection subset), reads EXIF/video metadata, and writes summer2025.yaml + summer2025.zip to --output-path (defaults to --data-path). --project-id and --timezone fall back to the active trapper-tools project config when omitted. Pass --skip-deployments-validation only if you haven't imported the deployments CSV yet (step 2) and want to package anyway.

5. Upload

trapper-tools upload /data/2025_summer/summer2025.yaml --trigger

The matching .zip (same basename, same directory) is uploaded automatically — pass either file, the other is found by convention. By default this goes through the resumable HTTP chunk uploader (the trapper_uploader FastAPI service on port 8088); add --use-ftp-uploader to use FTPS with your Trapper FTP credentials instead, which is more efficient for thousands of files:

trapper-tools upload /data/2025_summer/summer2025.yaml --use-ftp-uploader --trigger

--resume retries an interrupted HTTP upload; --overwrite discards a stale partial upload and restarts; --remove-zip deletes the ZIP from the server once processing succeeds.

6. Trigger the pipeline

--trigger (used above) tells TRAPPER to start processing as soon as the upload completes: Resource rows are created, linked to the imported deployments, and — if a ClassificationProject is configured to consume this collection — the AI pipeline fires automatically.

Watch progress in the web UI's Collection page (resource count rises as packages are ingested), the Celery Flower dashboard (http://localhost:5555), or the AI Classification Job admin.

One command for steps 3–5

trapper-tools pipeline --data-path /data/2025_summer --convert --package-name summer2025 --trigger
Chains convert → package → upload (HTTP, by default) → trigger in one call. Use this for unattended batch ingestions, e.g. a cron job after every SD-card swap. It doesn't expose --use-ftp-uploader; for FTPS bulk uploads run package and upload --use-ftp-uploader separately.

Verify it worked

The target Collection's resource count should match your dataset, and (if a Classification Project with AI configured is attached) an AI Classification Job row should appear and progress to completion.

Troubleshooting

Upload succeeded but nothing got processed

Check that you passed --trigger. Without it, the file sits uploaded but unprocessed — trigger it manually from Accounts → HTTP uploader files, select the row, and run the Trigger processing action.

Deployment folder rejected during packaging

package checks each deployment folder's slugified name against the deployments you've already generated/imported via step 2 — re-check the folder name (or the CSV), or pass --skip-deployments-validation if you haven't imported it yet and want to package anyway.

Next steps