lastfm scrobbler for icecast

Soumettre à Last.fm les chansons d’un flux Icecast

Voici le script python que j’ai écrit pour soumettre automatiquement à Last.fm les chansons qui sont diffusées sur ma radio Icecast.

Au fil du temps, j’ai publié dans ces colonnes différents tutoriels pour gérer une radio avec Icecast, à l’aide de Winamp, VirtualDJ, et SAM Broadcaster dont on pouvait créer un fichier texte qui pouvait ensuite être filtré puis utilisé avec un script PHP pour soumettre les chansons à Last.fm.

Il y a quelques semaines, Stéphan m’a contacté pour m’informer que le script PHP que j’utilisais jusqu’alors pour scrobbler les titres était maintenant incompatible avec PHP8, et qu’il lui fallait installer PHP7.4 spécifiquement pour le faire tourner.

Le script n’utilisait pas les dernières API de Last.fm non plus, donc c’était le bon moment de moderniser tout cela. J’en ai d’ailleurs profité pour servir le serveur Icecast en HTTPS.

Le choix de Python

Après de multiples essais, je me suis vite rendu compte que PHP n’était pas du tout adapté au scrobbling : la plupart des librairies PHP sont maintenant obsolètes (PHP8) ou ne sont plus maintenues car Last.fm est en perte de vitesse (par rapport à ce que c’était il y a quelques années).

Python, au contraire, est très simple à utiliser et il existe une librairie spécifique dédiée à l’API Last.fm qui nous permet de soumettre les titres simplement: pylast.

Enfin, l’avantage de python est qu’il est installé et mis à jour sur toutes les distributions Linux et MacOS nativement et donc cela rend le code portable et facile à transporter.

Outre Python 3, vous avez besoin du gestionnaire de paquets pip :

apt install python3-pip

Vous avez également besoin de quelques modules supplémentaires, que l’on installe avec pip :

python3 -m pip install --upgrade pip
pip3 install pylast
pip3 install requests

C’est tout ce qu’il vous faut au niveau des dépendances. Plus besoin de PHP ni de ses librairies, plus besoin de stocker le nom des titres dans un fichier texte, tout va se faire en direct depuis le serveur Icecast.

Last.FM Scrobbler for Icecast

Le script Last.FM Scrobbler for Icecast vérifie le statut du server Icecast toutes les 30 secondes. Si le serveur est démarré et que la radio joue, il récupère les informations de la chanson et les soumet à Last.fm, tout en vérifiant bien que la chanson n’est pas la même que la précédente. Cela évite tout doublon, ce qui fausserait les soumissions du compte.

Si le serveur Icecast n’est pas démarré, le script vous avertit et attend 5 minutes.

Si le serveur Icecast est démarré mais que le fichier status-json.xsl ne contient pas les informations nécessaires, le script vous avertit et vous recommande de redémarrer votre webradio car la connexion avec Icecast est perdue.

On crée notre script:

nano /home/scripts/lastfm-scrobbler-icecast.py

Et on y ajoute:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------
# Script name : Last.FM Scrobbler for Icecast
# Created By  : Matt Biscay
# Created Date: 2023/01/24
# Author URI  : https://www.skyminds.net
# Version     : 1.0.0
# Copyright   : 2023 SkyMinds.Net
# ---------------------------------------------------------------------- 
"""
This script will check the status of the icecast server every 30 sec and if the server is running, it will check for the currently playing track and scrobble it to LastFM if it's different from the last scrobbled track.
If the server is not running, the script will wait for 5 minutes before retrying.
It uses the pylast library to interact with the LastFM API.

@param API_KEY: the LastFM API key
@param API_SECRET: the LastFM API secret
@param username: the LastFM username
@param password: the LastFM password
@param icecast_url: the URL of the icecast server status page
"""

import pylast
import time
import requests
import json
# --------------------------------------------------
# --------- EDIT CONFIGURATION HERE ----------------
# --------------------------------------------------
# Your LastFM API key and secret
API_KEY = "LASTFM_API_KEY"
API_SECRET = "LASTFM_API_SECRET"

# The username and password of the user you want to authenticate 
# and scrobble the track for
username = "LASTFM_USER"
password = "LASTFM_PWD"

# The URL of the Icecast server's status-json.xsl page
icecast_url = "http://icecast.example.com:8000/status-json.xsl"

# ------------------------------------------------
# ---------- END OF CONFIGURATION  ---------------
# ------------------------------------------------

# Create a new LastFM network object
network = pylast.LastFMNetwork(api_key=API_KEY, api_secret=API_SECRET,
                               username=username, password_hash=pylast.md5(password))

