Catégories
Gstreamer Musique Open-source Planet-libre

Streaming audio haute qualité avec AAC

Le codec AAC (Advanced Audio Coding dont les fichiers portent souvent l’extension. MP4) est devenu au moins aussi populaire que le bon vieux MP3. Le fait que ce soit le codec audio utilisé par iTunes, le leader mondial de la vente en ligne, n’y est surement pas étranger.

Nous allons dans ce billet voir que l’on peut également utiliser ce codec lors de streaming. Je ne suis pas le premier à avoir cette idée car l’AAC est déjà utilisé pour la diffusion de la radio numérique Japonaise.

On ne change pas une équipe qui gagne, nous allons utiliser le framework GStreamer pour faire ce petit test de streaming audio entre deux machines. Pour ceux qui ne sont pas habitués à la notion de pipeline GStreamer, je vous conseille la lecture de ce billet.

Que cherche t’on à faire ?

Nous allons essayer de diffuser (« streamer ») un flux audio (par exemple un .WAV non compressé pour être sûr d’avoir une source de bonne qualité) depuis une machine A vers une machine B (reliées par un réseau IP) en utilisant un encodage AAC-LC et une encapsulation MPEG-4 / RTP.

Création de la pipeline d’émission

Si vous avez bien suivi, la commande suivante doit être saisie sur la machine A:

gst-launch -tv \

gstrtpbin name=rtpbin latency=0 buffer-mode=0 \

filesrc location=\ »samples/test.wav\ » ! decodebin ! audioconvert \

! queue ! faac bitrate=128000 ! rtpmp4apay \

! rtpbin.send_rtp_sink_1 \

rtpbin.send_rtp_src_1 ! udpsink port=6969 host=$IP_B

Bien que fait cette commande:

  1. elle lance GStreamer (gst-launch)
  2. Elle produit un flux réseau RTP (gstrtpbin)
  3. La source audio du flux réseau RTP sera un fichier WAV (filesrc), qui sera décodé (decodebin)
  4. On encode en AAC en utilisant le plugin faac (basée sur FAAC l’implémentation libre du codec AAC) en fixant un débit réseau cible de 128Kbps (128000 bits). On utilisera ainsi un streaming de type CBR (constant bitrate), c’est à dire que l’on fixe le débit et que le codec s’arrange pour adapter la qualité
  5. On encapsule le résultat dans une trame RTP MP4 Audio (rtpmp4apay)
  6. On stream en UDP (udpsink) vers la machine $IP_B  (à remplacer par l’adresse IP de la machine B) et sur le port 6969

Création de la pipeline de réception

A saisir sur la machine… B (bravo vous avez gagné une partie gratuite):

gst-launch -tv \

udpsrc port=6969 caps= »application/x-rtp, media=(string)audio, clock-rate=(int)16000, encoding-name=(string)MP4A-LATM, cpresent=(string)0, payload=(int)96, config=(string)40002810″ \

! gstrtpjitterbuffer latency=200 drop-on-latency=true ! rtpmp4adepay ! faad \

! audioconvert ! audioresample ! autoaudiosink

Que fait cette commande:

  1. Elle lance GStreamer (gst-launch)
  2. Elle écoute sur le port UDP port 6969 en filtrant les paquets RTP MP4A (udpsrc). La valeur a mettre dans la string config varie selon la fréquence d’échantillonnage de votre source. Elle est affichée lors du lancement de la pipeline A.
  3. Elle bufferise les paquets dans un buffer qui aura une taille maximale de 200ms (à adapter selon la qualité de votre réseau entre A et B). Si les paquets sortes de ce buffer avec plus de 200ms, ils seront dropés (donc perte de paquets, perte d’information, perte de son…).
  4. On décode le paquet RTP (rtpmp4adepay)
  5. On décode le flux audio AAC (faad)
  6. On joue le son sur le périphérique de sorti audio standard (autoaudiosink)

Résultat des tests

Après avoir fait mumuse avec des sources différentes (musique, voix…) et des débits plus ou moins importants (de 8 à 320 Kbps). On arrive à des résultats très intéressants.

Par exemple pour de la voix (« Pierre si tu m’entends 🙂 »), on arrive à une qualité tout à fait acceptable en réglant un bitrate de 16bps pour un flux à 16KHz.

Pour la musique, point de salut en dessous de 128 Kbps (à moins de se contenter d’une qualité vraiment médiocre). A 256 Kbps, on a une qualité qui correspond à une écoute depuis un fichier .MP4 téléchargé sous iTunes Store. Au dessus de 256 Kbps, je n’ai pas noté d’amélioration (mais je n’avais pas un périphérique de sorti de très grande qualité).

Catégories
Gstreamer Open-source

