Skip to main content

CLI tool to download Zoom cloud recordings and extract audio for transcription

Project description

dlzoom

Download Zoom cloud recordings from the command line.

Simple CLI tool to download audio recordings and metadata from Zoom meetings using meeting IDs.

Features

  • ๐ŸŽต Download audio recordings (M4A format)
  • ๐Ÿ“ Download transcripts, chat logs, and timelines
  • ๐Ÿ”„ Automatic audio extraction from video files (MP4 โ†’ M4A)
  • ๐Ÿ” Server-to-Server OAuth authentication
  • ๐Ÿ“‹ JSON output for automation
  • ๐ŸŽฏ Support for recurring meetings and PMI
  • โณ Wait for recording processing with --wait
  • ๐Ÿ” Check recording availability before downloading
  • ๐Ÿ›ก๏ธ Secure (credentials never exposed in logs)
  • ๐Ÿ” Automatic retry with exponential backoff
  • ๐Ÿ’ช Production-ready with 119 tests

Installation

Choose your preferred method:

๐Ÿš€ Quick Try (uvx - Instant Run, No Install)

Fastest way to try dlzoom - requires Python 3.11+ and ffmpeg:

# Install uv first (if not installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Run dlzoom instantly (no installation needed!)
uvx dlzoom 123456789 --check-availability

๐Ÿ“ฆ PyPI Install (Recommended for Regular Use)

# Install with pip
pip install dlzoom

# Or with uv (10-100x faster)
uv pip install dlzoom

# Or with uv tool (isolated installation)
uv tool install dlzoom

Note: Requires Python 3.11+ and ffmpeg (see below).

๐Ÿณ Docker (Zero Dependencies - Everything Included!)

Best for: Production, CI/CD, no local dependencies

# Run with Docker (includes Python + ffmpeg)
docker run -it --rm \
  -v $(pwd)/recordings:/app/downloads \
  -e ZOOM_ACCOUNT_ID="your_account_id" \
  -e ZOOM_CLIENT_ID="your_client_id" \
  -e ZOOM_CLIENT_SECRET="your_secret" \
  yanivgolan1/dlzoom:latest \
  123456789```

**Or use GitHub Container Registry:**
```bash
docker run -it --rm \
  -v $(pwd)/recordings:/app/downloads \
  -e ZOOM_ACCOUNT_ID="your_account_id" \
  -e ZOOM_CLIENT_ID="your_client_id" \
  -e ZOOM_CLIENT_SECRET="your_secret" \
  ghcr.io/yaniv-golan/dlzoom:latest \
  123456789```

### ๐Ÿ”ง From Source (Development)

```bash
# Clone the repository
git clone https://github.com/yaniv-golan/dlzoom.git
cd dlzoom

# Create virtual environment (recommended)
python3.11 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install
pip install -e .

Prerequisites (for non-Docker installations)

  • Python 3.11+ (required)
  • ffmpeg (required for audio extraction from video files)

Install ffmpeg:

# macOS
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

# Windows (via Chocolatey)
choco install ffmpeg

# Windows (via winget)
winget install ffmpeg

Docker users: No need to install Python or ffmpeg - everything is included!

Quick Start

1. Get Zoom API Credentials

Coming in v0.2: One-click authentication! No more manual app setup. See Roadmap.

Current method (Server-to-Server OAuth):

  1. Go to Zoom Marketplace
  2. Sign in โ†’ Develop โ†’ Build App
  3. Create a Server-to-Server OAuth app
  4. Copy your credentials:
    • Account ID
    • Client ID
    • Client Secret
  5. Add required scopes:
    • recording:read:admin
    • meeting:read:admin

Why this is temporary: This approach requires manual OAuth app creation and credential management. In v0.2, we're adding one-click OAuth authentication (like gh auth login) where you just authorize dlzoom in your browser and you're done!

2. Configure Credentials

Create a .env file in your working directory:

ZOOM_ACCOUNT_ID=your_account_id_here
ZOOM_CLIENT_ID=your_client_id_here
ZOOM_CLIENT_SECRET=your_client_secret_here

Or set environment variables:

export ZOOM_ACCOUNT_ID="your_account_id"
export ZOOM_CLIENT_ID="your_client_id"
export ZOOM_CLIENT_SECRET="your_client_secret"

Or use a config file:

# config.yaml
zoom_account_id: "your_account_id"
zoom_client_id: "your_client_id"
zoom_client_secret: "your_client_secret"
log_level: "INFO"

3. Download a Recording

dlzoom 123456789

Usage

Basic Commands

Check if recording is available:

dlzoom 123456789 --check-availability

List all recordings for a meeting:

dlzoom 123456789 --list

Download recording (audio + transcript + chat + timeline):

dlzoom 123456789

Download with custom output name:

dlzoom 123456789 --output-name "my_meeting"

Download to specific directory:

dlzoom 123456789 --output-dir ~/Downloads/zoom