# The previously scrobbled track name
previous_track = ""

print("# ------------------------------------------ #")
print("#  Script: Last.FM Scrobbler for Icecast     #")
print("#  Author: Matt Biscay                       #")
print("#  URL   : https://www.skyminds.net          #")
print("# ------------------------------------------ #")
print("")

while True:

    try:
        # Make a GET request to the status-json.xsl page
        response = requests.get(icecast_url)
    except requests.exceptions.ConnectionError as e:
        print("Error: Icecast server is down.")
        # Wait for 5 minutes before retrying
        time.sleep(5*60)
        continue

    if response.status_code != 200:
        print("Error: Icecast server is not running or there is some other error")
        # Wait for 5 minutes before retrying
        time.sleep(5*60)
        continue

    # Parse the JSON response
    data = json.loads(response.text)

    # Get the currently playing track information
    if "icestats" in data and "source" in data["icestats"] and "artist" in data["icestats"]["source"] and "title" in data["icestats"]["source"]:
        artist = data["icestats"]["source"]["artist"]
        track = data["icestats"]["source"]["title"]
        current_track = f'{artist} - {track}'
        if current_track != previous_track:
            # Scrobble the track
            try:
                timestamp = int(time.time())
                network.scrobble(artist=artist, title=track, timestamp=timestamp)
                print(f"Track scrobbled successfully: {current_track}")
                previous_track = current_track
            except pylast.WSError as e:
                print("Error:", e)
        # Wait for 30 seconds before checking for new tracks
        time.sleep(30)
    else:
        print("Error: Icecast XML does not contain the required information. Restart your webradio.")
        # Wait for 1 minutes before retrying
        time.sleep(60)
        continue

Editez les variables dans la partie EDIT YOUR CONFIGURATION: vous avez besoin de votre clé API last.fm ainsi que la clé API secret, de votre nom d’utilisateur et mot de passe last.fm, et enfin l’adresse complète du fichier XML d’Icecast, status-json.xsl.

Lire la suite

icecast ssl https cloudflare

Configurer Icecast avec un certificat SSL et Cloudflare

Voici comment configurer un serveur Icecast pour utiliser un certificat SSL pour proposer des flux radio servis en HTTPS, le tout derrière Cloudflare.

Depuis que Strict Transport Security (HSTS) a été activé par défaut pour tous les sites hébergés sur le serveur, la page de Thunderstruck Radio ne s’affiche plus correctement car le serveur Icecast est encore servi en simple HTTP, donc sans certificat SSL.

Nous allons donc changer tout cela et sécuriser Icecast avec le certificat SSL de notre domaine, de manière à ce que les flux radio ainsi que le flux JSON soient servis en HTTPS.

Étape 1 : créer un sous-domaine au niveau DNS

Il vaut mieux séparer la radio de votre site principal, c’est beaucoup plus simple à gérer et évite les épineux problèmes de configuration.

J’opte pour ajouter le sous-domaine thunderstruck.skyminds.net avec un enregistrement DNS de type A dans Cloudflare:

thunderstruck.skyminds.net.	1	IN	A	xxx.xxx.xxx.xxx

On garde le sous-domaine en DNS seulement, nul besoin d’activer le cache (puisque c’est un flux).

Étape 2 : ouvrir le port 8443 dans le pare-feu

J’utilise Cloudflare donc nous avons quelques ports HTTPS ouverts par défaut qui peuvent être utilisés sans blocages :

# Ports HTTPS ouverts par défaut chez Cloudflare, sans support cache :

    443
    2053
    2083
    2087
    2096
    8443

Nous utilisons ufw donc la commande est très simple pour ouvrir le port 8443 :

ufw allow 8443/tcp comment "Icecast SSL"

Le serveur accepte désormais les connexions sur le port 8443 pour Icecast.

Étape 3 : configurer le sous-domaine sous NginX

Nous allons maintenant configurer notre sous-domaine et éditer le bloc serveur de notre domaine sous NginX:

nano /etc/nginx/sites-available/skyminds.conf

Et nous y ajoutons ce bloc:

# Thunderstruck.skyminds.net
server {
    listen       8443 ssl http2;
    listen  [::]:8443 ssl http2;

    server_name thunderstruck.skyminds.net;

    # Let's Encrypt
    ssl_certificate         /etc/nginx/ssl/skyminds.net/fullchain.pem;
    ssl_certificate_key     /etc/nginx/ssl/skyminds.net/privkey.pem;

    location / {
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        proxy_pass              http://127.0.0.1:8443;
        proxy_read_timeout      90;
        proxy_redirect          off;
        proxy_buffering         off;
        tcp_nodelay             on;

	    # CSP headers
	    add_header Content-Security-Policy "media-src 'self' https://thunderstruck.skyminds.net:8443";
    }
}

