A production-ready folder watcher that automatically transcodes newly added video files using ffmpeg, with safe file stabilization (waits until copy finishes), queueing, retries, renaming templates, and rotating logs.
- Watch a directory (recursively or not) and transcode new files as they arrive
- File stabilization: wait until size stops changing before processing
- Queue + worker pool to handle bursts
- Robust rename templates:
{event},{date},{time},{basename},{ext},{counter} - Atomic writes: encode to
*.tmpthen rename to final name - Rotating logs in
./logs/transcoder.log - Configurable via YAML
- Cross-platform (macOS, Windows, Linux)
- Python 3.9+ recommended
- FFmpeg installed (available in your PATH), or set
ffmpeg_pathin the config
# 1) Setup venv (recommended)
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS/Linux:
source .venv/bin/activate
# 2) Install deps
pip install -r requirements.txt
# 3) Create config from example
cp config.example.yaml config.yaml
# Edit config.yaml as needed (watch_dir, output_dir, event_name, etc.)
# 4) Create folders (or let the script do it)
mkdir -p input_videos output_videos logs
# 5) Run watcher
python watch_and_transcode.py -c config.yamlpython watch_and_transcode.py -c config.yaml --onceevent_name: "StudioEvent"
output_dir: "output_videos"
rename_template: "{event}_{date}_{basename}.mp4"
watch_dir: "input_videos"
recursive: true
include_extensions: [".mov", ".mxf", ".avi", ".mp4", ".m4v", ".mkv", ".wmv", ".mts"]
ffmpeg_path: "ffmpeg"
video_codec: "libx264"
preset: "fast"
crf: 23
audio_codec: "aac"
audio_bitrate: "192k"
copy_audio_when_possible: false
stabilization_seconds: 4
stabilization_poll_interval: 1
max_retries: 2
retry_backoff_seconds: 5
workers: 2
log_dir: "logs"
log_level: "INFO"{event}→event_namefrom config{date}→YYYY-MM-DD(current){time}→HH-MM-SS(current){basename}→ source file name without extension{ext}→ source file extension without the dot{counter}→ optional index if you add it to the template; the script also auto-appends_02,_03, ... on collisions
Use the included script to simulate slow file arrival (like camera copies or network ingest):
# Activate venv, then:
python tools/simulate_ingest.py input_videos path/to/BigVideo.mov --chunk-bytes 262144 --sleep 0.5It copies the file in chunks into the watch folder so you can verify stabilization behavior.
Create /etc/systemd/system/auto-transcode.service:
[Unit]
Description=Auto Transcode Watcher
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/auto-transcode-watcher
ExecStart=/path/to/auto-transcode-watcher/.venv/bin/python watch_and_transcode.py -c config.yaml
Restart=on-failure
User=youruser
Group=yourgroup
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
Enable & start:
sudo systemctl daemon-reload
sudo systemctl enable auto-transcode.service
sudo systemctl start auto-transcode.serviceCreate ~/Library/LaunchAgents/com.studio.auto-transcode.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.studio.auto-transcode</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/auto-transcode-watcher/.venv/bin/python</string>
<string>/path/to/auto-transcode-watcher/watch_and_transcode.py</string>
<string>-c</string>
<string>/path/to/auto-transcode-watcher/config.yaml</string>
</array>
<key>WorkingDirectory</key><string>/path/to/auto-transcode-watcher</string>
<key>RunAtLoad</key><true/>
<key>StandardOutPath</key><string>/path/to/auto-transcode-watcher/logs/launchd.out</string>
<key>StandardErrorPath</key><string>/path/to/auto-transcode-watcher/logs/launchd.err</string>
</dict>
</plist>Load it:
launchctl load ~/Library/LaunchAgents/com.studio.auto-transcode.plist
launchctl start com.studio.auto-transcode- Use Task Scheduler to run the script at logon, or
- Use NSSM to wrap the script as a service:
nssm install AutoTranscodeWatcher- Application path:
C:\path\to\auto-transcode-watcher\.venv\Scripts\python.exe - Arguments:
watch_and_transcode.py -c config.yaml - Startup directory:
C:\path\to\auto-transcode-watcher
- Simple desktop GUI (PyQt/Tkinter)
- E-mail/Slack notifications on failures
- Cloud upload (S3/Drive) after success
- Optional rewrap-only (copy video/audio) if codecs already compliant
- Thumbnail generation & basic proxy workflows
MIT (see LICENSE)