Wait for recording to finish processing:

dlzoom 123456789 --wait 30

Password-protected recordings:

dlzoom 123456789 --password "meeting_password"

Advanced Options

Use config file:

dlzoom 123456789 --config config.yaml

Verbose output (see detailed logs):

dlzoom 123456789 --verbose

Debug mode (full API responses):

dlzoom 123456789 --debug

JSON output (for automation):

dlzoom 123456789 --json

Dry run (see what would be downloaded):

dlzoom 123456789 --dry-run

Custom filename template:

dlzoom 123456789\
  --filename-template "{topic}_{start_time:%Y%m%d}"

Custom folder structure:

dlzoom 123456789\
  --folder-template "{start_time:%Y}/{start_time:%m}"

Select specific recording instance (for recurring meetings):

dlzoom 123456789 --recording-id "abc123def456"

Skip Downloads

Skip transcript download:

dlzoom 123456789 --skip-transcript

Skip chat log download:

dlzoom 123456789 --skip-chat

Skip timeline download:

dlzoom 123456789 --skip-timeline

All Options

dlzoom [OPTIONS] MEETING_ID

Options:
  --output-dir, -o PATH          Output directory (default: current directory)
  --output-name, -n TEXT         Base filename (default: meeting_id)
  --verbose, -v                  Show detailed operation information
  --debug, -d                    Show full API responses and trace
  --json, -j                     JSON output mode (machine-readable)
  --list, -l                     List all recordings with timestamps
  --check-availability, -c       Check if recording is ready
  --recording-id TEXT            Select specific recording by UUID
  --wait MINUTES                 Wait for recording processing (timeout)
  --skip-transcript              Skip transcript download
  --skip-chat                    Skip chat log download
  --skip-timeline                Skip timeline download
  --dry-run                      Show what would be downloaded
  --password, -p TEXT            Password for protected recordings
  --log-file PATH                Write structured log (JSONL format)
  --config PATH                  Path to config file (JSON/YAML)
  --filename-template TEXT       Custom filename template
  --folder-template TEXT         Custom folder structure template
  --from-date TEXT               Start date for batch (YYYY-MM-DD)
  --to-date TEXT                 End date for batch (YYYY-MM-DD)
  --help                         Show this message and exit
  --version                      Show version and exit

Template Variables

Use in --filename-template and --folder-template:

  • {topic} - Meeting topic
  • {meeting_id} - Meeting ID
  • {host_email} - Host email address
  • {start_time:%Y%m%d} - Start time (format with strftime codes)
  • {duration} - Meeting duration

Examples:

# Date-based filename
--filename-template "{start_time:%Y%m%d}_{topic}"

# Organized by date
--folder-template "{start_time:%Y}/{start_time:%m}"

# Include host
--filename-template "{host_email}_{topic}_{start_time:%Y%m%d}"

Common Use Cases

Download Latest Recording from Recurring Meeting

dlzoom 123456789 --verbose

Download Specific Instance

# List all instances first
dlzoom 123456789 --list

# Download specific one
dlzoom 123456789 --recording-id "abc123def456"

Automated Pipeline (JSON Output)

dlzoom 123456789 --json > recording.json

Batch Processing

#!/bin/bash
for meeting_id in 111111111 222222222 333333333; do
    dlzoom $meeting_id  --output-dir ./recordings
done

Wait for Recording to Process

# Wait up to 60 minutes for processing
dlzoom 123456789 --wait 60

Troubleshooting

Authentication Failed

Error: Authentication failed

Solution: Check your credentials in .env or environment variables.

Meeting ID Format Invalid

Error: Invalid meeting ID format

Solution: Meeting IDs must be:

  • 9-12 digit numbers (e.g., 123456789)
  • Or UUID format (e.g., abc123XYZ+/=_-)

Recording Not Found

Error: Recording not found

Possible causes:

  • Meeting wasn't recorded
  • Recording not yet processed (use --wait)
  • No permission to access recording
  • Wrong meeting ID

Check availability first:

dlzoom 123456789 --check-availability

ffmpeg Not Found

Error: ffmpeg not found in PATH

Solution: Install ffmpeg:

# macOS
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

Rate Limit Exceeded

Error: Rate limit exceeded

Solution: Wait a few minutes and try again. The tool automatically retries with exponential backoff.

Insufficient Disk Space

Error: Insufficient disk space

Solution: Free up space or use --output-dir to save to a different location.

Configuration Files

JSON Config

{
  "zoom_account_id": "your_account_id",
  "zoom_client_id": "your_client_id",
  "zoom_client_secret": "your_client_secret",
  "output_dir": "./recordings",
  "log_level": "INFO"
}

YAML Config

zoom_account_id: "your_account_id"
zoom_client_id: "your_client_id"
zoom_client_secret: "your_client_secret"
output_dir: "./recordings"
log_level: "INFO"

Use with:

