Text-to-Voice Tutorial Part 2: Getting Notified When Your Voice File is Ready
This guide covers Part 2 of the text-to-voice workflow: setting up email notifications when your voice file has finished processing and is ready to download.
What you'll build:
- A Google Cloud Function that monitors your output bucket
- A webhook integration with Make.com (or your preferred automation platform)
- An automated email notification with a download link
You will need to have completed:
- Part 1 of the text-to-voice tutorial
- Google Cloud project with the first function already deployed
- Make.com account (free tier works fine)
- Input and output Cloud Storage buckets configured
Why This Setup is Necessary
You might wonder why we need this extra complexity—why not just trigger an email when a file lands in the bucket?
The Google Cloud Text-to-Speech API processes long audio files by:
- Sending audio in small chunks to your bucket
- Creating multiple temporary files
- Assembling everything into one complete file at the end
Without the code below, you'd receive an email notification for every temporary file chunk—potentially dozens of spam emails for a single audio file.
The function we're building filters out temporary files and only notifies you when the complete, assembled audio file is ready.
Step 1: Create the Webhook in Make.com
1.1 Set Up the Scenario
- Log in to Make.com and create a new scenario
- Search for and add a Webhook module
- Click Add to create a new webhook
- Name it something memorable: Voice File Ready
- Copy the webhook URL—you'll need this in Step 2
Leave this browser tab open; we'll come back to complete the email setup later.
Step 2: Create the Google Cloud Function
2.1 Navigate to Cloud Functions
- Go back to your Google Cloud Console
- Navigate to Cloud Functions (where you created the first function)
- Click Create Function
2.2 Configure the Function
Basic Settings:
- Function name: voice-file-ready (or your preferred name)
- Region: Choose the same region as your storage buckets (critical!)
- Runtime: Python 3.x
Trigger Configuration:
- Click Add Trigger
- Select Cloud Storage
- Event type: Finalize/Create
- Bucket: Browse and select your OUTPUT bucket (where voice files land)
- Click Save
Click Create to proceed to the code editor.
Step 3: Add the Function Code
3.1 Update Entry Point
In the function editor, change the Entry point field to:
notify_audio_ready
3.2 Main Function Code
Replace the contents of main.py with:
import functions_framework
import requests
import json
from datetime import datetime
# --- Configuration ---
# Replace with your own bucket name and webhook URL from Make (or any other automation tool)
OUTPUT_BUCKET = "<your-output-bucket>" # e.g. "my-voice-files-2"
MAKE_WEBHOOK_URL = "<your-make-webhook>" # e.g. "https://hook.eu1.make.com/bvp1z6pio1..."
@functions_framework.cloud_event
def notify_audio_ready(cloud_event):
"""Triggered when a file is uploaded to the 'voice-out' bucket."""
data = cloud_event.data
bucket_name = data.get("bucket")
object_name = data.get("name")
print(f"Event: gs://{bucket_name}/{object_name}")
# Only handle final .wav/.mp3 files in correct bucket
if bucket_name != OUTPUT_BUCKET:
print(f"Skipping — wrong bucket: {bucket_name}")
return
if not object_name.endswith((".wav", ".mp3")):
print(f"Skipping — not an audio file: {object_name}")
return
# IMPORTANT: Filter out temporary chunk files from Long Audio API
# These have pattern: filename_{job_id}_{chunk_number}.wav
# We only want the final assembled file
parts = object_name.rsplit(".", 1)[0].split("_")
if len(parts) >= 3 and parts[-1].isdigit() and parts[-2].isdigit():
print(f"Skipping temporary chunk: {object_name}")
return
# Build metadata for Make webhook
filename = object_name.split("/")[-1]
gs_uri = f"gs://{bucket_name}/{object_name}"
public_url = f"https://storage.googleapis.com/{bucket_name}/{object_name}"
timestamp = datetime.now().isoformat()
# This next part Builds te metadata for the webhook
#
# You can safely remove any fields you don’t need for your workflow.
# For most automations, just keeping "public_url" and "message" is enough.
# Example minimal version:
# payload = {
# "public_url": public_url,
# "message": f"🎧 Your audio file '{filename}' is ready!"
# }
#
payload = {
"event": "audio_file_ready",
"filename": filename,
"gs_uri": gs_uri,
"public_url": public_url,
"bucket": bucket_name,
"object_name": object_name,
"timestamp": timestamp,
"message": f"🎧 Your audio file '{filename}' is ready for download!"
}
try:
print(f" Sending webhook...")
response = requests.post(MAKE_WEBHOOK_URL, json=payload, timeout=10)
response.raise_for_status()
print(f" Webhook sent! Status: {response.status_code}")
except requests.RequestException as e:
print(f" Webhook error: {e}")
if getattr(e, "response", None):
print(f"Response text: {e.response.text}")
raise
3.3 Requirements File
Replace the contents of requirements.txt with:
functions-framework==3.*
requests==2.*
3.4 Make Sure You Configure Your Variables
Before deploying, update these values in the code:
Output Bucket:
OUTPUT_BUCKET = "your-output-bucket-name"
Webhook URL:
MAKE_WEBHOOK_URL = "your-make-webhook-url"
Replace these with:
- Your actual output bucket name
- The webhook URL you copied from Make.com in Step 1
3.5 Deploy the Function
Click Deploy and wait for the function to build (usually 1-2 minutes).
Step 4: Complete the Email Setup in Make.com
4.1 Set Up Data Structure
- Go back to your Make.com scenario
- Click on the webhook module
- Click Redetermine data structure
- The webhook is now listening...
4.2 Trigger a Test
To populate the data structure:
- Go to your Google Cloud Storage input bucket
- Upload a test text file (any small .txt or .md file)
- This triggers the full workflow
Within a few seconds, Make.com should receive the webhook data and you'll see "Successfully determined" in the webhook module.
4.3 Add Gmail Module
- Click the + button after the webhook
- Search for and add Gmail > Send an Email
- Create a connection to your Gmail account (follow the authentication prompts)
- Configure the email:
To: Your email address
Subject: Voice File Ready (or your preferred subject)
Message example:
Your voice file is ready!<br/><br/>
Download here: [map: public_url from webhook]
To add the download link:
- Click in the Message field
- Find
public_url
in the webhook data - Click to insert it
You can use any of these fields in your automation. The example above uses public_url to provide a direct download link, but you could also:
- Use file_name in the email subject
- Store bucket_name for record keeping
- Trigger different actions based on event_type
4.4 Test the Complete Workflow
- Save the scenario in Make.com
- Turn on the scenario (toggle in the bottom left)
- Upload another test file to your input bucket
- Wait 30-60 seconds
- Check your email—you should receive the notification with a clickable download link
Understanding What Gets Sent to the Webhook
The Cloud Function sends structured data to your webhook that you can use in your automations. Here's what a real webhook payload looks like:
event: audio_file_ready
filename: simple-test_14-10-2025.wav
gs_uri: gs://my-voice-2/simple-test_14-10-2025.wav
public_url: https://storage.googleapis.com/my-voi-iles-2/simple_14-10-2025.wav
bucket: my-voice-files-2
object_name: simple-test_14-10-2025.wav
timestamp: 2025-10-14T15:54:09.108763
message: 🎧 Your audio file 'simple-test_14-10-2025.wav' is ready for download!
Field Descriptions
- event - Event type identifier (useful if you're handling multiple event types)
- filename - Just the filename without path
- gs_uri - Google Storage URI (for programmatic access)
- public_url - Direct download link (this is what you want for emails!)
- bucket - Name of the output bucket
- object_name - Full object name/path in bucket
- timestamp - When the file was created
- message - Ready-to-use notification message with emoji
Customising the Webhook Payload
You can customise what data gets sent by modifying the function code. The payload is built in the main.py section shown below:
python
# This next part builds the metadata for the webhook
# ------------------------------------------------------------
# You can safely remove any fields you don't need for your workflow.
# For most automations, just keeping "public_url" and "message" is enough.
# Example minimal version:
# payload = {
# "public_url": public_url,
# "message": f"🎧 Your audio file '{filename}' is ready!"
# }
# ------------------------------------------------------------
payload = {
"event": "audio_file_ready",
"filename": filename,
"gs_uri": gs_uri,
"public_url": public_url,
"bucket": bucket_name,
"object_name": object_name,
"timestamp": timestamp,
"message": f"🎧 Your audio file '{filename}' is ready for download!"
}
Common Use Cases
Simple email notification: Just use public_url and message
Advanced workflows: Use all fields to:
- Store
gs_uri
in a database for record keeping - Use
timestamp
to track processing times - Filter by
event
type if handling multiple notification types - Use
bucket
andobject_name
for additional file operations - Include
filename
in email subjects or logging
Troubleshooting
Not Receiving Emails?
- Check Make.com scenario is running (toggle should be blue/on)
- Verify webhook received data (click on webhook module to see execution history)
- Check spam folder for the email
- Verify Gmail connection is still authenticated in Make.com
Remember: The most common issues are mismatched bucket names or regions, and authentication problems with Make.com or Gmail.
Alternative Automation Platforms
Whilst this guide uses Make.com, the same approach works with:
- Zapier - Use "Webhooks by Zapier" with "Catch Hook"
- n8n - Use the Webhook node
- Any platform with webhook support
Simply replace the Make.com webhook URL with your platform's webhook URL in the function code.