Test du codec Speex dans Gstreamer

Speex (wiki / site officiel) est un codec audio libre (licence dérivée de BSD) dont les perfomances sont très intéressantes, surtout pour transporter un signal comme la voix humaine. Le but de ce billet est de tester ce codec dans le cadre d’une application de streaming audio.

Mise en place du test

Pour tester ce codec, j’utilise le framework GStreamer et deux scripts shell tournant sur deux machines différentes. Le script rtpserver.sh prend comme source le microphone par défaut de votre machine, encode le flux en Speex, puis le diffuse en RTP/UDP vers la seconde machine. Le script rtpclient.sh récupére le flux RTP/UDP venant de la première machine, le décode et le diffuse sur la sortie son par défaut.

Le script rtpserver.sh:

#!/bin/sh

SEND_TO_ADDR=192.168.29.111
SEND_TO_RTP_PORT=5003
SEND_TO_RTCP_PORT=5004
RECV_FROM_RTCP_PORT=5005

ENCODER=speexenc
PAYLOADER=rtpspeexpay

SPEEX_PARAMS= »quality=4 vad=true dtx=true »
SPEEX_CAPS= »audio/x-raw-int,rate=16000″

ENCODER_PARAMS=${SPEEX_PARAMS}
RTP_PARAMS= »latency=200″
AUDIO_CAPS=${SPEEX_CAPS}

gst-launch -v  gstrtpbin name=rtpbin ${RTP_PARAMS} \
alsasrc \
! queue ! audioresample ! ${AUDIO_CAPS} ! ${ENCODER} ${ENCODER_PARAMS} ! ${PAYLOADER} \
! rtpbin.send_rtp_sink_1 \
rtpbin.send_rtp_src_1 ! udpsink port=${SEND_TO_RTP_PORT} host=${SEND_TO_ADDR} \
rtpbin.send_rtcp_src_1 ! udpsink port=${SEND_TO_RTCP_PORT} host=${SEND_TO_ADDR} sync=false async=false \
udpsrc port=${RECV_FROM_RTCP_PORT} ! rtpbin.recv_rtcp_sink_1

Le script rtpclient.sh:

#!/bin/sh

SEND_TO_RTCP_PORT=5005
RECV_FROM_ADDR=192.168.29.146
RECV_FROM_RTP_PORT=5003
RECV_FROM_RTCP_PORT=5004
AUDIORATE=16000

gst-launch-0.10 -v gstrtpbin name=rtpbin latency=200 \
udpsrc caps= »application/x-rtp, media=(string)audio, clock-rate=(int)${AUDIORATE}, encoding-name=(string)SPEEX, encoding-params=(string)1, ssrc=(guint)419764010, payload=(int)110, clock-base=(guint)3478167082, seqnum-base=(guint)57894″ port=${RECV_FROM_RTP_PORT} \
! rtpbin.recv_rtp_sink_1 \
rtpbin. ! rtpspeexdepay ! decodebin ! alsasink \
udpsrc port=${RECV_FROM_RTCP_PORT} ! rtpbin.recv_rtcp_sink_1 \
rtpbin.send_rtcp_src_1 ! udpsink port=${SEND_TO_RTCP_PORT} host=${RECV_FROM_ADDR} sync=false async=false

Attention, il faut lancer le script rtpclient.sh avant le rtpserver.sh . Les variables suivantes sont modifiables dans les scripts:

Script rtpserver.sh:
SEND_TO_ADDR: Adresse IP du client
SEND_TO_RTP_PORT: Numéro de port sur lequel les paquets RTP seront envoyés
SEND_TO_RTCP_PORT: Numéro de port sur lequel les paquets RTCP seront envoyés
RECV_FROM_RTCP_PORT: Numéro de port sur lequel les paquets RTCP seront reçus
SPEEX_PARAMS: Paramètres du plugin d’encodage Speexenc
SPEEX_CAPS: Caps du flux audio (audio rate)

Script rtpclient.sh:
SEND_TO_RTCP_PORT: Numéro de port sur lequel les paquets RTCP seront envoyés
RECV_FROM_ADDR:  Adresse IP du serveur
RECV_FROM_RTP_PORT: Numéro de port sur lequel les paquets RTP seront reçus
RECV_FROM_RTCP_PORT: Numéro de port sur lequel les paquets RTCP seront reçus
AUDIORATE: Audio rate, mettre la même valeur que celle dans le caps du serveur

Résultats des tests

Le premier test a été effectué avec un audio rate de 44000 (bref un taux d’échantillonnage proche de celui d’un CD audio).

