AI Text-to-Speech using AWS Polly

AI Text-to-Speech using AWS Polly

Details
View on WordPress

AI Text-to-Speech using AWS Polly creates audio versions of WordPress posts with AWS Polly voices.

This is an independent plugin by iTRON. It is not affiliated with or endorsed by Amazon, AWS, or Amazon Polly.

Development and source code: https://github.com/hokoo/aws-polly

Key features:

  • Generate audio for supported post types.
  • Queue audio generation in the background with WP-Cron.
  • Store audio locally or in Amazon S3.
  • Optionally use Amazon CloudFront for delivery.
  • Control voice, sample rate, autoplay, player label, and download availability.

Configuration

Follow the steps below in order. They use the English names shown in the AWS and WordPress interfaces; translated interfaces place the same controls in the same sections.

You must sign in to AWS with an account that is allowed to create IAM policies, IAM users, access keys, and, when S3 storage is used, S3 buckets. In a company AWS account, these operations may be restricted; if AWS shows an authorization error, ask the AWS account administrator to complete the corresponding step.

The AWS terms used in this guide mean:

  • S3 bucket: the container that holds generated MP3 files when S3 storage is enabled.
  • IAM policy: the list of AWS operations the plugin is allowed to perform.
  • IAM user: the dedicated technical identity to which that policy is attached.
  • Access key: the Access key ID and Secret access key that let WordPress use the IAM user’s permissions.

The plugin needs two credentials from AWS:

  • Access key ID: usually starts with AKIA.
  • Secret access key: a longer private value that AWS shows only when the key is created.

These values are not the email address and password used to sign in to AWS. Never use an access key belonging to the AWS account root user. The instructions below create a separate user that can only call the AWS operations required by this plugin.

1. Choose where the MP3 files will be stored

Choose one option before creating the AWS policy:

  • Local WordPress storage is the simplest first-time setup. The generated MP3 files are stored in the WordPress uploads directory. You do not need an S3 bucket or any S3 permissions.
  • Amazon S3 storage keeps the generated MP3 files in an AWS bucket. Complete the bucket steps below and use the policy marked Amazon S3 storage.

Amazon Polly is required in both cases and AWS usage may incur charges.

2. Sign in to AWS and choose a Region

  1. If you do not have an AWS account, create one at https://aws.amazon.com/. AWS may ask for billing and identity information during registration.
  2. Sign in to the AWS Management Console at https://console.aws.amazon.com/.
  3. In the search box at the top, enter Polly and open Amazon Polly.
  4. Use the Region selector in the upper-right corner of the console to select the Region where Polly will run. Remember both its name and code. For example, US East (N. Virginia) has the code us-east-1.
  5. Confirm that the Polly page opens in this Region. The available voices and engines vary by Region, so choose a Region that provides the voice you intend to use.

Use this same Region for Polly, the optional S3 bucket, and the AWS Region setting in WordPress. A bucket’s Region cannot be changed after the bucket is created.

3. Create an S3 bucket (skip for local storage)

If you selected local WordPress storage in step 1, skip directly to step 4.

  1. Open the S3 console at https://console.aws.amazon.com/s3/ or search for S3 at the top of the AWS Console.
  2. In the Region selector, select the same Region chosen for Amazon Polly.
  3. In the left menu, choose General purpose buckets, then choose Create bucket.
  4. If AWS asks for a bucket type or namespace, select a General purpose bucket in the standard shared global namespace.
  5. In Bucket name, enter a unique name such as example-com-polly-audio-1234. Use only lowercase letters, numbers, and hyphens. The name must be unique across AWS, must not contain private information, and cannot be changed later. If AWS reports that the name already exists, add another random number and try again.
  6. Check AWS Region and make sure it is the Region selected for Polly.
  7. Keep Object Ownership set to Bucket owner enforced and keep ACLs disabled.
  8. Leave Block all public access enabled for now. Step 8 explains how to make the audio playable with direct S3 delivery. Keeping this option enabled while creating the bucket avoids exposing an unfinished bucket.
  9. Leave Bucket Versioning disabled and Object Lock disabled unless your organization has a specific retention requirement. Object Lock can prevent the plugin from replacing or deleting old audio.
  10. Under Default encryption, keep the default Server-side encryption with Amazon S3 managed keys (SSE-S3). This option works without additional KMS permissions.
  11. Choose Create bucket.
  12. When the bucket appears in the bucket list, copy its exact name. WordPress needs the name only, such as example-com-polly-audio-1234; do not enter s3://, an ARN, or a web address in the bucket-name field.

Official S3 bucket instructions: https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html

4. Create the plugin permissions policy

