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-toolsis installed and a project configured —trapper-tools config init <name>creates~/.trapper-tools/<name>.tomland sets it active;trapper-tools helpers test-connectionverifies the API/FTPS connection - ExifTool and FFmpeg are on
PATH—trapper-tools helpers test-toolschecks 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
--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.