Repository navigation
Communication HTTP Client
The HTTP client classes let your microcontroller play internet radio, download audio files or send audio to a web server. They are Arduino Streams, so you can copy their data to a decoder and an output like from any other source. See Communication for the general considerations.
Contents
- Classes
- Playing a stream
- Internet radio with metadata: ICYStream
- Buffered streams
- Sending audio: POST
- Things to consider
All of them implement the AbstractURLStream API (include AudioTools/Communication/AudioHttp.h):
| Class | Description |
|---|---|
URLStream |
HTTP(S) GET, POST, PUT, DELETE |
ICYStream |
URLStream that also extracts the ICY (Shoutcast/Icecast) metadata: title, station ... |
URLStreamBuffered, ICYStreamBuffered
|
a task fills a buffer in the background, so that short network interruptions don't stop the audio |
They use the Arduino network API (WiFi, Ethernet or any other Client). For the ESP32 outside of Arduino (ESP-IDF) there are URLStreamESP32, ICYStreamESP32, URLStreamBufferedESP32 and ICYStreamBufferedESP32, which use the ESP-IDF HTTP client; without Arduino, URLStream etc. are aliases for these.
From streams-url_mp3_helix-i2s.ino: an MP3 internet radio, decoded and played via I2S:
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h" // https://github.com/pschatzmann/codec-helix
#include "AudioTools/Communication/AudioHttp.h"
URLStream url("ssid", "password");
I2SStream i2s;
EncodedAudioStream dec(&i2s, new MP3DecoderHelix());
StreamCopy copier(dec, url);
void setup() {
auto config = i2s.defaultConfig(TX_MODE);
i2s.begin(config);
dec.begin(); // the decoder sets the I2S format from the stream
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128", "audio/mp3");
}
void loop() { copier.copy(); }begin(url, acceptMime, method, requestMime, requestData) sends the request; the second parameter is the Accept header. If you pass the SSID and password to the constructor, the stream connects to WiFi (and switches off WiFi power save unless you call setPowerSave(true)); otherwise connect WiFi yourself, or pass your own Client with setClient() - e.g. an EthernetClient or a WiFiClientSecure for HTTPS.
There are examples for many formats: MP3 (Helix, MAD), AAC, FLAC, Vorbis, MPEG-TS, raw PCM, and for writing the stream to a file. To find out the format of an unknown stream, mime() returns the content type of the reply - or use a MultiDecoder.
Most internet radios send the current title in the stream (ICY metadata). ICYStream removes it from the audio data and reports it to a callback. With the AudioPlayer and an AudioSourceURL you can also switch between stations. From player-url_icy-i2s.ino:
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Disk/AudioSourceURL.h"
#include "AudioTools/Communication/AudioHttp.h"
const char *urls[] = {
"http://stream.srg-ssr.ch/m/rsj/mp3_128",
"http://stream.srg-ssr.ch/m/drs3/mp3_128",
};
ICYStream urlStream("ssid", "password");
AudioSourceURL source(urlStream, urls, "audio/mp3");
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);
void printMetaData(MetaDataType type, const char* str, int len) {
Serial.print(toStr(type));
Serial.print(": ");
Serial.println(str);
}
void setup() {
auto cfg = i2s.defaultConfig(TX_MODE);
i2s.begin(cfg);
player.setMetadataCallback(printMetaData);
player.begin();
}
void loop() { player.copy(); }player.next() switches to the next station. See Audio Metadata for more about metadata.
The network delivers the data irregularly. URLStreamBuffered and ICYStreamBuffered read it in a separate task into a buffer, from which your sketch reads - so the playback continues during short interruptions. Use them like URLStream/ICYStream; they need a platform with tasks (e.g. ESP32).
To send audio to a web server, write it to an HttpRequest. From streams-http_post.ino, which posts 60 seconds of a sine tone:
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
TimedStream timed(sound); // ends the stream after 60 seconds
WiFiClient client;
HttpRequest http(client);
StreamCopy copier(http, timed);
void setup() {
// ... connect WiFi
sineWave.begin(AudioInfo(44100, 2, 16), N_B4);
timed.setEndSec(60);
timed.begin();
Url url("http://192.168.1.44:9988");
http.header().put(TRANSFER_ENCODING, CHUNKED);
http.processBegin(POST, url, "audio/pcm");
}
void loop() {
if (!copier.copy()) http.processEnd(); // finish the request at the end
}The python-post-server can receive it on a PC. To post a complete stream in one call, use url.begin(url, accept, POST, "audio/pcm", stream, len).
-
HTTPS: pass a
WiFiClientSecurewithsetClient(); for testing you can callclient.setInsecure(). - Redirects: are followed automatically.
- Interruptions: if the stream stops, check the network first - see Communication; a buffered stream bridges short interruptions.
-
Timeouts:
setTimeout(ms)sets the read timeout of the connection.