End‑to‑end pipeline to turn WordPress posts into audio files (IT/EN) using LLM cleaning + Translation + Google Cloud TTS, orchestrated with n8n, and automatically published on dedicated WordPress pages.
- n8n orchestrates ingest, text cleaning, translation, TTS, and page updates.
- Cloud Run exposes a
/long-tts
endpoint that generates.wav
files and stores them in Google Cloud Storage (GCS). - Google Sheets acts as the tracking/queue layer.
/n8n-workflows
├─ WordPress_Automations__Part1.json
└─ WordPress_Automations__Part2.json
/GCP Code
├─ Dockerfile.txt
├─ main.py
└─ requirements.txt
/images
├─ WordPress_Automations__Part1.png
└─ WordPress_Automations__Part2.png
The workflow JSON files contain placeholders
INSERT_YOUR_ID_HERE
where project‑specific IDs were present (credential IDs, Google Sheets document ID/sheet name, WordPress page IDs). Replace them with your values before running.
- n8n self‑hosted (Docker or VM).
- WordPress site with REST API enabled (e.g., Application Passwords).
- Google Cloud project with:
- Cloud Text‑to‑Speech API enabled,
- Cloud Translation API (for Google Translate node in n8n),
- Google Sheets API (if n8n uses a service account to access Sheets),
- a GCS bucket for audio
.wav
files.
- Service Account with permissions on GCS and Sheets/Translate (for n8n and/or the Cloud Run service).
- A Google Sheet with columns:
ID, Title, Date, Content, Link, Status
.
Files are in /GCP Code
:
main.py
→ FastAPI app exposing a TTS endpoint on port 8080.requirements.txt
→fastapi
,uvicorn
,google-cloud-texttospeech
, etc.Dockerfile.txt
→ image build recipe.
Edit the top‑level constants to match your project:
BUCKET_NAME = "your-bucket-name"
PROJECT_ID = "your-gcp-project-id"
For production, prefer environment variables/Secret Manager. Constants are used here for clarity.
From /GCP Code
:
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
# Build
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/long-tts
# Deploy
gcloud run deploy long-tts \
--image gcr.io/YOUR_PROJECT_ID/long-tts \
--region europe-west1 \
--platform managed \
--allow-unauthenticated
Note the service URL: https://<long-tts-xxxx>.run.app
The endpoint consumed by n8n is:
https://<long-tts-xxxx>.run.app/long-tts
curl -X POST "https://<long-tts-xxxx>.run.app/long-tts" \
-H "Content-Type: application/json" \
-d '{
"text": "Hello from Cloud Run",
"language": "en-US",
"voice": "en-US-Neural2-D",
"filename": "test.wav"
}'
You should get JSON with gcs_uri
and filename
. Check the file in your GCS bucket.
- Create/identify two static pages:
- VoiceOvers – IT
- VoiceOvers – EN
- Note their page IDs (from the edit URL or via REST).
- In n8n → Credentials → WordPress, configure URL + user + application password.
- Create a Sheet (e.g.,
n8n-wp-automations
) with columns
ID, Title, Date, Content, Link, Status
- Copy the document ID (the long string in the Sheet URL).
- In n8n → Credentials → Google, create a service account credential with Sheets access.
- Enable Sheets and Translate APIs if you use the corresponding nodes.
In n8n: Workflows → Import
- Import
/n8n-workflows/WordPress_Automations__Part1.json
- Import
/n8n-workflows/WordPress_Automations__Part2.json
Open the nodes and replace every INSERT_YOUR_ID_HERE
with your real values:
- Credentials internal IDs (if required by your n8n instance; keep the credential
name
unless you rename it). - Google Sheets:
documentId.value
andsheetName.value
. - WordPress:
pageId
for EN and IT VoiceOver pages.
Do not delete fields—only replace the placeholder with your ID/string.
In the HTTP Request nodes for TTS (IT/EN), set the Cloud Run URL:
https://<long-tts-xxxx>.run.app/long-tts
Ensure the audio files are reachable from your site:
- Either set objects (or the bucket) to public read,
- Or adapt the HTML in the workflow to use Signed URLs.
- WordPress credentials → WordPress nodes.
- Google Service Account → Google Sheets/Translate nodes.
- OpenAI → “OpenAI | Clean” nodes (if you keep the LLM cleaning steps).
- Scheduled trigger → fetch posts via WordPress API.
- HTML → plain text cleaning.
- Append/Update into Google Sheets:
ID, Title, Date, Content, Link
(emptyStatus
).
- Select next record with empty
Status
(sorted by date). - Aggressive text cleaning (OpenAI “Clean” nodes).
- EN translation (Google Translate) + final cleanup.
- HTTP calls to /long-tts to generate
.wav
for IT/EN. - Fetch the two WordPress pages (IT/EN) and inject an
<audio>
player block containing:- title, date, link to the original article,
- audio source pointing to your GCS bucket (e.g.,
https://storage.googleapis.com/<bucket>/<ID>.wav
and<ID>EN.wav
).
- Update
Status=done
in Google Sheets.
- Run Part 1 (or wait for its schedule) to populate the Sheet.
- Run Part 2 to process the next pending row: generate audio, update WordPress, mark
done
. - Verify:
.wav
files in GCS,<audio>
blocks on your EN/IT pages,Status
updated in the Sheet.
<hr>
<h3>🎧 VoiceOver: {{Title}}</h3>
<h5>Date: {{Date}}</h5>
<h5>Article link: {{Link}}</h5>
<p>PostID: {{ID}}</p>
<audio controls>
<source src="https://storage.googleapis.com/<BUCKET>/<ID>.wav" type="audio/mpeg">
</audio>
In the EN workflow path an
EN.wav
suffix is typically used for the English version.
- 401/403 on Cloud Run → Is the service public? Otherwise configure IAM and authentication (ID token).
- WordPress update fails → Double‑check
pageId
, WP user permissions, and base URL in credentials. - Audio not reachable → Check GCS ACLs/policies or use Signed URLs.
- TTS artifacts/pronunciation → Ensure the “Clean” nodes strip quotes/escape sequences/HTML entities before TTS.
- Sheet not updating → Confirm column mapping and
matchingColumns: ["ID"]
on the Sheets node.
This repository’s original content (workflow JSON, deployment instructions, and example code) is released under the MIT License.
You are responsible for complying with licenses and terms of external services and SDKs (Google Cloud, OpenAI, etc.).
MIT License
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
If this saved you time, star this repo to help others find it!