mirror of
https://github.com/forkless/Piperless.git
synced 2026-08-17 01:01:48 +02:00
246 lines
12 KiB
Markdown
246 lines
12 KiB
Markdown
# Piperless — Audio Transcripts for WordPress
|
||
|
||
**Turn your WordPress posts into high-quality audio transcripts using local, open-source neural TTS. No API keys. No subscriptions. No data leaving your server.**
|
||
|
||
> **Transparency note:** Piperless was developed using AI-assisted CLI tools (DeepSeek V4 Pro). Every line of code, security review, and translation was generated through prompt-driven development — then reviewed, tested, and hardened by a human. This weekend project started out of curiosity for what AI technology can do. Total development cost: one working day and less than the price of a cup of coffee in AI tokens.
|
||
|
||
|
||
## What It Does
|
||
|
||
Piperless converts every published post into a natural-sounding audio transcript using the [Piper](https://github.com/rhasspy/piper) text-to-speech engine. It generates audio automatically on publish, caches the results, and embeds a customizable HTML5 audio player in your content.
|
||
|
||
- **Visually impaired** readers can listen instead of read
|
||
- **Dyslexic** readers get an alternative format
|
||
- **Commuting** readers can consume posts as audio
|
||
- **Non-native speakers** benefit from hearing correct pronunciation
|
||
|
||
|
||
## Features
|
||
|
||
- **Automatic generation** — optionally generate audio when a post is published. No per-post action required.
|
||
- **6 player themes** — Classic, Minimal, Modern Dark, Ron Burgundy, Dan Rather Blue, and Custom CSS. Match your brand.
|
||
- **Per-post overrides** — customize voice, language, quality, player style, and placement for individual posts via the Gutenberg sidebar.
|
||
- **Content-addressed caching** — identical text + voice + language always produces the same audio file. Never regenerate the same content twice.
|
||
- **Multi-language** — Piper supports 20+ languages. Install the voice models you need and Piperless auto-discovers them.
|
||
- **Voice aliases** — rename technical model names like `en_US-lessac-low` to "American Female" in your admin panel.
|
||
- **MP3 & Opus encoding** — auto-converts Piper's WAV output to MP3 or Opus using ffmpeg. Opus offers better quality at lower bitrates. Falls back to WAV if ffmpeg is unavailable.
|
||
- **Smart text extraction** — uses the post excerpt when available to avoid reading embedded content (YouTube, Twitter, third-party embeds), decimal numbers, and other artifacts that produce garbled speech. Falls back to the full post body when no excerpt is set.
|
||
- **No external services** — Piper runs on your server. Text never leaves your infrastructure. GDPR-compliant by architecture.
|
||
- **Production-hardened** — 29/29 security audit clearance. Rate limiting, authorization layering, process timeout guards, open_basedir aware.
|
||
- **Dashboard widget** — at-a-glance storage stats on the WordPress dashboard (togglable via Screen Options). File counts and sizes by audio format, posts awaiting transcription, and disk usage bar.
|
||
- **8 admin languages** — Dutch, German, French, Spanish, Chinese (Simplified), Japanese, Brazilian Portuguese, and Italian translations included.
|
||
|
||
|
||
## Why the Excerpt Matters
|
||
|
||
Piper reads text exactly as it appears. Without careful text selection, you get:
|
||
|
||
- **Embedded content read verbatim** — YouTube video descriptions, Twitter embed text, and third-party widget content get read as part of your article, confusing listeners.
|
||
- **Decimal numbers breaking sentence flow** — "The price increased by 3.5 percent" becomes "The price increased by 3" [pause] "5 percent" because Piper interprets the period as a sentence boundary.
|
||
- **Shortcodes and markup noise** — unrendered shortcodes and HTML artifacts in the post body produce gibberish audio.
|
||
|
||
Piperless solves this by **using the WordPress excerpt field first**. Write a clean, spoken-word version of your post in the excerpt — it's read as-is. If no excerpt exists, Piperless falls back to the post body with an optional filter to skip embedded blocks.
|
||
|
||
**Pro tip:** Think of the excerpt as your "audio script." It doesn't replace the post — it's the version that sounds natural when read aloud.
|
||
|
||
|
||
## Requirements
|
||
|
||
| Component | Minimum | Notes |
|
||
|-----------|---------|-------|
|
||
| WordPress | 6.0+ | Self-hosted |
|
||
| PHP | 8.0+ | |
|
||
| Piper TTS | Installed on server | [GitHub](https://github.com/rhasspy/piper) |
|
||
| Voice models | `.onnx` + `.json` files | 20+ languages available |
|
||
| ffmpeg | Optional | Auto-detected. Converts WAV → MP3 |
|
||
| Server | VPS or dedicated | Shared hosting cannot install Piper |
|
||
|
||
**Piperless will not work on shared hosting.** It requires shell access to install Piper and the ability to run system binaries via `proc_open`.
|
||
|
||
|
||
## Quick Start
|
||
|
||
### 1. Install Piper
|
||
|
||
```bash
|
||
# Download Piper binary for your platform from:
|
||
# https://github.com/rhasspy/piper/releases
|
||
|
||
# Or install via package manager (where available)
|
||
```
|
||
|
||
### 2. Download Voice Models
|
||
|
||
Download `.onnx` and `.onnx.json` files for your languages from the [Piper voice repository](https://huggingface.co/rhasspy/piper-voices). Place them in a directory accessible to PHP.
|
||
|
||
```bash
|
||
/opt/var/piper/voices/
|
||
├── en_US-lessac-low.onnx
|
||
├── en_US-lessac-low.onnx.json
|
||
├── en_US-amy-medium.onnx
|
||
├── en_US-amy-medium.onnx.json
|
||
├── nl_NL-ml-medium.onnx
|
||
└── nl_NL-ml-medium.onnx.json
|
||
```
|
||
|
||
### 3. Install Piperless
|
||
|
||
1. Download the latest release ZIP
|
||
2. Go to WordPress Admin → Plugins → Add New → Upload Plugin
|
||
3. Choose the ZIP file and click "Install Now"
|
||
4. Activate the plugin
|
||
|
||
### 4. Configure
|
||
|
||
Go to **Settings → Piperless** and set:
|
||
|
||
- **Piper Binary Path** — absolute path to the Piper executable (e.g., `/opt/bin/piper`)
|
||
- **Models Directory** — path to your `.onnx` voice models
|
||
- **Default Voice** — choose a default voice from the auto-discovered list
|
||
- Click **Test Connection** to verify Piper is working
|
||
|
||
### 5. Generate Your First Audio
|
||
|
||
Open any post in the block editor. In the Piperless sidebar panel, click **Generate Audio**. The audio player will appear in your post automatically based on your placement settings.
|
||
|
||
|
||
## Admin Panel
|
||
|
||
Piperless adds a settings page under **Settings → Piperless** with 8 tabs:
|
||
|
||
| Tab | Purpose |
|
||
|-----|---------|
|
||
| **Piper** | Configure the TTS engine, browse and preview voice models, set voice aliases |
|
||
| **Content** | Auto-generate on publish, skip embedded content during text extraction |
|
||
| **Styling** | Player theme, placement, custom CSS, player title, duration display |
|
||
| **Performance** | Piper process timeout (30–3600s), audio endpoint rate limiting |
|
||
| **Cache Management** | Stats, cache browser, clear orphaned files, flush entire cache |
|
||
| **Logs** | Logging level configuration, live log viewer, clear log |
|
||
| **About** | Version, GitHub repository, and support links |
|
||
| **Dashboard** | WordPress admin dashboard widget with audio storage stats and disk usage |
|
||
|
||
|
||
## Player Themes
|
||
|
||
Six built-in themes plus unlimited custom CSS:
|
||
|
||
| Theme | Description |
|
||
|-------|-------------|
|
||
| **Classic** | Blue accent, clean borders |
|
||
| **Minimal** | Clean, understated |
|
||
| **Modern Dark** | Dark background |
|
||
| **Ron Burgundy** | Bold burgundy |
|
||
| **Dan Rather Blue** | Classic navy |
|
||
| **Custom CSS** | Full control — base theme with your own styles |
|
||
|
||
Each theme is a standalone CSS file. Switch themes instantly from the Styling tab.
|
||
|
||
|
||
## Accessibility
|
||
|
||
Piperless was built with accessibility in mind:
|
||
|
||
- **Screen reader landmark** — player container exposes `role="region"` and `aria-label="Audio transcript: Post Title"`
|
||
- **ARIA labels** — play/pause button and volume control are properly labeled
|
||
- **Keyboard navigation** — player is a navigable region
|
||
- **Content-as-transcript** — since the audio is generated from the post text, the text itself serves as the transcript for WCAG compliance
|
||
|
||
|
||
## Security
|
||
|
||
Piperless shells out to system binaries. It was built with defense-in-depth from the start:
|
||
|
||
- **Command injection prevention** — `escapeshellarg()` on every shell argument. Zero `escapeshellcmd()` calls.
|
||
- **Authorization** — REST endpoints verify per-post ownership, not just capability checks
|
||
- **Rate limiting** — configurable requests/minute per IP on the public audio proxy
|
||
- **Path traversal prevention** — cache keys regex-validated, model paths stripped from API responses
|
||
- **Error capture** — `error_clear_last()` before every suppressed filesystem call for deterministic diagnostics
|
||
- **Log file security** — `chmod 0600` after every write
|
||
- **Process isolation** — `set_time_limit()` guards with configurable timeouts
|
||
- **open_basedir aware** — string-prefix matching before any filesystem call to prevent hangs
|
||
|
||
Comprehensive review: **29/29 categories cleared. 1 logic bug found and fixed. Zero open findings.** [See full audit →](AUDIT.md)
|
||
|
||
|
||
## Translation
|
||
|
||
Piperless ships with complete translations for:
|
||
|
||
| Language | Locale | Coverage |
|
||
|----------|--------|----------|
|
||
| Dutch | nl_NL | 120/120 |
|
||
| German | de_DE | 120/120 |
|
||
| French | fr_FR | 120/120 |
|
||
| Spanish | es_ES | 120/120 |
|
||
| Chinese (Simplified) | zh_CN | 120/120 |
|
||
| Japanese | ja | 120/120 |
|
||
| Portuguese (Brazil) | pt_BR | 120/120 |
|
||
| Italian | it_IT | 120/120 |
|
||
|
||
The admin panel, Gutenberg sidebar, and frontend player are fully translated. See `languages/` for `.po` and `.mo` files.
|
||
|
||
|
||
## Filters & Hooks
|
||
|
||
### Filters
|
||
|
||
- `piperless_post_types` — post types supported by the plugin (default: `['post', 'page']`)
|
||
- `piperless_quality_tiers` — recognized quality labels in model filenames
|
||
- `piperless_skip_blocks` — Gutenberg block types to skip during text extraction
|
||
- `piperless_ffmpeg_paths` — paths to probe for ffmpeg auto-detection
|
||
|
||
### Shortcodes
|
||
|
||
- `[piperless_player]` — render the audio player for the current post
|
||
- `[piperless_player post_id="123"]` — render the player for a specific post
|
||
|
||
|
||
## Development
|
||
|
||
Piperless is built as 8 PHP classes with separation of concerns:
|
||
|
||
```
|
||
includes/
|
||
├── class-plugin.php # Entry point, singleton, hook wiring
|
||
├── class-piper.php # Piper CLI wrapper (3 interface modes)
|
||
├── class-transcriber.php # Text extraction, generation pipeline, mutex
|
||
├── class-cache-manager.php # Content-addressed file cache, MP3 conversion
|
||
├── class-gutenberg.php # Block editor sidebar, REST API endpoints
|
||
├── class-settings.php # Admin panel (8 tabs), AJAX handlers
|
||
├── class-dashboard.php # Dashboard widget with file stats and disk usage
|
||
├── class-player.php # Frontend HTML5 player (6 themes)
|
||
└── class-logger.php # PSR-3 logger with dual-channel fallback
|
||
```
|
||
|
||
### Build & Tooling
|
||
|
||
The `Makefile` wraps the build and translation toolchain:
|
||
|
||
```
|
||
make build → Create piperless-X.Y.Z.zip
|
||
make translations → Extract .pot → JSON, sync to all locales
|
||
make json2po → Convert JSON translations back to .po/.mo
|
||
make check-translations → Validate translation integrity
|
||
make lock-translations → Lock all locales for translation work
|
||
make unlock-translations → Release all translation locks
|
||
make translation-status → Show lock/completion for each locale
|
||
make clean → Remove build artifacts
|
||
```
|
||
|
||
All tools run as standalone shell scripts in `tools/` — the Makefile is a convenience wrapper.
|
||
|
||
See `doc/index.html` for full developer documentation with architecture diagram, method tables, and security model.
|
||
|
||
|
||
## License
|
||
|
||
MIT-licensed. Piperless is free and open-source. Piper TTS is also MIT-licensed. Voice models vary — check individual model licenses.
|
||
|
||
|
||
## Links
|
||
|
||
- **Piper TTS:** [github.com/rhasspy/piper](https://github.com/rhasspy/piper)
|
||
- **Piper Voices:** [huggingface.co/rhasspy/piper-voices](https://huggingface.co/rhasspy/piper-voices)
|
||
- **Support:** [forkless.com](https://forkless.com)
|
||
- **Contact:** devs@forkless.com
|