Metadata-Version: 2.5
Name: annextube
Version: 0.13.0
Summary: YouTube archive system using git-annex for efficient storage and incremental updates
Project-URL: Homepage, https://github.com/con/annextube
Project-URL: Documentation, https://annextube.readthedocs.io
Project-URL: Repository, https://github.com/con/annextube
Project-URL: Bug Tracker, https://github.com/con/annextube/issues
Author-email: Yaroslav Halchenko <debian@onerussian.com>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Multimedia :: Video
Requires-Python: >=3.10
Requires-Dist: click>=8.0.0
Requires-Dist: datalad>=1.0.0
Requires-Dist: datasalad>=0.3.0
Requires-Dist: deno>2.6.6
Requires-Dist: google-api-python-client>=2.0.0
Requires-Dist: jsonschema>=4.0.0
Requires-Dist: platformdirs>=4.0.0
Requires-Dist: python-magic>=0.4.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
Requires-Dist: tomlkit>=0.12.0
Requires-Dist: yt-dlp[default]>=2026.07.04
Provides-Extra: audio-align
Requires-Dist: openai-whisper>=20231117; extra == 'audio-align'
Requires-Dist: stable-ts>=2.15.0; extra == 'audio-align'
Provides-Extra: ci
Requires-Dist: mypy>=1.0; extra == 'ci'
Requires-Dist: pagefind-bin<2.0,>=1.0; extra == 'ci'
Requires-Dist: pagefind<2.0,>=1.0; extra == 'ci'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'ci'
Requires-Dist: pytest-cov>=4.0; extra == 'ci'
Requires-Dist: pytest-timeout>=2.0; extra == 'ci'
Requires-Dist: pytest>=7.0; extra == 'ci'
Requires-Dist: ruff>=0.1.0; extra == 'ci'
Requires-Dist: tox-gh-actions>=3.0; extra == 'ci'
Requires-Dist: tox-uv>=1.0; extra == 'ci'
Requires-Dist: tox>=4.0; extra == 'ci'
Requires-Dist: types-pyyaml; extra == 'ci'
Requires-Dist: types-requests; extra == 'ci'
Provides-Extra: devel
Requires-Dist: mypy>=1.0; extra == 'devel'
Requires-Dist: pagefind-bin<2.0,>=1.0; extra == 'devel'
Requires-Dist: pagefind<2.0,>=1.0; extra == 'devel'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'devel'
Requires-Dist: pytest-cov>=4.0; extra == 'devel'
Requires-Dist: pytest-timeout>=2.0; extra == 'devel'
Requires-Dist: pytest>=7.0; extra == 'devel'
Requires-Dist: ruff>=0.1.0; extra == 'devel'
Requires-Dist: tox-uv>=1.0; extra == 'devel'
Requires-Dist: tox>=4.0; extra == 'devel'
Requires-Dist: types-pyyaml; extra == 'devel'
Requires-Dist: types-requests; extra == 'devel'
Provides-Extra: e2e
Requires-Dist: playwright>=1.40; extra == 'e2e'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'e2e'
Requires-Dist: pytest-cov>=4.0; extra == 'e2e'
Requires-Dist: pytest-playwright>=0.4.0; extra == 'e2e'
Requires-Dist: pytest-timeout>=2.0; extra == 'e2e'
Requires-Dist: pytest>=7.0; extra == 'e2e'
Provides-Extra: full
Requires-Dist: openai-whisper>=20231117; extra == 'full'
Requires-Dist: pagefind-bin<2.0,>=1.0; extra == 'full'
Requires-Dist: pagefind<2.0,>=1.0; extra == 'full'
Requires-Dist: stable-ts>=2.15.0; extra == 'full'
Provides-Extra: search
Requires-Dist: pagefind-bin<2.0,>=1.0; extra == 'search'
Requires-Dist: pagefind<2.0,>=1.0; extra == 'search'
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
Requires-Dist: pytest-cov>=4.0; extra == 'test'
Requires-Dist: pytest-timeout>=2.0; extra == 'test'
Requires-Dist: pytest>=7.0; extra == 'test'
Description-Content-Type: text/markdown