Paramètres:
rate=44000 / vad=false / dtx=false
Tests:
En jouant sur l’option quality, on obtient
quality=10 -> bande passante de 80 Kbps
quality=8 -> bande passante de 60 Kbps
quality=6 -> bande passante de 50 Kbps
quality=4 -> bande passante de 40 Kbps
quality=3 -> bande passante de 36 Kbps
quality=2 -> bande passante de 35 Kbps
Conclusion:
On obtient une dégradation de la qualité de réception de la voix en dessous d’une valeur de quality de 4. Il est clairement dit dans la documentation que la qualité > 4 son a réserver pour les sources audio plus complexes que la voix humaine (musique, film…). Par contre la consommation de CPU est plus importante (rapport de 5 contre 1 entre quality=10 et quality=1).
La bande passante est constante (à quelques Kbps) que l’on parle ou que l’on ne parle pas.

Paramètres:
En jouant sur les paramètres vad et dtx, on va essayer d’optimiser la bande passante en gardant la même qualité.
VAD (dixit Wiki): « Quand cette option est activé, le VAD détecte quand l’audio encodé est du dialogue ou du silence/bruit de fond. VAD est toujours implicitement activé en encodage VBR, donc cette option est utile uniquement en mode non VBR. Dans ce cas Speex détecte les périodes sans dialogue et les encode avec le strict minimum de bits pour reproduire le bruit de fond. Cette fonction est appelée Comfort Noise Generation (CNG). »
DTX (dixit Wiki): « la transmission discontinue est une fonctionnalité qui s’ajoute aux
opérations de VAD et de VBR, qui permet de couper la transmission
complètement quand le bruit de fond est stationnaire. Dans un fichier,
5 bits sont utilisés pour chaque frame manquante (correspondant à 250 bits/s) »

Tests:
On ajoute les paramètres vad=true et dtx=true au niveau du serveur (SPEEX_PARAMS)
La bande passante reste la même (40 Kbps) quand on parle, par contre elle passe à 23 Kbps quand on ne parle pas.
Conclusion:
Les algorithmes VAD et DTX fonctionnent très bien. Ils permettent de gagner de la bande passante quand l’activité au niveau sonore est faible (ce qui est le cas dans une conversation ou, normalement, une seule personne parle à un instant t).

En conservant les paramètres du premier test (quality=4, vad=true, dtx=true), on change seulement l’audio rate (au niveau du serveur et du client).

Paramètres:
rate=16000
Tests:
Bande passante de 28 Kbps lorsque l’on parle, 17 Kbps pendant les silences.
Conclusion:
La qualité reste excellente. Sur une conversation (voix humaine), on ne voit pas la différence avec un rate de 44000 (44 KHz).

Paramètres:
rate=8000
Tests:

Bande passante de 23 Kbps lorsque l’on parle, 16 Kbps pendant les silences.

Conclusion:
La qualité est dégradée mais la conversation reste compréhensible. On gagne seulement 5 Kbps par rapport au test précédant.

Pour conclure

D’après les tests effectués, le meilleur compromis bande passante qualité est:

  • audio rate = 16000 (16 Khz)
  • quality = 4
  • vad = true
  • dtx = true

Catégories
Open-source

Chameleo: un framework multimedia open-source

chameleo.png

Une équipe Coréenne est en train de développer un framework multimédia nommée Chameleo. Ce dernier propose au développer un niveau d’abstraction de haut niveau pour développer des applications de type lecteurs vidéo multimédia.

Le principal intérêt de Chameleo est son évolutivité. En effet, il sera facile pour les développeurs d’ajouter des fonctions aux applications créées avec ce framework. Ainsi, il intégre de base les modules GStreamer, GTK+, Cairo (pour la génération des capture d’image) et FreeType/Pango (pour l’intégration du texte dans les vidéo). En ce qui concerne le rendu, Chameleo peut se baser sur DirectX ou OpenGL. Chameleo est écrit en langage Python.


capture widget for chameleo from KyoungJune Eee on Vimeo.

A l’heure actuelle, les formats supportés sont les suivants:

  • Formats des fichiers: AVI, ASF/WMV, MKV, FLV, MPEG-PS/TS
  • Codecs video: DivX-3/4, MPEG-4, DivX-5, XviD, H.264, WMV-1/2, WMV-3/WMV-9, VC-1, MPEG-1/2, Indeo Video v3, Sorenson, Cinepack, H.263, MJPEG
  • Codecs audio: MP3, AC3, Vorbis, WMA-1/2, WMA-3, PCM
  • Sous-titres: SMI, SRT, TEXT

Pour leur développement, l’équipe Coréenne a développée un lecteur video sous Windows que vous pouvez télécharger ici. On peut y ajouter des plugins et changer le skin.

Les sources du framework ainsi que la documentation peuvent être téléchargées sur le Wiki.

On attend les premières applications développées sur ce framework avec impatience