Showing posts with label IOT. Show all posts
Showing posts with label IOT. Show all posts

Friday, August 14, 2026

Javascript Speech Recognition

For an index to all my stories click this text

Speech synthesises is having your computer speak out words and sentences to you. You can do that with Javascript like I wrote in this story: 
https://lucstechblog.blogspot.com/2025/09/javascript-speech-synthesises.html
But even microcontrollers like the ESP32 can (although in a very low quality) speak out words and sentences like you can read in these stories:
- talkie 1
https://lucstechblog.blogspot.com/2022/11/talkie-part-1-esp32-speech-synthesiser.html 

- Audio on the Raspberry Pi Pico part 4
http://lucstechblog.blogspot.com/2024/11/pico-audio-part-4-talking-thermometer.html

But next to that there is speech recognition. That's the other way round. You speak into a microphone and your computer recognizes the words and acts on them. The most famous examples are of course Google Home and Alexa.

A few years ago I wrote a story on how to build a speech recognition App for Android:
https://lucstechblog.blogspot.com/2016/01/voice-command.html

This time I am going to show you how it is done in Javascript.
There is a limitation and that is that this is Windows only and it does not work in Firefox. Firefox does not support speech recognition. So you will have to use Google Chrome or Microsoft Edge.

Javascript.

Javascript runs in a browser. So to use it you need to build a minimal web-page.

On this web-page we put a text that tells what this page is about and an empty paragraph into which the spoken and recognized words and sentences are put.

<!DOCTYPE html>
<html>
<body>
<h1 style="color:red;">Luc's speech recognition</h1>
<h2>Below comes the text that you speak.</h2>
<br>
<p id="texthere"></p>

</html>

This is the complete web-page. However it does nothing exept setting some text on your screen. To have speech recognition to work we need a Javascript program. and here is that program line by line.

window.SpeechRecognition = window.webkitSpeechRecognition || window.SpeechRecognition;

This line selects the speech recognition that is needed for your browser.

const recognition = new window.SpeechRecognition();

We make an instance of the Speech.Recognition and call it recognition

    recognition.continuous = true;


This line is important as it sets the speech recognition to continuous.
Continuous means that you do not need a button to click on each time you want a new sentence to get analysed.

    recognition.lang = "en-US"

And with this line you can change the language you want to get recognised.

    recognition.onresult = (event) =>
    {
      var textheard = (event.results[event.results.length -1][0].transcript);
      document.getElementById("texthere").innerHTML = textheard;
    }


If the speech recognition has heard a sentence an event is raised.
The variable textheard gets the interpreted text from the speech recognition and that variable is put into the paragraph on the screen with the ID texthere.

recognition.start();


And this is the actual command that starts the speech recognition.

And that is all that is to it.

So here is the complete page with the Javascript code.

<!DOCTYPE html>
<html>
<body>
<h1 style="color:red;">Luc's speech recognition</h1>
<h2>Below comes the text that you speak.</h2>
<br>
<p id="texthere"></p>

<script>

window.SpeechRecognition = window.webkitSpeechRecognition || window.SpeechRecognition;

    const recognition = new window.SpeechRecognition();

    recognition.continuous = true;
    recognition.lang = "en-US"

    recognition.onresult = (event) =>
    {
      var textheard = (event.results[event.results.length -1][0].transcript);
      document.getElementById("texthere").innerHTML = textheard;
    }
    
    recognition.start();

</script>
</html>


Play with it.

To play with this, copy the above code and paste it into your favorite texteditor. I mostly use notepad for these small programs.
Save the file as recognition.html or any name you like in any folder of your choice. Just make sure it is plain ASCII and the file has the extension HTML.
Open the folder and you will see an HTML file. Left click on that and open it with Google Chrome or microsofts Edge.



The webpage asks now whether it is ok to use your computers microphone.
Then just speak any text to your liking.



And this is how the webpage looks after I said "put lamp number one on"
You can see where this is going.

Language selection.

The above program uses recognition.lang = "en-US" yo set the speech.recognition to recognise the English language. So here is a list of the other languages that are available.

Javascript uses the BCP 47 Language Codes and here is the complete list of languages that are available:

