Imported from JQLSpec/media_slurp (
AGENTS.md). Install upstream withnpx skills add JQLSpec/media_slurp. Copyright stays with the author.
Repository Guidelines
Project Structure & Module Organization
media_transcoder.pyholds the watcher loop, configuration loader, FFmpeg command builders, and watchdog event handlers. Treat it as the canonical source for business logic and architecture.media_transcoder_cfg.jsondefines root paths (base, ingest, Camera_Originals, Encoded/H265, Encoded/Proxy), encoder presets, file extensions, and processing thresholds. Copy it to~/.media_transcoder_cfg.jsonfor user-specific overrides.check_video_metadata.shandset_camera_metadata.sh(documented inSHELL_SCRIPTS.md) live at repo root and provide ffprobe/ffmpeg helpers for camera metadata hygiene.- Documentation (
README.md,SHELL_SCRIPTS.md, this AGENTS.md file) and dependency manifest (requirements.txt) are also in the root directory; there are no nested packages or tests yet.
Build, Test, and Development Commands
# Install Python dependencies (watchdog)
pip3 install -r requirements.txt
# Run the transcoder interactively (creates ingest/output folders automatically)
python3 media_transcoder.py
# Audit metadata before ingest (ensures camera/date tags are present)
./check_video_metadata.sh Ingest/*.mp4
Coding Style & Naming Conventions
- Indentation: 4 spaces throughout the Python codebase; no tabs observed.
- File naming: Snake_case for scripts (
media_transcoder.py,check_video_metadata.sh), uppercase for supporting docs (README.md). Config files use lowercase with underscores. - Function/variable naming: Python functions and locals use snake_case, classes use
CapWords(e.g.,Config,VideoTranscoder). Shell scripts prefer uppercase env vars and mixed-case echo labels. - Linting: No automated linters are configured. Follow PEP 8 manually and keep shell scripts POSIX-compliant. If adding tooling (e.g.,
ruff,shellcheck), document the commands in this section.
Testing Guidelines
- Framework: No automated tests ship with the repository. Validation relies on manual runs of
media_transcoder.pyplus the metadata helper scripts. - Test files: When adding tests, mirror the root layout (e.g.,
tests/test_transcoder.py) and keep fixtures undertests/fixtures/. - Running tests: Not applicable yet; document
pytest/unittestcommands once introduced. - Coverage: No coverage targets are defined. For now, sanity-check by transcoding a short sample clip and verifying outputs in
Encoded/H265andEncoded/Proxy.
Commit & Pull Request Guidelines
- Commit format: The existing history favors short imperative statements (e.g.,
Initial things,Update). Prefer<scope>: <summary>if you introduce more complex work, but keep subjects β€50 chars and bodies wrapped at 72 chars. - PR process: Reference the feature or fix in the PR description, summarize hardware/codec changes, and note any config migrations. Include manual test evidence (sample command output) before requesting review.
- Branch naming: No enforced scheme is documented. Suggested pattern:
feature/<short-topic>orfix/<issue-id>so contributors can infer purpose quickly.
Repository Tour
π― What This Repository Does
Media Transcoder automates ingest-to-delivery processing for camera footage by watching an ingest folder, stabilizing files, then launching parallel FFmpeg jobs that emit visually lossless H.265 masters and Final Cut Proβfriendly H.264 proxies.
Key responsibilities:
- Monitor ingest paths and defer work until files finish copying
- Detect camera metadata to build
YYYY-MM-DD/Camerafolder hierarchies - Select the best available hardware encoder (VideoToolbox, NVENC, VAAPI, or libx265/libx264 fallback)
ποΈ Architecture Overview
System Context
[Camera card dump / Watch folder]
β
[media_transcoder.py]
β β
Encoded/H265 & Proxy Camera_Originals (archive)
β
Final Cut Pro / NLEs
Key Components
- Config (class in
media_transcoder.py): Loads JSON config (user override β project default), resolves platform-specific base paths, and probes hardware acceleration by shelling out tosysctl,nvidia-smi, or/dev/drichecks. - VideoTranscoder: Orchestrates ffprobe scans, metadata extraction, FFmpeg command synthesis, progress parsing, and post-processing (size reporting, original relocation).
- VideoFileHandler & Observer loop: Watchdog-based filesystem event handler that debounces file writes, queues stable files, and invokes the transcoder;
main()wires the observer, processes existing backlog, and keeps the loop alive.
Data Flow
- Watchdog notices a new supported extension inside
Ingest/and tracks its last-write timestamp. - Once
stability_timeoutelapses without changes,VideoTranscoder.transcode_file()probes duration, frame count, recording date, and camera type (ffprobe tags, filename heuristics). - Date/camera subfolders under
Encoded/H265andEncoded/Proxyare created; two FFmpeg commands (H.265 + proxy) run on dedicated threads with hardware-aware flags. - Progress lines are parsed from FFmpeg stderr for live frame/fps/ETA output. When both encodes succeed, the original file is moved to
Camera_Originals/and size savings are reported.
π Project Structure [Partial Directory Tree]
media_slurp/
βββ media_transcoder.py # Main watcher + transcoder + CLI entry point
βββ media_transcoder_cfg.json # Default paths, encoder presets, stability tuning
βββ README.md # End-user setup, hardware notes, services
βββ SHELL_SCRIPTS.md # Metadata helper documentation
βββ check_video_metadata.sh # ffprobe audit helper for camera/date tags
βββ set_camera_metadata.sh # ffmpeg helper that injects tags in-place
βββ requirements.txt # Python deps (watchdog 4.0.0)
βββ AGENTS.md # This AGENTS.md file (guidelines + tour)
Key Files to Know
| File | Purpose | When You'd Touch It |
|---|---|---|
media_transcoder.py |
Event loop, Config, VideoTranscoder, FFmpeg orchestration | Implement new encoders, tweak progress logic, or change watcher behavior |
media_transcoder_cfg.json |
Baseline directory map, encoder presets, stability thresholds | Update default paths/timeout values or add codecs/extensions |
~/.media_transcoder_cfg.json (user override) |
Personal configuration that supersedes project defaults | Customize ingest/output roots per workstation |
README.md |
Install instructions, launchd/systemd recipes | Update when workflows, hardware requirements, or usage steps change |
SHELL_SCRIPTS.md |
Explains helper scripts and metadata workflows | Document new shell automation or troubleshooting steps |
check_video_metadata.sh |
Validates presence of make, model, and creation_time tags |
Run before ingest to prevent Unknown folders |
set_camera_metadata.sh |
Injects/repairs metadata via stream copy | Fix legacy footage before re-ingesting |
requirements.txt |
Pins watchdog dependency | Add/remove Python packages |
π§ Technology Stack
Core Technologies
- Language: Python 3.7+ β chosen for cross-platform filesystem access, subprocess control, and available threading.
- Frameworks/Libraries:
watchdog==4.0.0powers filesystem monitoring;threading,subprocess, andpathlibhandle concurrency and process orchestration. - Media Tooling: FFmpeg/ffprobe (external binaries) provide probing, hardware acceleration, and encoding; VideoToolbox (macOS), NVENC (NVIDIA), VAAPI (Intel/AMD), and libx265/libx264 serve as encoder backends.
- Shell Utilities: launchd/systemd examples enable background service deployment.
Key Libraries
- Watchdog β Observer + event handler abstractions for cross-platform directory watching.
- FFmpeg β Actual encoder/decoder invoked from Python (handles hevc/h264 video, AAC audio, metadata copying).
- ffprobe β Supplies duration, frame count, metadata (creation_time, make/model) for routing logic.
Development Tools
- pip β Installs the lone Python dependency.
- brew/apt β Referenced in README for FFmpeg installation.
- launchctl/systemd β Optional service managers when running unattended.
π External Dependencies
Required Services
- FFmpeg + ffprobe β Must include hardware acceleration support relevant to the host (VideoToolbox on macOS, NVENC/VAAPI on Linux). Absence falls back to software encoders with slower throughput.
- GPU drivers / hardware interfaces β
nvidia-smifor CUDA availability;/dev/dri/renderD128for VAAPI; Apple Silicon/Intel Quick Sync on macOS detected viasysctl.
Optional Integrations
- launchd/systemd units β Provide auto-start behavior; scripts live outside this repo but README contains templates.
π Common Workflows
Watch-folder Transcoding
- Copy raw footage into
Ingest/under the configured base directory. media_transcoder.pyensures directories exist, processes any backlog, then watches for new files.- After stability checks, the file is transcoded twice in parallel, outputs appear in
Encoded/H265/<date>/<camera>/andEncoded/Proxy/<date>/<camera>/, and the source moves toCamera_Originals/. - Import outputs into Final Cut Pro or other NLEs using the date/camera hierarchy.
Code path: main() β Config.ensure_directories() β VideoFileHandler.process_pending_files() β VideoTranscoder.transcode_file().
Metadata Repair Loop
- Run
./check_video_metadata.sh Camera_Originals/*.mp4to find files organized underUnknown. - For each offender, execute
./set_camera_metadata.sh <file> <make> <model>to apply QuickTime + standard tags (optionally inferring creation_time from filenames). - Re-ingest fixed files by moving them back into
Ingest/; the watcher reprocesses them with correct folder routing.
Code path: Shell scripts (check_video_metadata.sh, set_camera_metadata.sh) β media_transcoder.py metadata parsing helpers (_get_camera_type, _get_recording_date).
π Performance & Scale
- Parallelism: H.265 and proxy jobs run on separate threads, so total job time roughly matches the slower encoder. Hardware accelerators dramatically improve throughput (3β10Γ real-time depending on GPU/CPU).
- Stability heuristics:
stability_required_checksandstability_check_intervalprevent processing half-copied files; adjust for slower storage if needed. - Timeouts:
encode_timeoutdefaults to two hours; long-form footage on software encoders may need higher limits.
Monitoring
- Live console output includes platform, selected encoders, per-job frame/fps/ETA, and size comparisons.
- Extend logging by honoring the
loggingsection inmedia_transcoder_cfg.json(log file name + level).
π¨ Things to Be Careful About
π Security & Safety
- File moves are destructive: Successful jobs move originals into
Camera_Originals/. Ensure that directory is backed up if footage must be preserved elsewhere. - Metadata scripts overwrite files:
set_camera_metadata.shdeletes the original after writing a tagged copy. Always keep backups or run on duplicates first. - External binaries: FFmpeg commands are assembled from config and metadata; validate user-provided overrides to avoid injecting unsafe parameters.
Data Handling
- Sensitive footage paths live in config files; avoid committing user-specific overrides in
~/.media_transcoder_cfg.json. - Directory permissions (especially
/Users/Shared/mediaor/home/media) must allow the watcher to create subdirectories and move files.
Update to last commit: d6b8bf5
Last updated: 2026-02-15