The Problem

Downloading media from many sites requires a separate tool per platform, manual handling of yt‑dlp/ffmpeg arguments, and a UI for non‑technical users. Teams that self‑host a downloader need a single, lightweight service that exposes a clean web interface without a heavy stack.

What This Does

reclip is a self‑hosted Flask application that wraps yt‑dlp and ffmpeg. The backend lives in a single file, app.py, which defines six routes (index, get_info, start_download, check_status, plus helper run_download and download_file). The UI is a single HTML page (templates/index.html) with vanilla CSS/JS, served by Flask’s static folder (static/favicon.svg).

  • app.py – 6 functions; two of them invoke external commands and read/write temporary files.
  • reclip.sh – a shell wrapper used in the quick‑start guide; its exact logic is not disclosed but it launches the service.
  • Dockerfile – builds a container from python:3.12‑slim, copies the source, installs Flask and yt‑dlp, and runs the app.

All assets (preview images, example video) are under assets/ and are unrelated to runtime.

How It Is Wired

Execution starts at app.py. When the script is run (python app.py or via the Docker CMD), Flask creates an HTTP server on port 8899.

  1. index – serves templates/index.html. No external effect.
  2. get_info – called by the UI to fetch metadata. It runs yt‑dlp with --dump-json via subprocess, captures stdout, and returns JSON to the browser. This is the first external‑command touch.
  3. start_download – receives the user’s format choice (MP4/MP3) and desired quality. It spawns a background thread that calls run_download.
  4. run_download – builds the yt‑dlp command line (including ffmpeg for audio extraction when MP3 is selected) and executes it. The command writes the resulting file into a temporary directory; the function returns the file path. This is the second external‑command touch and the only file‑write path.
  5. check_status – polls the background thread’s state and reports completion. When finished, the UI presents a download link that serves the file directly from the temporary location.

No other Python modules are imported; the import graph consists solely of the single app module, so there is no intra‑project coupling or circular dependency. All side‑effects are confined to the two functions that invoke subprocesses and write files, giving a clear blast radius.

How To Use It

# Prereqs (per README)
brew install yt-dlp ffmpeg   # or apt install ffmpeg && pip install yt-dlp

# Local run
git clone https://github.com/moses-y/reclip
cd reclip
./reclip.sh                 # wrapper that starts the Flask server
# then open http://localhost:8899

# Docker alternative
docker build -t reclip . && docker run -p 8899:8899 reclip

No additional configuration files or environment variables are required; the service relies on the system‑installed yt‑dlp and ffmpeg binaries.

Real‑World Use

A corporate intranet could deploy the Docker image behind an internal reverse proxy, allowing employees to download training videos from YouTube or Vimeo without leaving the network. The UI can be embedded in an existing portal via an iframe; the backend isolates the heavy ffmpeg work in a separate container, keeping the host environment clean.

Code Health & Issues

  • High – Add a build gate for the Docker image – no CI workflow validates the image (Dockerfile).
  • Medium – Enable Dependabot or Renovate – only requirements.txt present; no automated dependency updates.
  • Medium – Pin the base image by digest – Dockerfile uses mutable tag python:3.12‑slim.
  • Medium – Add a non‑root USER – Dockerfile runs the app as root.
  • Medium – No test suite – repository contains no tests/ directory.
  • Medium – No CI pipeline – no .github/workflows/ or similar.
  • Low – No lockfilerequirements.txt without a requirements.lock makes builds non‑reproducible.

All findings are derived from static analysis; no additional issues were detected.

The Bottom Line

reclip delivers a minimal, functional web UI around yt‑dlp and ffmpeg with a single‑file Flask backend, making it easy to self‑host. The codebase is tiny and straightforward but lacks automated testing, CI, and hardened container practices. It is suitable for small internal teams that can accept the operational risk or are willing to add a CI pipeline and container hardening before production use.