ar-SA Arabic Saudi Arabia
cs-CZ Czech Czech Republic
da-DK Danish Denmark
de-DE German Germany
el-GR Modern Greek Greece
en-AU English Australia
en-GB English United Kingdom
en-IE English Ireland
en-US English United States
en-ZA English South Africa
es-ES Spanish Spain
es-MX Spanish Mexico
fi-FI Finnish Finland
fr-CA French Canada
fr-FR French France
he-IL Hebrew Israel
hi-IN Hindi India
hu-HU Hungarian Hungary
id-ID Indonesian Indonesia
it-IT Italian Italy
ja-JP Japanese Japan
ko-KR Korean Republic of Korea
nl-BE Dutch Belgium
nl-NL Dutch Netherlands
no-NO Norwegian Norway
pl-PL Polish Poland
pt-BR Portuguese Brazil
pt-PT Portuguese Portugal
ro-RO Romanian Romania
ru-RU Russian Russian Federation
sk-SK Slovak Slovakia
sv-SE Swedish Sweden
th-TH Thai Thailand
tr-TR Turkish Turkey
zh-CN Chinese China
zh-HK Chinese Hong Kong
zh-TW Chinese Taiwan


So just change recognition.lang = "en-US" into recognition.lang = "nl-NL" to change from English to Dutch for example.

Some considerations.

First:
The speech recognition is continuous. However when there is a silence for more then 10 seconds the speech recognition is turned off and you will have to restart it manually.

Second:
Do not use this if you hate Google. Actually every sentence you speak is send over the internet to Google's speech recognition server in the cloud. So if you thought you could use this to get rid of your Google Home or Nest you are wrong. This is still using Google's services.

What's next

The next step is to combine the speech synthezises and the ESP webserver with the speech recognition. Then we will be able to have the ESP8266 react on commands like "put the lamp on" and "tell me the room temperature" !!!

Till then.
Have fun

Luc Volders



Friday, May 15, 2026

NTFY part 2: Send notifications with ESP32 and Pico

For an index to all my stories click this text.

This is the second story about NTFY. The first story showed what NTFY is and how it can send notifications and messages to your Android smartphone from a PC dashboard.

This story shows how you can send notifications from your EP8266 or ESP32 in Arduino language (C++) to your phone, and how you can do that with a Raspberry Pi Pico in MicroPython.

So before you go on I recommend reading the previous story which you can find here: https://lucstechblog.blogspot.com/2026/05/notifications-with-ntfy.html

I'll start with sending a message from the Raspberry Pi Pico as a notification to a smartphone.

For your convenience I hereby give you the link to the NTFY website: https://ntfy.sh/

Limits and solution

First I hope you remember that with the free service NTFY there is a limit of 250 messages per day.
 
The messages remain for 12 hour on the server.
This means that if your phone is off, or has no internet connection, for 13 hours you will miss messages.

There are two solutions for this.
First you can get a paid subscription and then you get a lot more messages each day.
The second solution is to install your own NTFY server. You can do that on a Raspberry Pi (even the humble Zero) and then you can decide how many messages you can send per day  and how long they stay on the server.

Mind you: 250 messages per day is about 10 messages per hour which would be more than sufficient for most projects.

Nevertheless I chose the second solution and installed my own server. Maybe something for another story ........................

Sending a message from MicroPython with a Pico 

(Scroll down for the ESP32 arduino version)

We are going to do this the easy way. We are going to attach a button to the Pico and simulate that it is a door contact. Everytime the button is pressed the Pico will send a notification to the phone.

We are going to send an alarm with the text:

The door opened X times

The X will alter each time we press the button.

Let's start with the breadboard setup which is really easy.



It is just the Raspberry pi pico with a button attached to GP14. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).

Here is the complete program.

import machine
import network
import urequests as requests
import time

button1 = machine.Pin(14, machine.Pin.IN)
dooropen = 0

# Router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "YOUR-PASSWORD"
print("Connecting to wifi...")

# wifi connection
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, pw)

# wait for connection
while not wifi.isconnected():
    pass

print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))

while True:
    if button1.value() == 0:
        dooropen = dooropen + 1
        sendstring ="The door opened " + str(dooropen) + " times"
        requests.post("http://ntfy.sh/lucstechblog",
        data= sendstring              
        )
        print("Data is send. dooropen = "+str(dooropen))
        time.sleep(3)

Let's have a look at the program in some detail.

import machine
import network
import urequests as requests
import time 

