Adding a Text-to-Speech Player to Your Website Using Elementor

Listen, Learn, and Engage

Note: This audio feature may not work correctly on certain browsers like Brave. Please switch to a different browser for the best experience.
0:00 / 0:00
We're on a mission to propel brands to new heights, constantly seeking the next frontier in forging meaningful brand connections.

I hate reading unless it interests me, even if it’s something I must read. If you can relate, we are one of a kind. I prefer listening to audiobooks or watching videos from TEDx over reading printed or online material to understand concepts or learn something new.

I thought I would write a quick article for people managing their platforms or with less coding knowledge to help them add an audio player that reads their content so people who prefer listening can do so.
Adding a text-to-speech (TTS) player to your website may sound complex, but it’s actually quite simple.

With Elementor, you can set up a custom TTS player with minimal coding.

This guide will walk you through each step, making the process easy and manageable, even without coding knowledge.

image
This is what you would get with the following code:

Step 1: Creating a Single Post Template in Elementor Pro

  1. Go to Templates > Theme Builder in your WordPress dashboard.
  2. Click on Add New and select Single Post from the dropdown.
  3. Give the template a name (e.g., “Post with TTS”) and click Create Template.
  4. Choose a layout or start with a blank page. This will serve as the base for your posts.

Step 2: Adding Your Post Content

  1. In the Elementor editor, drag the Post Content widget into your template. This widget will automatically display the content of each post.
  2. To ensure the text is accessible to the TTS player, add a CSS class to the Post Content widget.
    • Click on the Post Content widget, go to the Advanced tab, and add contentsNew to the CSS Classes field.
    This CSS class allows the TTS player script to locate and read the post content.

Step 3: Adding the contentsNew CSS Class to the Post Content

<!-- You should make the container of the blog article the contentsNew CSS Class -->
<div class="contentsNew">Remove this when you use this code</div>

To ensure the audio player can locate and read the text content of your post, the Post Content widget in your Elementor template needs a specific CSS class (contentsNew).

Here’s how to do it,

  1. Find the Post Content widget in your Elementor template.
  2. Go to the Advanced tab of the widget.
  3. In the CSS Classes field, type contentsNew.

This class allows the JavaScript function getArticleText() to find and retrieve the text within the Post Content widget. The getArticleText() function looks specifically for elements with the class contentsNew, gathers the text, and prepares it for the TTS player to read.

Example Layout After Setting Up in Elementor

After you’ve added the CSS class to the Post Content widget, your HTML structure will look like the following,

<div id="audio-player">
    <button id="playButton" class="control-button"><img src="http://hypesrilanka.com/wp-content/uploads/2023/09/Play-min.svg"></button>
    <button id="pauseButton" class="control-button" disabled><img src="http://hypesrilanka.com/wp-content/uploads/2023/09/Pause-min.svg"></button>
    <span id="currentTime">0:00</span> / <span id="totalTime">0:00</span>
</div>

<div class="contentsNew">
    <!-- This will be automatically filled with post content by Elementor, 
    so no need to add any text manually here once the template is applied to your posts. -->
</div>

Step 4: Adding the Text-to-Speech Player HTML and CSS

Now, let’s add the audio player itself. You’ll use an HTML widget for this.

  1. In the same Elementor template, drag the HTML widget below the Post Content widget.
  2. Copy the code below and paste it into the HTML widget.
<style>
    /* Small and sleek audio player container */
    #audio-player {
        display: flex;
        align-items: center;
        gap: 10px;
        width: fit-content;
        padding: 8px;
        background-color: #222;
        border-radius: 25px;
        box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2);
        color: #fff;
        font-family: Arial, sans-serif;
        font-size: 14px;
    }

    /* Play and pause buttons */
    .control-button {
        background-color: #ff4747;
        border: none;
        border-radius: 50%;
        width: 30px;
        height: 30px;
        color: white;
        font-size: 16px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: background-color 0.2s ease;
    }

    .control-button:hover {
        background-color: #ff7979;
    }

    /* Timer styling */
    #currentTime, #totalTime {
        font-size: 12px;
    }
</style>

<!-- Audio Player HTML -->
<div id="audio-player">
    <button id="playButton" class="control-button"><img src="http://hypesrilanka.com/wp-content/uploads/2023/09/Play-min.svg"></button>
    <button id="pauseButton" class="control-button" disabled><img src="http://hypesrilanka.com/wp-content/uploads/2023/09/Pause-min.svg"></button>
    <span id="currentTime">0:00</span> / <span id="totalTime">0:00</span>
</div>