An IAM policy is a document that tells AWS exactly what the plugin is allowed to do. Create one as follows:

  1. Open the IAM console at https://console.aws.amazon.com/iam/ or search for IAM at the top of the AWS Console.
  2. In the left menu, choose Policies.
  3. Choose Create policy.
  4. In Policy editor, choose JSON.
  5. Delete the sample JSON already in the editor.
  6. Copy and paste one of the complete policies below. Use the local policy if WordPress will store the MP3 files, or the S3 policy if the bucket will store them. Do not combine the two examples.

For local WordPress storage, paste this policy exactly as shown:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "UseAmazonPolly",
      "Effect": "Allow",
      "Action": [
        "polly:DescribeVoices",
        "polly:SynthesizeSpeech"
      ],
      "Resource": "*"
    }
  ]
}

For Amazon S3 storage, first replace both occurrences of YOUR-BUCKET-NAME with the exact bucket name copied in step 3, then paste the complete policy. For example, arn:aws:s3:::YOUR-BUCKET-NAME becomes arn:aws:s3:::example-com-polly-audio-1234. Keep the arn:aws:s3::: prefix and keep the /* at the end of the second bucket resource.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "UseAmazonPolly",
      "Effect": "Allow",
      "Action": [
        "polly:DescribeVoices",
        "polly:SynthesizeSpeech"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CheckAudioBucket",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
    },
    {
      "Sid": "ManageGeneratedAudio",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
    }
  ]
}
  1. Choose Next. AWS checks the JSON and shows the permissions that will be granted. The Resource: "*" value for the two Polly operations is expected; those operations require it and it does not grant access to other AWS services.
  2. On Review and create, enter WordPressPollyPlugin in Policy name. You can enter Permissions required by the AI Text-to-Speech WordPress plugin in Description.
  3. Choose Create policy. A green success message should appear.

The S3 policy has three separate jobs: s3:ListBucket lets the plugin verify the bucket, s3:PutObject lets it upload MP3 files, and s3:DeleteObject lets it remove obsolete MP3 files. Do not use broad policies such as AdministratorAccess, AmazonPollyFullAccess, or AmazonS3FullAccess in place of the policy above.

Official policy instructions and permission references: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html, https://docs.aws.amazon.com/polly/latest/dg/api-permissions-reference.html, and https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-policy-actions.html

5. Create a dedicated IAM user

This is a technical user for the plugin. It does not need a password and nobody should use it to sign in to the AWS Console.

  1. Stay in the IAM console and choose Users in the left menu.
  2. Choose Create user.
  3. In User name, enter a recognizable name such as wordpress-polly-plugin or wordpress-polly-example-com.
  4. Leave Provide user access to the AWS Management Console unchecked. The plugin needs an access key, not console access.
  5. Choose Next.
  6. On Set permissions, select Attach policies directly.
  7. In the permissions-policy search box, enter WordPressPollyPlugin.
  8. Select the checkbox next to the policy created in step 4. Make sure the policy name appears in the permissions summary.
  9. Choose Next, review the user, then choose Create user.
  10. Open the new user from the user list and check the Permissions tab. WordPressPollyPlugin must be listed under Permissions policies. If it is not listed, choose Add permissions, choose Attach policies directly, select it, and save.

Official IAM user instructions: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html

6. Create the access key

  1. On the page for the wordpress-polly-plugin user, open the Security credentials tab.
  2. Scroll to Access keys and choose Create access key.
  3. On Access key best practices & alternatives, select Other, confirm that you understand the recommendation if AWS asks, and choose Next.
  4. In Description tag value, enter the WordPress site hostname, for example www.example.com, so the key can be identified later.
  5. Choose Create access key.
  6. Keep this page open. It shows two different values: Access key ID and Secret access key. Choose Show if the secret is hidden.
  7. Copy both values to the WordPress settings in step 7, or choose Download .csv file and temporarily save the file in a secure location. AWS will not show this secret access key again after you leave the page.

If the secret is lost, do not try to recover it. Create a new access key, update WordPress, verify that it works, and then deactivate and delete the old key. An IAM user can have at most two access keys at the same time.

Official access-key instructions: https://docs.aws.amazon.com/IAM/latest/UserGuide/access-key-self-managed.html

7. Enter the AWS settings in WordPress

  1. Sign in to WordPress as an administrator.
  2. In the left WordPress menu, choose AI TTS -> General.
  3. Paste the AWS Access key ID into AWS access key. Do not paste the IAM user name here.
  4. Paste the AWS Secret access key into AWS secret key. Take care not to add a space before or after the value.
  5. In AWS Region, select the same Region used in steps 2 and 3.
  6. For local storage, leave Amazon S3 bucket name empty. For S3 storage, enter only the exact bucket name copied in step 3.
  7. Choose Save Changes.
  8. Open AI TTS -> Text-To-Speech.
  9. Enable Enable text-to-speech support. If you created an S3 bucket, also enable Store audio in Amazon S3; leave it disabled for local WordPress storage.
  10. Choose Save Changes again. The Voice name list should load voices available in the selected Region.

The Access key ID and Secret access key must come from the same access key. Mixing an ID from one key with a secret from another key will always fail.

8. Allow visitors to play files stored in S3 (skip for local storage)

Complete this step only when Store audio in Amazon S3 is enabled. The plugin uploads MP3 files but does not change the bucket’s public-access settings.

The easiest direct-delivery setup uses a dedicated public bucket:

  1. Open S3 -> General purpose buckets and choose the bucket created in step 3.
  2. Open the Permissions tab.
  3. Find Block public access (bucket settings) and choose Edit.
  4. Clear Block all public access, acknowledge the warning, and choose Save changes. AWS may ask you to type confirm.
  5. On the same Permissions tab, find Bucket policy and choose Edit.
  6. Replace YOUR-BUCKET-NAME in the policy below with the exact bucket name. Do not remove the /* from the end of the resource.
  7. Paste the complete policy into the editor and choose Save changes.

    {
    “Version”: “2012-10-17”,
    “Statement”: [
    {
    “Sid”: “PublicReadGeneratedAudio”,
    “Effect”: “Allow”,
    “Principal”: ““,
    “Action”: “s3:GetObject”,
    “Resource”: “arn:aws:s3:::YOUR-BUCKET-NAME/
    ”
    }
    ]
    }

Use a bucket dedicated to plugin audio because this policy makes every object in that bucket downloadable by anyone who knows its URL. If AWS refuses to save the policy, the account-level Block Public Access setting may still prohibit public buckets. Do not change an account-wide security setting unless you understand how it affects the account’s other buckets. In that situation, ask the AWS account administrator for help or use Amazon CloudFront with a private S3 origin and Origin Access Control, then enter the CloudFront distribution domain in the plugin settings.

Official public-read instructions: https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html

9. Verify the setup

  1. In WordPress, open AI TTS -> Text-To-Speech. If the voice list loads, the access key, Region, IAM user, and Polly permissions are working.
  2. Select a language and voice, keep text-to-speech enabled, and save the settings.
  3. Create or edit a test post, enable text-to-speech for that post, and update or publish it.
  4. Audio generation runs in the background through WP-Cron, so it may not appear immediately. Wait for the job to finish, then open the post and play the audio.
  5. With S3 storage, open the bucket’s Objects tab. A generated file has a name such as itron_polly_tts_123.mp3, optionally inside year/month folders.

Common problems:

  • The voice list does not load: verify that both credential fields are filled, the access key is Active, WordPressPollyPlugin is attached to the IAM user, and the selected Region supports Amazon Polly.
  • AWS reports an invalid access key or signature: copy the Access key ID and Secret access key again from the same downloaded CSV. Remove accidental spaces. Create a new key if the secret is no longer available.
  • The S3 bucket is not accessible: verify the exact bucket name and Region. Check that both S3 ARNs in WordPressPollyPlugin contain that exact name and that Store audio in Amazon S3 is enabled only when a bucket is configured.
  • Audio is generated but the browser returns 403 Access Denied: direct S3 delivery is still blocked, the public bucket policy has the wrong bucket name, or CloudFront cannot access the private bucket.
  • The policy editor reports an invalid resource: a bucket ARN must look like arn:aws:s3:::example-com-polly-audio-1234; an object ARN must have /* at the end.
  • Nothing is generated after saving a post: confirm that WordPress WP-Cron works, text-to-speech is enabled globally and on the post, and the post type is enabled in the plugin settings.

Optional: store credentials outside the WordPress database

The steps above save the credentials in WordPress so that the setup is straightforward. For a production site, an administrator can instead define them in wp-config.php or another PHP config file loaded before WordPress finishes bootstrapping. This keeps them out of the WordPress options table. The configuration file must be outside version control and readable only by the server account that needs it:

define( 'ITRON_POLLY_TTS_S3_ACCESS_KEY', 'your-access-key' );
define( 'ITRON_POLLY_TTS_S3_SECRET_KEY', 'your-secret-key' );

You can also lock the bucket and region in PHP the same way:

define( 'ITRON_POLLY_TTS_S3_BUCKET_NAME', 'your-s3-bucket' );
define( 'ITRON_POLLY_TTS_S3_REGION', 'us-east-1' );

When these constants are present, the plugin uses them instead of saved options and shows the related admin fields as defined by PHP constant. Do not commit real secrets into version control.

Use the IAM user and access key only for this plugin. Review the key’s last-used date, rotate it periodically, and deactivate or delete it immediately if it is exposed or no longer needed. Do …

Details

Plugin code:
ai-text-to-speech-using-aws-polly
Plugin version:
1.0.8
Author:
Outdated:
No
WP version:
6.5 or higher
PHP version:
8.1 or higher
Test up to WP version:
7.1
Total installations:
0
Last updated:
2026-09-07
Rating:
Times rated:
0
audio
aws-polly
podcast
speech-synthesis
text-to-speech