These are the libraries that are needed to get the program running. They are all included in the standard MicroPython distributions. So no need to download libraries.

button1 = machine.Pin(14, machine.Pin.IN)
dooropen = 0

The button is attached to GP14 and defined as a variable with the name button1. An extra variable with the name dooropen is defined. This will be used to count the number of times you press the button.

# Router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "YOUR-PASSWORD"
print("Connecting to wifi...")

# wifi connection
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, pw)

# wait for connection
while not wifi.isconnected():
    pass

print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))

Nothing special here. These are the standard program lines to connect the Pico to your router. Don't forget to replace YOUR-ROUTERS-NAME and YOUR-PASSWORD with the required values for your router.
When the connection is established you will find the Pico's IP number in MicroPython's shell.

while True:
    if button1.value() == 0:
        dooropen = dooropen + 1

The while loop is where the actual action takes place.
First the program tests if the button is pressed. If so then the variable dooropen is increased by 1.

        sendstring ="The door opened " + str(dooropen) + " times"

In this line we prepare the text that is going to be send.
This is the important line. Here you can fill in any information you like to send. If you would add a digital thermometer and put it's value in the variable temp you could alter the text like like this:

        sendstring ="The temperature is now " + str(temp) + " degrees"

On to the next part.

        requests.post("http://ntfy.sh/lucstechblog",
        data= sendstring              
        )


NTFY needs a post request in stead of the get requests which we normally use. We post to the site http://ntfy.sh/ and the topic is lucstechblog.

        print("Data is send. dooropen = "+str(dooropen))
        time.sleep(3)


Next we print a confirmation in the shell and wait a few seconds to make sure the request is send.

That is all.

The result.

Run the program. Press the button.



And this is what you'll see in Thonny's shell.



And here is how I got a notification in the top left corner of my phone's screen. My phone also gave an audio signal to draw my attention to the notification.



This is how the notification appeared on my phone's screen



And this is how it looks in the NTFY app on my phone.

At the same time the message appeared in the PC web version of NTFY.







Sending a message with an ESP32 in Arduino language (C++)

Just like we did with the Pico and MicroPython, we are going to do this the easy way. We are going to attach a button to the ESP32 and everytime the button is pressed the ESP32 will send a notification to the phone.

We are going to send an alarm with the text:

The button attached to the ESP32 was pressed X times.

The X will alter each time we press the button.

Let's start with the breadboard setup which is really easy.



It is just the ESP32 with a button attached to D22. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).

Here is the complete program.


#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";

//Where to send the notification
const char* ntfyurl = "http://ntfy.sh/lucstechblog";

const int buttonPin = 23;
int butpress = 0;

void setup() 
  {
  pinMode(buttonPin, INPUT);  
  
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) 
    {
      delay(500);
      Serial.print(".");
    }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
  }

void loop() 
{
    if (digitalRead(buttonPin) == LOW) 
      {
      butpress = butpress + 1;  
      if(WiFi.status()== WL_CONNECTED)
        { 
      WiFiClient client;
      HTTPClient http;
    
      // Your Domain name with URL path or IP address with path
      http.begin(client, ntfyurl);
      http.addHeader("Content-Type", "text/plain");
      
      // Build the text to send with HTTP POST:
      // The button attached to the ESP32 was pressed X times.
      String httpRequestData = "The button attached to the ESP32 was pressed "; 
      httpRequestData = httpRequestData + butpress;
      httpRequestData = httpRequestData + " times";  
      
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      Serial.print("The response we got : ");
      Serial.println(httpResponseCode);
        
      // Close connection
      http.end();

      // Wait before the next round
      delay (3);
        }
      }  
}


Lets look at some details in the program.

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";

//Where to send the notification
const char* nyfyurl = "http://ntfy.sh/lucstechblog";

const int buttonPin = 23;
int butpress = 0;

Nothing special here. The necessary libraries are loaded and The variables are defined. The variable ntfyurl is defined as http://ntfy.sh/lucstechblog which is the address of the NTFY server and the topic.

The setup() has nothing unusual.

