- Python 90.4%
- JavaScript 4%
- CSS 3.7%
- HTML 1%
- Dockerfile 0.9%
Flip every platform flag from WINDOWS/WIN32 to MACOS so the file is internally consistent with a real Mac-authored .pro/.proPlaylist, which the macOS renderer treats as native: - ApplicationInfo.platform 2->1, with platform_version bumped 10->13 (macOS Ventura) so it doesn't read as "macOS 10" - media URL platform (_pb_media_url) 2->1 - playlist item document_path URL platform 2->1 Values match real PP-authored files. Cross-platform import on Windows is handled by the playlist's uses_relative_urls flag (real platform=1 files open fine on Windows); to be verified on the Windows machine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| data | ||
| docs | ||
| src | ||
| static | ||
| templates | ||
| tools | ||
| .containerignore | ||
| .gitignore | ||
| app.py | ||
| Containerfile | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
cspp — ChurchSuite → ProPresenter Playlist Generator
Generates a ProPresenter 7 .proPlaylist file from a ChurchSuite service plan URL.
What it does
- Loads a ChurchSuite plan URL (handles Cloudflare protection via a real browser)
- Identifies songs vs. other items (prayer, reading, sermon, communion, …)
- Fetches lyrics where possible (see Lyric Sources)
- Builds a
.proPlaylistzip archive:- Each song → a
.propresentation with slides grouped as Intro / Verse / Chorus / Bridge / … / Outro - Each non-song → a ProPresenter placeholder item (titled appropriately)
- Each song → a
- Delivers the file as a browser download
Running locally
python app.py
# open http://localhost:5000
Dependencies (Python 3.12+):
pip install -r requirements.txt
playwright install chromium
Running in a container
# Build
docker build -f Containerfile -t cspp .
# or
podman build -f Containerfile -t cspp .
# Run
docker run -p 5000:5000 cspp
# open http://localhost:5000
The official Playwright image is used as the base, so no extra browser setup is needed.
CCLI SongSelect lyrics (optional)
Two auth strategies are supported, tried in order:
Option A — Cookie file (recommended, works everywhere)
The SongSelect login page is protected by Cloudflare Turnstile which blocks automated browsers. The reliable workaround is to export your cookies from a real browser session:
- Log into https://songselect.ccli.com/ in Chrome or Edge.
- Install the Cookie-Editor extension (by Fanboy).
- Click the extension icon → Export → Export as JSON → save the file.
- Pass the path to the container:
docker run -p 5000:5000 \
-v /path/to/ccli_cookies.json:/cookies.json:ro \
-e CCLI_COOKIES_FILE=/cookies.json \
cspp
Cookies typically stay valid for 30 days (longer with "Keep me signed in"). Re-export when lyrics stop being fetched.
Option B — Username / password
Uses undetected-chromedriver, which patches the ChromeDriver binary so
Cloudflare Turnstile passes automatically (typically within 3 seconds).
Requires Google Chrome to be installed on the system.
CCLI_USERNAME=you@example.com CCLI_PASSWORD=yourpassword python app.py
Or in Docker/Podman (Chrome is installed in the container image):
docker run -p 5000:5000 \
-e CCLI_USERNAME=you@example.com \
-e CCLI_PASSWORD=yourpassword \
cspp
Without either option, songs will get blank placeholder presentations.
Project structure
app.py Flask entry point (routes: /, /preview, /generate)
src/
churchsuite.py Playwright-based plan scraper
ccli.py CCLI SongSelect lyric fetcher (UCD login or cookie injection)
lyrics.py Lyric fetching pipeline (manual → CCLI → plan HTML)
propresenter/
proto_utils.py Low-level protobuf binary encoding
presentation.py .pro file builder (slides, groups, RTF text)
playlist.py .proPlaylist ZIP assembler
templates/index.html Web UI
static/{style.css,app.js}
Containerfile
Lyric sources
Tried in order:
- CCLI SongSelect – requires auth config (see above); fetches all songs in one browser session
- ChurchSuite plan HTML – lyrics sometimes embedded in the rendered plan page
Songs with no lyrics get a minimal blank presentation (Intro + blank slide + Outro). The operator can link to an existing library file in ProPresenter if needed.
Playlist format notes
.proPlaylist is a ZIP archive containing:
| File | Description |
|---|---|
data |
Protobuf-encoded playlist (undocumented wrapper + rv.data.Playlist) |
SongName.pro |
Protobuf-encoded rv.data.Presentation for each song |
The proto schemas are from ProPresenter7-Proto.
Planned / future work
- Background images – expose a set of stock images; let user pick one per song or globally
- Reading slides – replace the "Reading" placeholder with slides showing the Bible text
- Prayer slides – simple "Prayer" display slide
- ProPresenter library matching – detect songs already in the library and reference them by path instead of bundling a new
.profile - More lyric sources – OpenSong library, Planning Center songs API