Testez la configuration et rechargez nginx :

nginx -t

service nginx reload

Étape 4 : unifier le certificat SSL et sa clé privée

Icecast peut fonctionner avec un certificat SSL à partir de la version 2.4.4. Commencez donc par vérifier que cette version est à minima installée sur le serveur:

icecast2 -v

Ensuite, Icecast nécessite un fichier de certificat unique, qui est en fait une compilation du certificat et de sa clé privée.

Nous créons donc un fichier shell qui va contenir notre commande:

nano /home/scripts/icecast-ssl.sh

et dans lequel nous ajoutons notre commande cat :

#!/bin/bash
cat /etc/nginx/ssl/skyminds.net/fullchain.pem /etc/nginx/ssl/skyminds.net/privkey.pem > /etc/icecast2/bundle.pem

Vous pouvez exécuter le fichier de manière à générer le fichier bundle.pem:

bash /home/scripts/icecast-ssl.sh

On assigne maintenant les bons droits pour que le certificat soit lisible par icecast2:

chown icecast2:icecast /etc/icecast2/bundle.pem

Étape 5 : automatiser le renouvellement du certificat Icecast

J’utilise acme.sh pour la génération et le renouvellement automatique de tous les certificats du serveur donc il est très utile d’éditer la configuration du certificat pour que le script de génération du certificat pour SSL ait lieu automatiquement, juste après le renouvellement du certificat de notre domaine.

On édite donc la configuration acme.sh du domaine:

nano /root/.acme.sh/skyminds.net_ecc/skyminds.net.conf

Et nous éditons la directive Le_RenewHook avec le chemin de notre nouveau script shell :

Le_RenewHook='bash /home/scripts/icecast-ssl.sh && service icecast2 restart'

Sauvegardez les changements.

Lire la suite

iphone-icecast-add-stream

Ecouter une webradio Icecast sur un iPhone ou iPod Touch

iphone icecast icon

Je me suis posé la question de savoir si ma webradio pouvait être écoutée sur un iPhone ou iPod Touch. Et bien sachez que ce n’est pas possible nativement : le lecteur Quicktime intégré à l’iPhone ou iPod Touch attend un protocole de flux (RTSP, MMS…) et non le protocole HTTP.

Il est toutefois possible de lire un flux Icecast avec une application, FStream.

Installation de l’application FStream

Rendez-vous dans l’AppStore et installez l’application FStream, qui a le gros avantage d’être gratuite ce qui est idéal pour les tests (je vous encourage à donner un tip aux développeurs des applications que vous utilisez).

FStream est capable de lire les formats audio OGG Vorbis (via HTTP), AAC/AAC+ (via HTTP), MP3 (via HTTP), WMA (via MMS/MMSH – ASF). Il reconnaît les playlists M3U – PLS – ASX et peut encoder des flux aux formatx MP3, AAC, AIFF, WAV.

Lire la suite

Plugin Last.fm pour SAM Broadcaster sous Ubuntu photo

Plugin Last.fm pour SAM Broadcaster sous Ubuntu

sam_lastfm_ubuntu_logo

Maintenant que SAM Broadcaster tourne sous Ubuntu, il ne me reste plus qu’à configurer mon plugin last.fm pour SAM avec PHP.

L’installation est assez semblable à celle sous Windows. Vous ne devriez donc pas être perdus. Pour les nouveaux, voici comment faire.

Etape 1 : Installation de PHP et de cURL

Tout d’abord, vous avez besoin du binaire PHP :

sudo apt-get install php7.4-cli

ainsi que de la librairie cURL pour les appels distants :

sudo apt-get install curl libcurl3 libcurl3-dev php7.4-curl

Lire la suite

Installer SAM Broadcaster sous Ubuntu avec Wine photo

Installer SAM Broadcaster sous Ubuntu avec Wine

Ce n’est un secret pour personne, je suis un inconditionnel de SAM Broadcaster. C’est pour moi l’un des meilleurs logiciels pour animer une webradio et c’est la seule chose qui me retenait sur Windows.

Et bien ce n’est plus le cas puisque je viens de l’installer sous Ubuntu par l’intermédiaire de Wine et tout fonctionne impeccablement.

