refactor: replace moviepy with mutagen + pymediainfo for media duration extraction
Summary
app/utils/media_duration.py imports moviepy — a full video editing framework — solely to read the duration of audio and video files. This introduces a heavy dependency for a single metadata field and includes a fragile subprocess re-encoding fallback for corrupted files.
Problem
-
moviepyis a video editing library (transitions, effects, compositing) being used as a metadata reader - It pulls in
imageio,decorator,proglog, and ffmpeg binary dependencies unnecessarily - The file includes a fallback that re-encodes corrupted MP4s via ffmpeg subprocess — adding ffmpeg as a hidden system requirement
-
moviepy'sVideoFileClipopens and decodes the file to extract duration, which is orders of magnitude more work than reading metadata headers - This makes duration extraction slow for large files and error-prone for unusual encodings
Proposed Solution
Replace with purpose-built metadata libraries:
-
mutagen(LGPL) for audio files (MP3, WAV, M4A, OGG) — reads ID3/Vorbis/M4A tags including duration in milliseconds without decoding audio -
pymediainfo(MIT) for video files (MP4, MOV, WebM, MKV, AVI) — wraps the MediaInfo library, returns structured track metadata
# Audio (mutagen)
from mutagen import File
audio = File(path)
duration_seconds = audio.info.length
# Video (pymediainfo)
from pymediainfo import MediaInfo
info = MediaInfo.parse(path)
duration_seconds = info.tracks[0].duration / 1000
Library signals:
| mutagen | pymediainfo | |
|---|---|---|
| License | LGPL | MIT |
| Weekly downloads | 2M+ | 500K+ |
| Maintenance | Active | Active |
| CVEs | None known | None known |
Impact
| Dimension | Current | After |
|---|---|---|
| LOC | 243 lines (incl. re-encoding fallback) | ~30 lines |
| Dependency weight | moviepy + imageio + ffmpeg binary | mutagen + pymediainfo (MediaInfo) |
| Performance | Decodes audio/video frames | Reads file headers only |
| Reliability | Fragile re-encoding for corrupt files | Raises clean exception |
| Formats covered | Same | Same (MP3, WAV, M4A, OGG, MP4, MOV, WebM, MKV) |
Files Affected
-
app/utils/media_duration.py— replace entirely -
pyproject.toml— removemoviepy, addmutagenandpymediainfo