A CLI + interactive TUI for the boring-but-critical infrastructure underneath video post-production: probe camera cards, organize them, generate proxies, spin up a DaVinci Resolve project, and verify backups — every step logged to a local SQLite audit trail.
No API keys. No cloud. Just FFmpeg, your local SQLite, and (optionally) DaVinci Resolve.
1. The interactive TUI (the primary interface for most people)
ferryLaunches a full-screen Textual workstation with four screens: Home (dashboard), Pipelines (browse + queue + watch runs live), Audit Log (browse and search run history), and Settings (edit and persist config). See The TUI below for the full keymap.
2. The CLI (for scripts, cron, and quick one-offs)
ferry run ./raw/ --organize --proxy --resolve-project --verify --project-name "Episode-12"Chains probe → organize → proxy → resolve-project → verify in one call. Each command also runs standalone — see The CLI.
Prefer scripts and one-liners? Add --no-tui to skip the TUI auto-launch and stay in CLI mode:
ferry --no-tui run ./raw/# 1. Get the code
git clone https://github.com/dspury/file-ferry.git
cd file-ferry
# 2. Install (use pipx for an isolated install, or pip if you don't have it)
pipx install .
# — or —
pip install .
# 3. Make sure ffmpeg is on PATH (required)
brew install ffmpeg # macOS
sudo apt install ffmpeg # Debian/Ubuntu
# 4. Launch the TUI
ferryWant to try it without your own media? Bundled sample footage is in examples/:
cd examples/
./run-demo.shA full walkthrough with screenshots and audit-log output is in examples/WALKTHROUGH.md.
The TUI is a full-screen Textual workstation. It's keyboard-driven and lives inside your terminal — no browser, no separate window.
| Screen | What it does |
|---|---|
| Home | Dashboard with ffmpeg version, db path, and stat tiles (total / succeeded / failed / live runs) |
| Pipelines | Browse mounted folders, queue several sources, run all five capability steps, watch progress live. The MEDIA BROWSER pane surfaces connected external drives (camera cards, backup disks, USB sticks) at the top — each entry shows name and free/total space, click one to jump the tree straight to it. The drive list refreshes automatically when cards are plugged in or ejected, and system junk (.Trashes, $RECYCLE.BIN, AppleDouble ._* sidecars, …) is hidden from the browser and skipped by every pipeline step. |
| Audit Log | Browse and search run history; runs are color-coded by status |
| Settings | Edit and persist proxy codec/height, checksum algorithm, and binary paths |
Keybindings (all available without leaving the keyboard):
| Key | Action |
|---|---|
R / L / S |
Jump to Pipelines / Audit Log / Settings from Home |
A |
Add a folder to the queue (in Pipelines) |
Ctrl+R |
Run the queue |
Ctrl+C |
Safely cancel the current run |
/ |
Search the audit log |
Ctrl+S |
Save settings |
Q |
Quit |
The TUI is optional — ferry --no-tui keeps you in CLI mode and prints command help.
Each capability runs standalone or as part of the run pipeline. Step order in run is fixed: probe (always) → organize → proxy → resolve-project → verify. Skip any combination you don't need.
| Command | What it does |
|---|---|
probe |
Run ffprobe on every file in a folder; capture codec, resolution, frame rate, color, audio, duration, size, mtime |
organize |
Re-arrange files into a structured layout, preserving the source's folder shape (cards/scenes/takes) |
proxy |
Generate ProRes 422 Proxy (or any ProRes variant) at 1080p via ffmpeg; aspect-preserving; skips non-video |
resolve create |
Create a DaVinci Resolve project programmatically; falls back to a JSON manifest if Resolve isn't running |
verify |
Checksum a folder; on rerun, report what changed (added/modified/missing) — designed for cron |
log |
Query the audit log (text or JSON) |
run |
Orchestrate any combination of the above as a pipeline |
Run ferry <command> --help for the full flag list. Example output:
$ ferry run ./raw/ --organize --proxy --resolve-project --verify --project-name "Episode-12"
Step 1: probe
Probed 4 file(s)
Step 2: organize
Copied 4, skipped 0
Step 3: proxy
Generated 4 proxy file(s)
Step 4: resolve-project
Created Resolve project (v20.0)
Step 5: verify
Clean: 4 file(s) verified
Done.
# Every night at 3am, verify the backup drive and alert on any change
0 3 * * * cd /path/to/workspace && ferry verify /Volumes/Backup/ || mail -s "Backup alert" me@example.comExit codes from verify: 0 = clean, 1 = missing, 2 = modified, 3 = added.
Requirements:
- Python 3.11+ (for
tomllibstdlib) - FFmpeg with
ffprobeon$PATH(or pointed at via config) - DaVinci Resolve Studio (free tier is fine) — only required for
resolve create; everything else works without it
Install:
git clone https://github.com/dspury/file-ferry.git
cd file-ferry
pipx install . # clean isolated install
# — or —
pip install . # into your current environmentFrom a working tree (development):
git clone https://github.com/dspury/file-ferry.git
cd file-ferry
pip install -e ".[dev]"Verify:
ferry --version
ferry --helpferry works with sensible defaults. Drop a ferry.toml in your project root or ~/.ferry/ to override. Search order: --config <path> / FERRY_CONFIG env var → ./ferry.toml → ~/.ferry/config.toml.
# Proxy generation defaults (any ProRes variant)
proxy_codec = "ProRes422Proxy"
proxy_height = 1080
# Checksum algorithm: xxhash (default, ~10x faster) | sha256
checksum_algo = "xxhash"See ferry.toml.example for the full reference.
v0.3.0 renamed the project, and with it every path it reads. Nothing is migrated
automatically — ferry looks only at the new locations, and your old data is
left untouched where it is. To carry it over:
mv ~/.media-mate ~/.ferry # config + audit log
mv ~/.ferry/media-mate.db ~/.ferry/ferry.db # the database itself
mv ./media-mate.toml ./ferry.toml # per-project config, if you have oneThe desktop app keeps its data separately, under
~/Library/Application Support/ferry/ (was .../media-mate/) on macOS. That
directory holds the vNext database, operation receipts and diagnostic logs, so
move it too — left behind, the app starts with an empty database and your
projects, jobs and receipts are not carried over.
The database schema did not change, so a moved ferry.db is read as-is.
Every operation writes to ~/.ferry/ferry.db (SQLite). The schema covers runs, files, probes, proxies, projects, verifications, and organize operations.
The log answers questions like:
- "When did this file get probed, and what was the result?"
- "What got copied during the last organize run?"
- "When was this Resolve project created, and from what source folder?"
- "What was the checksum of this file at the last verify?"
It's the system of record — back it up, copy it between machines, trust it as ground truth. Query from the TUI's Audit Log screen or the CLI:
ferry log # text table
ferry log --format json
ferry log --limit 5The next product direction is documented in
docs/FILE-FERRY-PRODUCT-DIRECTION.md:
a local-first desktop workstation for verified card offload, existing-folder
adoption, project reconciliation, and a retained CLI/TUI.
The full build plan is in
docs/FILE-FERRY-FULL-APP-IMPLEMENTATION-PLAN.md.
All nine implementation packages are landed (see its §0 progress table):
Electron shell + secure bridge, the complete desktop experience, TUI/CLI
parity, and packaged-release hardening. The remaining items are operator-owned
release gates (signing/notarization, real-media suite, soak, security review)
— see §16 of the plan.
Longer-term ideas (not yet scheduled):
- Scene detection (PySceneDetect)
- Audio loudness analysis
- Watch-folder mode
- Cloud-storage adapters
Open source under the MIT license. Issues and PRs welcome on GitHub.
Development setup:
git clone https://github.com/dspury/file-ferry.git
cd file-ferry
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest # 326 tests
ruff check . && ruff format --check .
mypy srcFull specification: SPEC.md.
MIT — see LICENSE.