A Python automation system built to eliminate manual, repetitive post-session processing for a live EdTech operations workflow — recording downloads, attendance/chat extraction, and accurate trainer duration calculation.
Context: Built independently while working as an Operations Executive managing live online training sessions across multiple concurrent batches (executive education programs backed by IITs, IIMs, and MIT). This wasn't an assigned task — it was built after identifying that the team was spending several hours daily on manual, repetitive post-session work. The system was adopted by the operations team and used in production.
Note: All company-specific data, credentials, learner records, and internal identifiers have been removed from this repository. This is the core automation logic only.
For every live training session, the system automatically:
- Identifies valid sessions ready for processing (
session_finder.py) — handles multiple session states (valid, ongoing, generating, needs review) with caching and fallback logic. - Downloads recordings from the Webex API in parallel using a thread
pool (
recording.py). - Extracts attendance and chat transcripts (
attendance.py,chat.py). - Calculates accurate trainer teaching duration (
duration.py) by:- Identifying the trainer via audio/screen-share analytics
- Detecting "hard gaps" (dropped audio/video for 5+ minutes) and "soft gaps" (partial signal degradation for 10+ minutes)
- Using Gemini AI to classify ambiguous gaps (break vs. technical issue)
- Excluding waiting time, breaks, and network disruptions from the final duration used for compliance and billing records
- Writes results to Google Sheets (
utils/gsheet.py) with retry logic, idempotent skip-checks, and color-coded status flags. - Auto-terminates stale sessions via a background scheduler
(
scheduler/terminator.py). - Creates WordPress unit pages automatically (
wordpress_automation/unit_creation.py) — uses Playwright browser automation to read a queue of pending units from a Google Sheet, log into the LMS, and create/populate each unit page (title, video link, format/metadata) without manual data entry.
run.py Entry point — orchestrates the pipeline with
multi-threaded workers + a background prefetch thread
core/
auth.py Webex OAuth token management (refresh flow)
webex_client.py Thin wrapper around Webex REST + Analytics APIs
__init__.py Shared Google Sheets client init
modules/
session_finder.py Session discovery, validation, state handling
recording.py Parallel recording download
attendance.py Attendance report extraction
chat.py Chat transcript extraction
duration.py Trainer duration calculation engine (core logic)
utils/
gsheet.py Google Sheets read/write helpers
console.py Logging/output helpers
scheduler/
terminator.py Background job to close out stale sessions
threshold.py Standalone script for gap-detection threshold tuning
wordpress_automation/
unit_creation.py Browser automation (Playwright) that logs into the
LMS and creates unit pages from a Google Sheet queue
- Python 3 —
concurrent.futures.ThreadPoolExecutorfor parallel downloads - Webex REST + Analytics APIs — session, recording, and quality-metrics data
- Google Sheets API (via
gspread) — data storage and team-facing dashboard - Google Gemini API — gap classification for ambiguous session interruptions
- Google Service Account — auth for Sheets access
- Modular structure — each concern (session discovery, recording, attendance, duration) is isolated so any one piece can be modified or swapped without touching the others.
- Parallel processing — recordings for multiple sessions download concurrently instead of sequentially, since this was previously a significant chunk of daily manual time.
- Gap detection over naive timestamps — simple start/end timestamps overstate a trainer's actual teaching time. The duration engine analyzes audio bitrate and video fps at a per-minute resolution to detect real interruptions instead of guessing.
This was an internally used, actively refined tool — not a polished open
source library. It went through multiple rounds of debugging based on real
production usage (see inline comments in duration.py for iteration notes).
Credentials, learner data, and internal identifiers are intentionally
excluded from this repository; see .env.example for the expected
configuration shape.
- Replaced a manual, multi-person daily workflow (5–7 hours of collective effort across 6–7 people) with a single automated pipeline requiring roughly 30–60 minutes of team QA and exception handling.
- Processed 350+ live sessions over 12 months in production use.
- Adopted by the operations team within weeks of initial rollout.
- Eliminated a separate, fully manual WordPress content-publishing workflow via the unit-creation module.
This repository contains the modules I retained personal copies of. The production system had 10 components in total — 5 are included here, and 5 remained on company infrastructure after my exit and aren't reproduced:
Included in this repository:
- WordPress unit/course page creation (Playwright)
- Valid session detection and flagging (
session_finder.py) - Attendance download (
attendance.py) - Chat transcript download (
chat.py) - Recording download (
recording.py) + trainer duration calculation (duration.py)
Part of the production system, not included here: 6. Automated upload of attendance/chat files to Google Drive, organized into date-wise (day/week/month/year) subfolders for cross-team access 7. Automated video upload to Vimeo, with the resulting link written back to the Google Sheet for linking to the unit page 8. Automated Webex meeting scheduling (name, password, and settings) driven from Google Sheet input 9. A scheduling-conflict check to catch overlapping concurrent meetings caused by batch merges/splits 10. Automated feedback fetching and sorting via Google Apps Script (manual trigger currently; planned as a time-based auto-trigger)
Planned future work: converting the tool into a desktop app with a UI, storing session data natively instead of depending on Google Sheets.
pip install -r requirements.txt
cp .env.example .env # fill in your own credentials
python run.pyBuilt by Shreyansh Raj