Upload PDFs and generate clean lecture-style audio using OpenAI, plus a realtime streaming lecture mode. The API runs on FastAPI and a background worker. A CLI is included for batch processing.
python -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .Create .env from the example:
cp .env.example .envSet OPENAI_API_KEY in .env.
uvicorn app.main:app --reloadEndpoints (core):
POST /uploadGET /jobs/{job_id}GET /jobs/{job_id}/scriptGET /jobs/{job_id}/audioGET /feed.xmlGET /health
Endpoints (lecture library + realtime):
GET /lecturesGET /lectures/{lecture_id}GET /lectures/{lecture_id}/chunk?index=NGET /lectures/{lecture_id}/context?index=N&window=30GET /lectures/{lecture_id}/scriptGET /lectures/{lecture_id}/realtime-instructionsPOST /lectures/{lecture_id}/realtime-token
- Offline PDF analysis + script writing:
OPENAI_MODEL_ANALYSIS(defaultgpt-5.2, fallbackgpt-5-mini). - Realtime streaming voice:
OPENAI_REALTIME_MODEL(defaultgpt-realtime) withOPENAI_REALTIME_VOICE.
The analysis model is not a realtime audio model. The iOS client connects directly to OpenAI Realtime using an ephemeral token from this server.
- Client requests
POST /lectures/{lecture_id}/realtime-tokento mint an ephemeral token. - Client establishes WebRTC to OpenAI Realtime using the token.
- Client fetches
GET /lectures/{lecture_id}/chunk?index=Nand sends chunk text into the Realtime session. - On STOP, client fetches
GET /lectures/{lecture_id}/context?index=N&window=30and sends the question plus context. - On OK, resume from the next chunk index.
Process a folder of PDFs without running the server:
lecture-to-audio /path/to/pdfsIf you already processed PDFs locally and want to push your data/ folder (scripts + chunks) to the server:
python tools/process_and_upload.py --sync-data data --server http://YOUR_SERVER_IP:8002This uploads any missing lectures from data/scripts and data/chunks to the server.
Set IOS_SYNC_DIR to an iCloud Drive folder. Example macOS paths:
~/Library/Mobile Documents/com~apple~CloudDocs/LectureAudio~/Library/Mobile Documents/com~apple~CloudDocs/Podcasts/LectureAudio
Final output name format:
Title - YYYYMMDD - jobid.m4a
Set PUBLIC_BASE_URL in .env (for example your local tunnel or server URL), then subscribe in a podcast app to:
PUBLIC_BASE_URL/feed.xml
- Large PDFs: reduce
MAX_PAGES_PER_CHUNKor use smaller input PDFs. - Long TTS: audio is generated in segments and concatenated with
ffmpegif available. Ifffmpegis missing and output format ism4a, the server will return an.m3uplaylist. - OpenAI errors: verify
OPENAI_API_KEYand model names in.env.
pip install -e .[dev]
pytest- Data directories are under
data/for uploads, extracted chunks, scripts, audio, RSS, and lecture chunks. - This MVP supports PDF processing; image and docx inputs are validated but not yet processed.