Skip to main content

Media Archive Sync

CI PyPI version Python versions License: MIT

Download and organize media files from web archives (Apache-style directory listings).

Long Description

Media Archive Sync is a Python library and CLI for downloading and organizing media from web archives that expose Apache-style directory listings. It crawls listings, downloads files in parallel with resume support, organizes local files, writes Kodi-compatible NFO sidecars, and can merge multipart videos.

Use it to maintain local copies of publicly hosted VOD archives, stream recordings, and other media collections without an archive API or RSS feed. The project provides both a Python API and a CLI, is ready for Docker deployments, and keeps configuration in ArchiveConfig rather than external configuration files.

Table of Contents

Background

Public media archives often consist of flat Apache directory listings with no structured API. Media Archive Sync turns that listing into a repeatable pipeline: crawl the archive, download files with retries and cached progress, optionally organize and merge them, and preserve metadata in sidecar files.

Install

Python package installation requires Python 3.11 or newer. Docker is the fastest way to run the pre-built image.

Docker

Pull the pre-built image and mount the media and cache directories:

docker pull ghcr.io/djdembeck/media-archive-sync:latest

docker run --rm \
    -v /host/media:/media:rw \
    -v /host/cache:/app/.cache:rw \
    ghcr.io/djdembeck/media-archive-sync:latest \
    --remote https://archive.example.com/vods/ \
    --local /media

The image entrypoint is media-archive-sync; its declared volumes are /media and /app/.cache.

PyPI

Install the released package with pip:

pip install media-archive-sync

Usage

CLI

The console script requires a remote archive URL. Start with the minimal command, then add the options you need:

# Basic download
media-archive-sync --remote https://archive.example.com/vods/ --local ./media

# Preview a download without writing files, and suppress non-essential output
media-archive-sync \
    --remote https://archive.example.com/vods/ \
    --local ./media \
    --dry-run --quiet

# Download in parallel with 10 workers
media-archive-sync \
    --remote https://archive.example.com/vods/ \
    --local ./media \
    --workers 10

# Organize downloaded files by month
media-archive-sync \
    --remote https://archive.example.com/vods/ \
    --local ./media \
    --workers 5 \
    --organize

Use media-archive-sync --help for the complete option list. The available flags are --remote, --local, --workers, --dry-run, --organize, and --quiet.

Library API

Use the library when you need to integrate crawling and downloading into a Python program. The crawler returns (URL, filename) pairs; convert those entries to local paths before passing them to download_files:

from pathlib import Path

from media_archive_sync import ArchiveConfig, crawl_archive, download_files

config = ArchiveConfig(
    remote_base="https://archive.example.com/vods/",
    local_root=Path("./media"),
    workers=5,
)

media_list, _ = crawl_archive(
    remote_base=config.remote_base,
    max_depth=config.max_depth,
    video_extensions=config.video_extensions,
)
download_files(
    [
        (url, config.local_root / filename)
        for url, filename in media_list
    ],
    workers=config.workers,
    skip_existing=config.skip_existing,
    timeout=config.request_timeout,
    max_retries=config.max_retries,
)

The examples/basic_download.py script contains the same crawl-and-download flow. For custom progress and organization, see examples/custom_organizer.py.

Features

  • 🌐 Web Archive Crawling - Crawl Apache-style directory listings
  • 📥 Parallel Downloads - Download multiple files simultaneously with resume support
  • 📁 Smart Organization - Organize by date, custom naming conventions
  • 📝 Metadata Support - Generate NFO sidecar files
  • 🎬 Video Merging - Concatenate multipart video files
  • 💾 Resume Support - Cache progress and resume interrupted downloads
  • 🔧 Configurable - Everything is configurable, no hardcoded values

Configuration

Configure the library with the ArchiveConfig dataclass. There are no external configuration files. The CLI maps its options to this configuration object for each run.

Common configuration fields
Field Default Purpose
remote_base "" Base URL for the remote archive
local_root Path("./media") Local media directory
workers 3 Number of parallel download workers
skip_existing True Skip files that already exist
cache_backend "sqlite" Progress cache backend; "sqlite" or "json"
cache_dir None Directory for cache data
write_nfo True Write NFO sidecar files
use_month_folders True Enable month-based organization
video_extensions .mp4, .mkv, .avi, .mov, .webm File extensions to crawl
max_retries 3 Maximum retry attempts per file
request_timeout 15 seconds HTTP request timeout

API

The package exports the configuration object and the core crawl and download functions directly:

from media_archive_sync import ArchiveConfig, crawl_archive, download_files
  • ArchiveConfig stores remote, local, download, cache, organization, metadata, and HTTP settings.
  • crawl_archive walks Apache-style listings and returns media entries plus per-directory counts.
  • download_files downloads (url, local_path) pairs in parallel with resume, skip-existing, timeout, and retry options.
  • download_with_config applies an ArchiveConfig to a download operation.
  • DownloadManager is available when you need manager-level control over downloads.

The package also exports organizer, metadata, cache, string-normalization, and multipart-video merge functions. Inspect the module source or Python signatures for the complete public surface.

Examples

Building

The following commands are for contributors building from the repository rather than running the released package or pre-built image.

Development install

Clone the repository and install the development dependencies:

git clone https://github.com/djdembeck/media-archive-sync.git
cd media-archive-sync
pip install -e ".[dev]"

The Makefile provides the equivalent setup and enables the repository hooks:

make dev-install

To configure the hooks separately:

make install-hooks

The development toolchain includes pytest, coverage, pytest-xdist, pytest-timeout, Ruff, Black, MyPy, responses, and httmock. See CONTRIBUTING.md for the development workflow and checks.

Build the Docker image

Build the multi-stage image from the repository and run its help command:

docker build -t media-archive-sync .
docker run --rm media-archive-sync --help

The Dockerfile builds with python:3.13-slim, installs the package into a separate runtime stage, and includes ffmpeg, mkvtoolnix, and mediainfo in that runtime image.

For a non-editable package install directly from the repository, use:

pip install git+https://github.com/djdembeck/media-archive-sync.git

Contributing

See CONTRIBUTING.md for development setup, git hooks, quality checks, and pull request guidelines.

License

MIT (SPDX identifier); see LICENSE.

Metadata

Release files for media-archive-sync 0.4.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for media-archive-sync 0.4.4
File Size Uploaded Provenance Actions
media_archive_sync-0.4.4.tar.gz 137.9 kB With provenance Details for media_archive_sync-0.4.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for media-archive-sync 0.4.4
File Interpreter ABI Platform Actions
media_archive_sync-0.4.4-py3-none-any.whl Python 3 none any Details for media_archive_sync-0.4.4-py3-none-any.whl

Total release size: 209.8 kB

Release files / media_archive_sync-0.4.4.tar.gz

Download URL media_archive_sync-0.4.4.tar.gz
Size 137.9 kB
Tags Source
SHA-256 checksum
How to use checksums
6e1567268239e10307ab207ad8bab8f923d7ab63f29689274881d9cce614f3d3
BLAKE2b-256 checksum
How to use checksums
a355a0c7c63c175abd3eb7b77a061eaeac4fc41b172ecadc917c3c9a561185b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / media_archive_sync-0.4.4-py3-none-any.whl

Download URL media_archive_sync-0.4.4-py3-none-any.whl
Size 71.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
369bbb81bd93a484dd16830be28ccf487668e1813fe5b3dc71522f6b083284b2
BLAKE2b-256 checksum
How to use checksums
a301c3407545f6ee8d40295f528ff8afecd2a03576e661d5fae26ab711dfbef2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Security for media-archive-sync 0.4.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for media_archive_sync-0.4.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page