The loop() is where the fun begins.

    if (digitalRead(buttonPin) == LOW)
      {
      butpress = butpress + 1;  
      if(WiFi.status()== WL_CONNECTED)
        {
      WiFiClient client;
      HTTPClient http;

The program continually tests if the button is pressed. If so the butpress variable is increased by 1 and the wifi and http clients are activated.

      // Your Domain name with URL path or IP address with path
      http.begin(client, ntfyurl);
      http.addHeader("Content-Type", "text/plain");

The http communication with the NTFY server is started with the previous defined ntfyurl. A header is sent first that identifies the data we are going to send as plain text.

      // Build the text to send with HTTP POST:
      // The button attached to the ESP32 was pressed X times.
      String httpRequestData = "The button attached to the ESP32 was pressed ";
      httpRequestData = httpRequestData + butpress;
      httpRequestData = httpRequestData + " times";

The text "The button attached to the ESP32 was pressed X times." is build here by combining several parts. One of the parts that is added is butpress which is the variable that counts how many times the button was pressed.

      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      Serial.print("The response we got : ");
      Serial.println(httpResponseCode);
        
      // Close connection
      http.end();

The request is send as a http POST request with the previous defined httpRequestData. The request receives a response with an indication if it has succeeded. The response is then printed in the serial monitor. After sending the request the connection is closed.

      // Wait before the next round
      delay (3);


The program then waits for 3 seconds. This time can be shortened but a short delay is preferred to prevent detecting a bouncing button as a button press.

It is obvious that this code can easily be adapted to send sensor readings etc. etc. etc.



This is what the Serial Monitor shows. As you can see there are 4 responses with the number 200 that means that the request was received ok.



And here are the notifications I received. As you can see I subscribed to 6 topics. The topics were made just for testing.

Expansion

In this example I use the same topic all the time: lucstechblog. It is of course possible to create multiple topics. So a single Pico or ESP can send notifications to several topics. However you can also have multiple microcontrollers sending data to several topics.

In the above examples we send notifications with just one line of text. You can send notifications with multiple lines of text. The documentation of NTFY shows how to do this. You can find the documentation here: https://docs.ntfy.sh/

Even better: you can attach files to a notification. These can be text files but also pictures !! I have successfully experimented with sending pictures from C++ and from MicroPython. I can see a chat program coming up...........

You can have the Pico's and ESP's send notifications to several NTFY servers.
On the NTFY documents pages there is a list of public NFTY servers. You can find the docs and that list here: https://docs.ntfy.sh/integrations/

You can start your own private server. A Raspberry Pi is sufficient. Even a humble Raspberry Pi Zero will do.
Using your own private server does not expose your topics (if someone finds them) and their data to a general audience. It restricts the information to those you have given the information about the server and it's topics.
On a private server you can expand the lifetime of the messages from 12 hour to any timelimit that suits you. And the number of messages you can send per day can be limitless !!!

Not only can you send notifications but using the right API call you can also get all notifications that have been send with a certain topic from the server. This way you can have two-way conversation between microcontrollers. A microcontroller can retrieve the messages on a certain topic from the server, and can act on that, and then send a notification with the same or a different topic. You do need a private server for this.

If you want a story on sending multiple line notifications, sending a textfile or a picture with the notification, starting your own server on a Raspberry Pi or retrieving notifications from your private server please send me an email.

I can see loads of possibilities with NTFY and therefore already installed my own private server.

Till next time.
Have fun
Luc Volders

Friday, May 1, 2026

Notifications with NTFY

For an index to all my stories click this text.

When working with IOT projects several things can happen. A certain temperature is reached, movement is detected, a light is set on in a room, someone is at the door etc. etc.etc. When something like this happens you will want to get a notification. You can, of course, build a website on which values are shown. But that implies that you need to go to that website to look at the values.

It is more efficient when you get a notification (an alarm) on your smart phone.



A notification like this is put on the startscreen of your phone so it will always draw your attention.

There is a free service that you can use to get these notifications it is called NTFY
You can find the website here: https://ntfy.sh/

NTFY

NTFY is of course short for NoTiFY. It is a free service that you can use. 

There is a limit of 250 notifications per day for a free or anonymous account. That is 10 messages per hour !!!

If you need more than 250 messages per day then you need to get a paid subscription.

To use NTFY you need to download a (free) app on your phone or tablet. But there is also a desktop (PC) version that can receive messages but can also send messages.

To send notification messages to your phone, tablet or PC there is a simple to use API that can be used with Arduino (C++) and MicroPython.

For using the free version you do not have to log-in or make an account. You can just use it. That is a bit like dweet.

Another similarity to Dweet is that a message/notification consists of two parts: a topic and the message itself. To get the notifications on your Phone or PC you need to "subscribe" to that topic.
A topic might be for example "Alarm" and the message can be "The garage door is open". Another topic might be "Myhome" and a message could be "The temperature = 22 degrees"

You may create as many topics as you like as long as you do not exceed the limit of 250 messages. A topic is created automatic when you send a message with your microcontroller that includes a non existant topic.

And yet another similarity to Dweet is that (unless you have a paid account) the topics are public. This means that anybody can get your messages and notifications as long as they know the topic you are using.
So use a cryptic topicname like LV23kit where LV are my initials, 23 is the year (2023) and kit means that the messages concern my kitchen. Just be creative.

If you need private topics you will need to get a paid plan.

The big difference with Dweet is that NTFY can send notifications to your phone/tablet/pc. Dweet can not send them, you need to collect them yourself. So for sending alarms NTFY is the best option.

There is one extra option that might prove usefull. NTFY can also send emails. So you can get your messages in your mailbox. For alarms that is not really an option as you want an instant notification if something is wrong. However it might be usefull for some of you so I will show how to use this option. With the free version you can send 5 emails per day.

One more thing though. The messages/notifications are stored for 12 hours. After 12 hours the messages disappear.

NTFY on the PC

First thing we are going to do is to get NTFY on your PC. Well that is easy. Just point your browser to https://ntfy.sh/app and you're done.



This is how the webpage looks..



Click on + Subscribe to topic and a window opens that allows you to enter the name of a topic.
Like stated before, for an anonymous (and free account), topics are public so choose a topic name that others can not guess easily.



You can also click on GENERATE NAME and NTFY will generate a topic for you that closely resembles a password.
This will give you some better privacy and secrecy but is more difficult to use on multiple devices at the same time. If, for example, you are using NTFY at the same time on your PC and on your smart phone you will need to find a way to send this cryptic topic name to your phone.

I choose a topic name myself: lucstechblog

Then click SUBSCRIBE.



This is how your screen will look now. On the left there is a list of subscribed topics. At this moment there is just one: lucstechblog. In the center there is a message that no notifications have been send or received with this topic.

NTFY on the Android Phone

To get notifications we need to install the NFTY app from the playstore. You can find it here:
https://play.google.com/store/apps/details?id=io.heckel.ntfy
Or just search for NTFY in the app store.



Install the app and open it.





It looks almost the same as the PC version. 





Press the + at the bottom of the screen for subscribing to a topic. We will use the same topic: lucstechblog
A big difference from the PC version is that there is no option to have NTFY generate a topic for you. This is because the phone version is only used for receiving notifications.

We now have 1 subscription to a topic.

Sending a message from the PC

Click with your mouse on the subscribed topic (lucstechblog)



And at the bottom type a test message like I did. Then click on the small arrow next to the message.



The PC screen will inform you that the message is send.



And you will almost immediately get a notification on your phone.
This is the important part. This shows that we can get alarm messages and other important messages as a notification on our phone.



And the NFTY app will inform you that a notification has been received.
And shows message also in the app.

First steps done.

The first setup is done.

Make yourself comfortable with the concept and create some topics for yourself and play around a bit.

Next time we are going to send notifications from the ESP32 using Arduino language (C++) and from the Raspberry Pi Pico with MicroPython.

A few small tips

You can use the browser version next to the app on your Phone. Just point your browser to: https://ntfy.sh/app That way you can also send messages from the phone that will be received by the PC. You will not get notification alarms through the browser but you will still get them through the app.

You can use NTFY on multiple phones and tablets. As long as they all subscribe to the same topics, they will all get the same notifications/messages.

And please remember that you can make as many topics as you like but there is a limit of 250 messages per day for the free account. The messages are stored on the server for 12 hours after which they vanish.

Although you can create loads of topics it is better and easier to maintain if you just use a few topics and make the messages in the topics more verbal.

Next story covers how to send notifications from your ESP32 with Arduino language (C++) or Raspberry Pi Pico W with MicroPython


So Till next time
have fun


Luc Volders











Friday, February 20, 2026

Text to Speech with voicerss

For an index to all my stories click this text.

This story shows how to convert text to spoken word using voicerss. This is the first in a series. This story tells how to use this service in your browser.

Some background.

I love playing with text to speech programs and services. I also think this can be a valuable addition to your projects. In the most dramatic scenario you can give spoken word feedback in your IOT projects to a blind person or a person who is visually impaired.
But there are more projects where a spoken word feedback can be valuable. And besides that it is just fun to hear your computer or microcontroller speak to you. There are several speech related projects on this weblog, but they use your phone for speech conversion.

In this and the upcoming story we are going to use a service called voicerss. And this will work on your computer but also on a microcontroller !! I will start with the computer version.

Voicerss.

Voicerss is a company that offers text to speech conversion. It is a commercial company but they have a free tier. And that tier is really generous.
You can make 350 free conversions per day and each one can have no less then 100K text. That is an awful lot for a free tier.

Even for small messages this is a lot.
350 messages a day is 14 messages per hour. But you are not likely to be awake 24 hour a day. Meaning that if you for example use this 10 hour a day you can have 35 messages per hour, meaning every 2 minutes. Well you can do the calculations yourself.

Create an account

To use voicerss there is a very simple API that can be called from a large variety of computer languages.
You do need to make an account to obtain your personal API key.


Start with visiting the Voicerss site: https://www.voicerss.org/


Chose login from the menu and at the bottom chose registration.


Fill in all the fields. You do not need to give a company name. But do fill in your real e-mail address. And of course chose an appropriate password.
Then check "I am not a robot" and press the register button at the bottom.

A confirmation email will be send to your email address. So open your email program. Look for that mail and press on the link.


The profile screen now shows at the bottom that your account is active. And it shows your API key.

The voicerss API

The API is what we need to let our computer (or microcontroller) communicate with voicerss. It is really very easy.

Look at the page with the API info.

If you scroll a bit down you can see the examples.
You can copy any one of them and just paste it into your browsers URL field.
But before pressing enter change key=1234567890QWERTY.
After the = fill in your own API key.

Then press enter. And hear the magic happening.

Experiment with this by altering the text in anything you like.

Javascript example


There are several examples at the SDK page. Just pick your preferred language and click on it.


This is the page that shows how to use voicerss with Javascript.

Start with clicking on Download Javascript text-to-speech sdk.

The download starts immediately. And a zip file will be downloaded in your computers download folder. I transferred it to a folder called voicerss I made for this article.

Clicking on that zip file reveals that it contains just a small javascript library called voicerss-tts-min.js. Extract that to the same forlder where you are going to put your own program in. This is important. The voicerss-tts-min.js library should be in the same folder where your javascript program will be. If you do not put it there your program will not be able to find the library.

At the bottom of the Javascript SDK page there is also a small example program. I downloaded that also and called it voicetest-minimal.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset='utf-8' />
    <script src='voicerss-tts.min.js'></script>
</head>
<body>
    <script>
        VoiceRSS.speech({
            key: '<API key>',
            src: 'Hello, world!',
            hl: 'en-us',
            v: 'Linda',
            r: 0,
            c: 'mp3',
            f: '44khz_16bit_stereo',
            ssml: false
        });
    </script>
</body>
</html>


Above is this program and as you can see it is very simple. That is of course because it uses the voicerss-tts-min library.

To get this working you need to change <API key> in your own API key. Only the key, do not put in the brackets.

Save the html page and then double click on it. Your browser should open saying the words Hello world. Make sure to have the volume of your speakers up.

Now this is a very simple program that can be adapted for many different projects. You could embed this in your IOT dashboards or in any project that uses Javascript to monitor or control data.

No library needed

As you have seen above you can paste the API direct in the browsers URL. So obviously using the right code you do not need the Javascript library.




I wrote a program in Javascript (and admittedly had some help with the styling). This opens a webpage with a field in which you can type text.

The code is below. Just copy it from this page. Paste it into an editor and save it as voice-test.html or something like that. Then click on that file and it will pen in your favorite browser.

Pressing the SEND button sends the text to voicerss and the program has an audio player that plays the received spoken words.
You can replay audio as often as you like by pressing the play button in the audio player.
You can of course also alter the text and resend it to voicerss.

But there is more

The received audio is also saved in your Downloads folder.
For those that wonder: my computer is a Raspberry Pi5 with 8GB and I am running Raspberry Trixie with the KDE Plasma shell. That is why the downloads folder might look unfamiliar.

Here is the program:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Text to Speech Demo</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      background: #f9f9f9;
    }

    textarea {
      width: 100%;
      height: 150px;
      padding: 10px;
      font-size: 16px;
      border: 1px solid #ccc;
      border-radius: 5px;
      resize: vertical;
    }

    button {
      margin-top: 10px;
      padding: 10px 20px;
      font-size: 16px;
      background-color: #0078d4;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }

    button:hover {
      background-color: #005fa3;
    }

    audio {
      margin-top: 20px;
      width: 100%;
    }
  </style>
</head>
<body>
  <h1>Text-to-Speech (VoiceRSS)</h1>

  <textarea id="textInput" placeholder="Type your text here..."></textarea><br>
  <button id="sendButton">Send</button>

  <audio id="audioPlayer" controls></audio>

  <script>
    const button = document.getElementById('sendButton');
    const textInput = document.getElementById('textInput');
    const audioPlayer = document.getElementById('audioPlayer');

    button.addEventListener('click', async () => {
      const text = textInput.value.trim();
      if (!text) {
        alert('Please enter some text first.');
        return;
      }

      const apiKey = 'replace-with-your-key'; // replace with your real VoiceRSS key
      const language = 'en-us';
      const voice = 'Amy';

      try {
        // VoiceRSS expects a POST with form data
        const formData = new FormData();
        formData.append('key',apiKey);
        formData.append('src', text);
        formData.append('hl', language);
        formData.append('v', voice);
        formData.append('c', 'WAV'); // codec
        formData.append('f', '8khz_16bit_mono');

        const response = await fetch('https://api.voicerss.org/', {
          method: 'POST',
          body: formData
        });

        const blob = await response.blob();

        // VoiceRSS sometimes returns text error messages instead of audio
        const contentType = blob.type || '';
        if (!contentType.startsWith('audio/')) {
          const textError = await blob.text();
          console.error('VoiceRSS error:', textError);
          alert('VoiceRSS error: ' + textError);
          return;
        }

        // Create object URL for playback and saving
        const audioUrl = URL.createObjectURL(blob);

        // Play in audio element
        audioPlayer.src = audioUrl;
        audioPlayer.play();

        // Trigger file save
        const downloadLink = document.createElement('a');
        downloadLink.href = audioUrl;
        const safeText = text.slice(0, 20).replace(/[^a-z0-9]/gi, '_'); // clean name
        downloadLink.download = `tts_${safeText || 'output'}.mp3`;
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
      } catch (err) {
        console.error(err);
        alert('Failed to fetch or play audio.');
      }
    });
  </script>
</body>
</html>

There are just two things in this program that I want to go into detail here.

      const apiKey = 'replace-with-your-key'; // replace with your real VoiceRSS key
      const language = 'en-us';
      const voice = 'Amy';

Before running this code change 'replace-with-your-key' indeed with your own API key. 

      try {
        // VoiceRSS expects a POST with form data
        const formData = new FormData();
        formData.append('key',apiKey);
        formData.append('src', text);
        formData.append('hl', language);
        formData.append('v', voice);
        formData.append('c', 'WAV'); // codec
        formData.append('f', '8khz_16bit_mono');

        const response = await fetch('https://api.voicerss.org/', {
          method: 'POST',
          body: formData
        });

And here you can see that I did not use the Javascript library but made an ordinary fetch request.

And hey ? What's that ???
The codec is WAV and 8khz in 16 bit mono ???

Can we do something with that ??????
Well that is for another story. You'll be surprised.

The API

I urge you to look at the API page.

You can change:

- The language
- The voice male/female often multiple voices
- The audio codecs MP3/WAV/AAC/OGG/CAV
- Audio format: from 8Khz-8bit to 48Khz-44khz_16bit

Plenty of room to play around with.

Concluding

voicerss is a cloud based service and I actually lately have a dislike for cloud based services. The dislike comes from many cloud based services that suddenly shut down (dweet, original blynk, iotTweet, logitech pop etc.) or suddenly start charging for their services (IFTTT webhooks).

Nevertheless is voicerss a fun service to play with and build some projects around. I have some ideas for this and will publish them as soon as they are mature.
The API is very easy to use in all kinds of programming languages.
And most important: they have a very generous free tier which makes it possible for us mere hobbyists to build some great projects for free.

Till next time
have fun

Luc Volders