This code will style your player and create Play and Pause buttons, with a simple display for current and total time.

Step 5: Adding JavaScript for Text-to-Speech Functionality

The JavaScript code will handle the TTS functionality, including loading voices, converting text to speech, and updating the audio player.

  1. In the same HTML widget (below the previous code), paste the JavaScript below
<script>
    document.addEventListener("DOMContentLoaded", () => {
    function getArticleText() {
        const contentElement = document.querySelector('.contentsNew');
        if (!contentElement) {
            alert("Error: No content found on the page.");
            return null;
        }
        return contentElement.textContent.trim();
    }

    function initializeVoices(callback) {
        const synth = window.speechSynthesis;
        if (!synth) {
            alert("Error: speechSynthesis not supported in this browser.");
            return;
        }
        
        console.log("Checking for voices...");
        if (synth.getVoices().length) {
            console.log("Voices are available immediately.");
            callback();
        } else {
            console.log("Waiting for voices to load...");
            synth.addEventListener('voiceschanged', callback, { once: true });
        }
    }

    const blogText = getArticleText();
    if (!blogText) return;

    initializeVoices(() => initializePlayer(blogText));

    function initializePlayer(blogText) {
        console.log("Initializing audio player...");

        const playButton = document.getElementById('playButton');
        const pauseButton = document.getElementById('pauseButton');
        const currentTimeDisplay = document.getElementById('currentTime');
        const totalTimeDisplay = document.getElementById('totalTime');
        let utterance;
        let isPlaying = false;
        let elapsedSeconds = 0;
        let timerInterval;

        if (!('speechSynthesis' in window)) {
            alert("Error: Your browser does not support the Web Speech API.");
            return;
        }

        function readArticle(text) {
            const synth = window.speechSynthesis;
            if (synth.speaking) synth.cancel();

            console.log("Creating utterance...");
            utterance = new SpeechSynthesisUtterance(text);
            utterance.voice = synth.getVoices().find(voice => voice.lang === 'en-US') || synth.getVoices()[0];

            if (!utterance.voice) {
                alert("Error: No suitable voice found for text-to-speech.");
                return;
            }

            const wordCount = text.split(" ").length;
            const totalDuration = Math.floor(wordCount / 3);
            totalTimeDisplay.textContent = formatTime(totalDuration);

            utterance.onstart = startTimer;
            utterance.onend = resetPlayback;

            console.log("Starting speech synthesis...");
            synth.speak(utterance);
            isPlaying = true;
            playButton.disabled = true;
            pauseButton.disabled = false;
        }

        function formatTime(seconds) {
            const minutes = Math.floor(seconds / 60);
            seconds = Math.floor(seconds % 60);
            return `${minutes}:${seconds < 10 ? '0' + seconds : seconds}`;
        }

        function startTimer() {
            elapsedSeconds = 0;
            currentTimeDisplay.textContent = '0:00';
            timerInterval = setInterval(() => {
                elapsedSeconds++;
                currentTimeDisplay.textContent = formatTime(elapsedSeconds);
            }, 1000);
        }

        function resetPlayback() {
            clearInterval(timerInterval);
            currentTimeDisplay.textContent = '0:00';
            isPlaying = false;
            playButton.disabled = false;
            pauseButton.disabled = true;
        }

        playButton.addEventListener('click', () => {
            console.log("Play button clicked");
            if (!isPlaying) {
                try {
                    // Initial test with a simple phrase to check synthesis
                    const testUtterance = new SpeechSynthesisUtterance("Hello, this is a test.");
                    window.speechSynthesis.speak(testUtterance);
                    // Then proceed to read the article
                    readArticle(blogText);
                } catch (error) {
                    alert("Error during playback: " + error.message);
                }
            }
        });

        pauseButton.addEventListener('click', () => {
            console.log("Pause button clicked");
            const synth = window.speechSynthesis;
            if (synth.speaking && !synth.paused) {
                synth.pause();
                clearInterval(timerInterval);
                playButton.disabled = false;
                pauseButton.disabled = true;
            } else if (!synth.speaking) {
                alert("Error: Speech synthesis is not currently playing.");
            }
        });
    }
});
</script>

Step 5: Save and Publish the Template

  1. Once you’ve added the HTML widget to the code, click Publish.
  2. Set the display conditions (e.g., All Posts) so this template applies to all blog posts on your site.
  3. Click Save & Close.

You can get the working complete code here: Get the Code

I hope this blog post helps you to add this to your website. All you need to do is add this to an HTML widget or directly add the CSS code within the Header and the Script at the end of the Body tag.

More From HypeX