# annextube

YouTube archive system using git-annex for efficient storage and incremental updates.

**[Live Demo](https://con.github.io/annextube/)** - Try the web interface with sample videos from the @AnnexTubeTesting channel (auto-generated by GitHub Actions)

## Features

- **Complete channel archival**: Videos, metadata, comments, and captions
- **Incremental updates**: Efficient detection of new content
- **Offline browsing**: Client-side web interface (no server required)
- **Flexible filtering**: By date, license, playlist, metadata attributes
- **CI/CD automation**: GitHub Actions and Codeberg Actions support
- **Git-annex integration**: Efficient storage with special remotes (S3, WebDAV, etc.)

## Quick Start

```bash
# Install (core)
pip install annextube

# Or install with all optional features (DataLad, search index, audio alignment)
pip install 'annextube[full]'

# Create archive
mkdir my-archive && cd my-archive
annextube init

# Configure (edit .annextube/config.toml)
# Add YouTube Data API key and channel URLs

# Backup
annextube backup

# Browse offline
annextube generate-web
open web/index.html
```

## Container Deployment

Pre-built container with all dependencies (git-annex, yt-dlp, ffmpeg, deno):

```bash
# Build container
podman build -t annextube:latest -f Containerfile .

# Run
podman run -it --rm -v $PWD:/archive -e YOUTUBE_API_KEY="key" annextube:latest backup

# For Singularity/Apptainer (HPC clusters)
apptainer build annextube.sif Containerfile
apptainer run --bind $PWD:/archive annextube.sif backup
```

See [docs/how-to/container-deployment.md](docs/content/how-to/container-deployment.md) for full guide.

## Documentation

- **Installation**: See [docs/tutorial/01-installation.md](docs/content/tutorial/01-installation.md)
- **Container Deployment**: See [docs/how-to/container-deployment.md](docs/content/how-to/container-deployment.md)
- **Quick Start**: See [specs/001-youtube-backup/quickstart.md](specs/001-youtube-backup/quickstart.md)
- **Troubleshooting**: See [docs/how-to/troubleshooting.md](docs/content/how-to/troubleshooting.md) (challenge solver errors, quota, interrupted backups)
- **API Reference**: See [docs/reference/](docs/content/reference/)

## System Requirements

### Required

- **Python 3.10+**: Runtime for annextube
- **git**: Version control
- **git-annex 8.0+**: Large file management
- **yt-dlp** (command-line): MUST be in PATH for git-annex --no-raw
  ```bash
  sudo pip install yt-dlp
  # Or download binary to /usr/local/bin
  ```

### Strongly Recommended

- **ffmpeg**: Video processing and best quality downloads
  ```bash
  sudo apt-get install ffmpeg  # Debian/Ubuntu
  brew install ffmpeg          # macOS
  ```

### Optional

- **YouTube Data API v3 key**: For API-based metadata (free from Google Cloud Console)
- **deno or node**: JavaScript runtime for modern YouTube features
- **Optional extras** (install individually or all at once with `pip install 'annextube[full]'`):

  | Extra | Install | Description |
  |-------|---------|-------------|
  | `datalad` | `pip install 'annextube[datalad]'` | DataLad dataset management |
  | `search` | `pip install 'annextube[search]'` | Full-text caption search index (pagefind) |
  | `audio-align` | `pip install 'annextube[audio-align]'` | Audio-based caption alignment (Whisper) |
  | **`full`** | `pip install 'annextube[full]'` | **All of the above** |

## Development

```bash
# Clone repository
git clone https://github.com/con/annextube.git
cd annextube

# Install with development dependencies
uv pip install -e ".[devel]"

# Run tests
pytest

# Run linter
ruff check annextube/ tests/

# Run type checker
mypy annextube/
```

## License

MIT License - see [LICENSE](LICENSE) file

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) (TBD)

## Project Status

🚧 **Early Development** - This project is under active development. API may change.

Current phase: Implementing MVP (User Story 1 + 2)