Par contre, c’est un tantinet plus complexe à mettre en place. Ce petit guide devrait vous aider.

Lire la suite

sam broadcaster fx

Rajouter des sons d’effets spéciaux (FX) dans SAM Broadcaster

Récemment, Gnash m’a demandé comment on pouvait rajouter des sons pour étoffer sa liste de sons d’effets spéciaux sous SAM Broadcaster.

Et bien, c’est tout simple et ne prend que quelques secondes. Suivez le guide.

Etape 1 : ajout de vos sons dans la section SoundFX

Tout d’abord, commencez par sélectionner la fenêtre Playlist. C’est là que vous gérez tous vos morceaux, jingles, publicités et bien sûr les effets à lancer depuis la console.

Dans cette fenêtre, sélectionnez Content > Sound FX > demoFX. Tous les effets se trouvent là, classés dans plusieurs sous-répertoires, comme dans l’image ci-dessous :

sam broadcaster fx

Lire la suite

SAM Broadcaster : mixer pipeline

Supprimer l’écho du micro sous SAM Broadcaster

sound_wave_echo Cette question me revient régulièrement de la part des utilisateurs de SAM Broadcaster : comment faire pour supprimer l’écho du micro lorsque l’on intervient sur la radio ?

La solution est simple : il suffit d’envoyer le son du micro directement dans l’encodeur, sans passer par le retour de la carte son.

Lire la suite

Plugin Last.fm pour SAM Broadcaster (Windows)

Je vous ai parlé dernièrement de mon adhésion à last.fm et de l’absence regrettable d’un plugin last.fm pour SAM Broadcaster.

Et bien, cela y est, j’ai réuni tout ce qu’il faut pour pouvoir scrobbler en toute quiétude, tout en laissant tourner votre webradio !

SAM Broadcaster & Last.fm

Contrairement aux autres lecteurs audio classiques, il ne s’agit pas d’une extension toute compilée à installer mais d’un script PHP qui va se charger de mettre à jour votre profil last.fm via CURL.

Installation et configuration prennent moins de 10 minutes.

Lire la suite

Script PAL pour SAM Broadcaster : créer une playlist variée par rotation automatique

Le script PAL suivant permet de créer une playlist automatique en se servant des règles de rotation indiquées dans Configuration > Playlist rotation rules :

SAM : rotation de playlist

Pour que le script PAL suivant fonctionne correctement, il y a quelques pré-requis :

  • placez vos fichiers dans les catégories du bloc Playlist de SAM. Pour les besoins de ce tutoriel, nous plaçons nos fichiers dans Playlist > Tracks.
  • si votre webradio a des jingles, placez-les dans Playlist > Content > Station IDs (All).

Lire la suite

Script PAL pour SAM Broadcaster : jouer un bip horaire

Ce script PAL permet de jouer un bip horaire au début de chaque nouvelle heure. Il faut pointer vers le fichier son qui contient les bips.


{Script PAL - Bip horaire par Matt - www.skyminds.net}
function ActivePlayer:TPlayer; forward;

{On attend la bonne heure}
PAL.WaitForTime(T['XX:00:00']);

{On ajoute le fichier bip}
Queue.Addfile('C:\bip.wav',ipTop);
ActivePlayer.FadeToNext;

{On lance le bon deck}
function ActivePlayer:TPlayer;
begin
if DeckA.Status = psPlaying then
Result := DeckA
else
Result := DeckB;
end;

Lire la suite

Animer une webradio à plusieurs avec SAM Broadcaster : la co-animation via VoIP

Vous avez suivi le tutoriel pour créer une webradio avec SAM Broadcaster et vous souhaitez animer une émission à plusieurs ?

SAM devrait proposer cette fonctionnalité dans une prochaine version mais en attendant, force est de constater qu’il faut utiliser des moyens quelque peu détournés…

Vous aurez besoin de 2 répartiteurs audio miniJack stéréo 3,5 mm mâle/2 miniJack stéréo 3,5 mm femelle ainsi que d’un câble audio miniJack stéréo 3,5 mm mâle/minJjack stéréo 3,5 mm mâle (20cm suffisent).

Cette installation n’est à faire que sur la machine qui diffuse bien évidemment. L’opération demande à peine 5 minutes.

Principe de fonctionnement

Nous allons installer une solution gratuite de VoIP comme Skype afin de mettre en relation les différents animateurs de l’émission.

Chaque animateur communiquera donc via Skype et la sortie audio des échanges sera redirigée vers l’entrée micro, faisant ainsi partager les interactions des animateurs avec les auditeurs.

Lire la suite