dlzoom 123456789 --config config.yaml

Output Files

Audio file:

  • Format: M4A (AAC audio)
  • Naming: {meeting_id}.m4a or custom via --output-name

Transcript file:

  • Format: VTT (WebVTT)
  • Naming: {meeting_id}_transcript.vtt

Chat log:

  • Format: TXT
  • Naming: {meeting_id}_chat.txt

Timeline:

  • Format: JSON
  • Naming: {meeting_id}_timeline.json
  • Contains: Meeting events (joins, leaves, screen shares, etc.)

Metadata:

  • Format: JSON
  • Naming: {meeting_id}_metadata.json
  • Contains: Meeting info, participants, recording details

Requirements

  • Python 3.8 or higher
  • ffmpeg (for audio extraction)
  • Zoom Server-to-Server OAuth app

Development

# Clone repository
git clone <repo-url>
cd dlzoom

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # or `.venv\Scripts\activate` on Windows

# Install in development mode
pip install -e .

# Run tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=src/dlzoom --cov-report=term-missing

Version

v0.1.0 - Initial release (2025-10-02)

See CHANGELOG.md for detailed release notes.

Roadmap

Planned for future releases:

v0.2 (Next) - OAuth Authentication ๐Ÿš€

  • ๐Ÿ” One-click authentication - No more manual OAuth app setup!

    dlzoom auth login  # Opens browser, authorize, done!
    dlzoom 123456789 # Just works
    
  • ๐Ÿ”„ Automatic token refresh

  • ๐Ÿ‘ค Per-user authentication (no shared credentials)

  • ๐Ÿ”‘ Secure token storage in ~/.dlzoom/credentials

  • ๐Ÿ“ฑ Multiple profiles support

v0.3

  • ๐Ÿ“… Batch download by date range
  • ๐ŸŽจ More output formats (CSV, TSV)
  • ๐Ÿ” Token encryption (system keychain)

Known Limitations

Feature Limitations

  • No standalone "list all recordings" command (requires meeting ID)
  • Audio quality parameter not exposed via CLI (internal only)
  • No batch download by date range
  • No listing of all meetings/recordings

License

MIT License - see LICENSE file for details.

Contributing

We welcome contributions! Here's how you can help:

Quick Start for Contributors

  1. Fork and clone the repository

  2. Set up development environment:

    python3.11 -m venv .venv
    source .venv/bin/activate
    pip install -e ".[dev]"
    
  3. Run tests:

    pytest tests/ -v
    
  4. Make your changes and ensure tests pass

  5. Submit a pull request

Guidelines

  • Follow Conventional Commits for commit messages
  • Add tests for new features
  • Update documentation as needed
  • Ensure all CI checks pass

Commit Message Format

<type>(<scope>): <subject>

Examples:
feat(cli): add support for CSV export
fix(auth): handle expired OAuth tokens
docs: update installation instructions

Types:

  • feat - New feature
  • fix - Bug fix
  • docs - Documentation
  • test - Tests
  • refactor - Code refactoring
  • chore - Maintenance

For detailed guidelines, see CONTRIBUTING.md.

Security

Security is important to us. If you discover a security vulnerability:

Security Features

  • โœ… Credentials never logged or exposed
  • โœ… Input validation (prevents injection attacks)
  • โœ… Atomic file operations
  • โœ… Automatic security scanning (Trivy)
  • โœ… Docker images run as non-root user

Support

For issues and questions:

Credits

Built with:

Acknowledgments

Thanks to all contributors and the open source community.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dlzoom-0.1.0.tar.gz (49.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dlzoom-0.1.0-py3-none-any.whl (36.3 kB view details)

Uploaded Python 3

File details

Details for the file dlzoom-0.1.0.tar.gz.

File metadata

  • Download URL: dlzoom-0.1.0.tar.gz
  • Upload date:
  • Size: 49.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dlzoom-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a990ce7d8f4cde26dbbefd0da862730c653efd8779178a5708fccb2d20753a3d
MD5 420801b2969458416f98558d2b4ffff2
BLAKE2b-256 406110125774aa0bbce2453f7485e07f53c82838cd882fbaab0327afe3334b78

See more details on using hashes here.

Provenance

The following attestation bundles were made for dlzoom-0.1.0.tar.gz:

Publisher: release.yml on yaniv-golan/dlzoom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dlzoom-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dlzoom-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dlzoom-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d67dcd9a1521aa8d586fa49ca62b5c4e468fa9a4ca457d87cfdf6c4ba9107fb6
MD5 c8c6be1575a74925ee222dc91a02a6c5
BLAKE2b-256 fa430ee622b8e973cf8fe408f7e88cc03d431f0490c9ac10797c95acd18cc7bf

See more details on using hashes here.

Provenance

The following attestation bundles were made for dlzoom-0.1.0-py3-none-any.whl:

Publisher: release.yml on yaniv-golan/dlzoom

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page