Zoom to Google Drive Transfer
Automated pipeline that downloads Zoom recordings, converts VTT transcripts to Google Docs, and smart-names files using Google Calendar event matching. One command, all recordings transferred.
What It Does
- Downloads all Zoom cloud recordings
- Converts VTT transcripts to Google Docs
- Smart-names files from Google Calendar
- Organizes by year/month folders
- Logs every transfer to a spreadsheet
- Handles Zoom's 30-day API pagination
Key Files
| File Structure | |
|---|---|
zoom_to_drive.py | Main orchestrator |
zoom_client.py | Zoom API wrapper |
gdrive_client.py | Google Drive + Docs API |
naming_engine.py | 3-tier smart naming |
naming_rules.json | Time-based naming rules |
state_manager.py | Transfer state tracking |
python zoom_to_drive.py and it handles everything — API pagination, file downloads, naming, Google Drive upload, transcript conversion, and logging.Transfer Pipeline
End-to-end flow from Zoom cloud storage to organized Google Drive folders. Each recording goes through naming, download, and upload stages.
Pipeline Flow
Per-Recording Steps
-
Check state Skip if already transferred (state_manager tracks by meeting UUID + file type)
-
Determine smart name 3-tier naming: Calendar match → Time rules → Zoom topic fallback
-
Create folder structure Year/Month folders created on demand (e.g.,
Zoom Recordings/2026/02 - February) -
Download from Zoom MP4 video + VTT transcript (if available). Uses download_url with access_token.
-
Upload to Google Drive Resumable upload for large files. Sets file name to smart name.
-
Convert VTT transcript Parse VTT, strip timestamps, format as readable text, create Google Doc.
-
Log transfer Append row to Transfer Log spreadsheet with date, name, source, status.
Smart Naming (3 Tiers)
The naming engine uses a 3-tier fallback system to give each recording a meaningful name instead of Zoom's default UUID-based filenames.
Tier 1: Google Calendar Match (92.9%)
Looks up the recording's start time against Google Calendar events. If a calendar event overlaps the Zoom meeting time window, uses the event title as the file name.
2026-02-15 - Client Call - GloboTech.mp4
Tier 2: Time-Based Rules (4.8%)
When no calendar match is found, falls back to naming_rules.json. Rules map time windows and days to recurring meeting names.
Tier 3: Zoom Topic Fallback (2.3%)
Last resort: uses the Zoom meeting topic as the file name. This is Zoom's default meeting name (e.g., "Shane's Personal Meeting Room" or "Quick Sync").
Naming Tier Stats (280 recordings)
| Naming Source Distribution | |||
|---|---|---|---|
| Tier 1 — Calendar | 260 recordings | 92.9% | Primary |
| Tier 2 — Time Rules | 13 recordings | 4.8% | Fallback |
| Tier 3 — Zoom Topic | 7 recordings | 2.3% | Last Resort |
Zoom API Handling
Zoom's API limits recording list queries to 30-day windows. The pipeline chunks date ranges automatically and handles pagination, rate limits, and auth token refresh.
30-Day Chunking
13 months = ~14 API chunks, each ≤ 30 days
API Configuration
| Zoom API Settings | |
|---|---|
| Auth | Server-to-Server OAuth (JWT deprecated) |
| Max range | 30 days per request |
| Page size | 300 recordings per page |
| Rate limit | 10 requests/second (heavy) |
| Download URLs | Require access_token param |
| Token TTL | 1 hour, auto-refreshed |
Error Handling
- 401 Unauthorized: Auto-refresh OAuth token and retry
- 429 Rate Limited: Exponential backoff (1s, 2s, 4s, 8s)
- 404 Not Found: Recording expired or deleted — skip and log
- 500 Server Error: Retry up to 3 times with 5s delay
- Download timeout: 5-minute timeout for large files, retry once
Google Drive Integration
Recordings are uploaded to an organized folder structure. VTT transcripts are converted to searchable Google Docs. Uses Google Drive API v3 and Google Docs API.
Folder Structure
Upload Process
- Check/create year foldere.g., "2026"
- Check/create month foldere.g., "02 - February"
- Resumable uploadLarge files use resumable protocol
- Set metadataName, MIME type, parent folder
VTT Transcript Conversion
- Parse VTT fileExtract text, strip timestamps and metadata
- Format contentClean paragraphs with speaker labels
- Create Google DocUpload as Google Docs MIME type
- Name with "(Transcript)"Same smart name + suffix
Google API Authentication
| Auth Configuration | |
|---|---|
| credentials.json | OAuth client credentials (from Google Cloud Console) |
| token.json | Auto-generated refresh token (persisted between runs) |
| Scopes | drive.file + docs + calendar.readonly |
| Project ID | 851550492652 (shared with Accounting tools) |
Transfer Log
Every transfer is logged to a Google Sheets spreadsheet for auditing and tracking. Includes source details, naming tier used, and transfer status.
Log Columns
| Transfer Log Spreadsheet | ||
|---|---|---|
| Transfer Date | When the transfer was executed | Date |
| Meeting Date | Original Zoom meeting date/time | Date |
| Original Name | Zoom's default file name (UUID-based) | Text |
| Smart Name | Final name assigned by naming engine | Text |
| Naming Tier | Which tier was used: Calendar / Rules / Topic | Category |
| File Type | MP4, VTT, M4A (audio-only), etc. | Text |
| File Size | Size in MB | Number |
| Duration | Meeting duration in minutes | Number |
| Drive Link | Direct link to uploaded file in Google Drive | URL |
| Status | Success, Skipped, or Error (with reason) | Status |
state_manager.py tracks which files have been processed (local JSON). The Transfer Log spreadsheet is the audit trail (cloud). Both are updated together, but the state file is what prevents duplicate transfers.Quick Start Guide
Get up and running with the Zoom to Google Drive transfer pipeline.
Prerequisites
- Python 3.10+
- Zoom Server-to-Server OAuth app (in
.env) - Google Cloud project with Drive, Docs, Calendar APIs enabled
credentials.jsonfrom Google Cloud Console
Setup Steps
-
Install dependencies
pip install -r requirements.txt -
Configure .env Set
ZOOM_ACCOUNT_ID,ZOOM_CLIENT_ID,ZOOM_CLIENT_SECRET -
Place credentials.json Google OAuth client credentials in the project root
-
First run (auth flow)
python zoom_to_drive.py— opens browser for Google OAuth consent on first run -
Subsequent runs Same command. Picks up from last transfer, skips already-done files.
Common Commands
DO
- Run transfers regularly (Zoom deletes cloud recordings)
- Add naming rules for recurring meetings
- Keep
credentials.jsonandtoken.jsongitignored - Use
--dry-runbefore large batch transfers - Check the Transfer Log for any Error status rows
DON'T
- Don't delete the state file unless you want full re-transfer
- Don't share
credentials.jsonortoken.json - Don't run multiple instances simultaneously (state conflicts)
- Don't exceed Zoom API rate limits (10 req/s)
- Don't manually rename files in Drive (breaks dedup)