Manipuler les tags des fichiers Ogg et FLAC

L'assemblage Luminescence.Xiph permet la lecture et l'écriture des tags au format Vorbis Comment dans les fichiers Ogg Vorbis, Ogg FLAC, FLAC natif et Speex. Les sources C# 3 sont sous LGPL.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Je développe depuis 2005 maintenant un éditeur de tag gratuit du nom de MetatOGGerSite officiel de MetatOGGer. Comme son nom l'indique, il a été conçu à la base pour prendre en charge les fichiers Ogg et contribuer ainsi aux efforts de la fondation XiphSite officiel de la fondation Xiph visant à développer un ensemble de briques multimédias gratuites et exempt de brevet (codec, conteneur, etc.). Le support des fichiers MP3 (tags ID3), Musepack, Windows Media, WavPack et Monkey's Audio a été ajouté par la suite. En fait, n'importe quel format peut être ajouté par le biais de plugin.

Fenêtre principale de MetatOGGer


MetatOGGer est développé en C# (l'interface utilise l'API WPF depuis la version 3). Il me fallait donc une librairie .NET pour gérer les tags au format Vorbis Comment des fichiers Ogg. Ne trouvant pas ce qu'il me fallait sur internet, j'ai décidé de développer ma propre librairie.

II. Un peu de théorie

II-A. Le format de tags des fichiers Ogg et FLAC natifs : Vorbis Comment

Les tags des fichiers Ogg (Vorbis, FLAC et Speex), ainsi que des fichiers FLAC natifs sont stockés au format Vorbis Comment. Les spécifications(1) de ce format sont disponibles iciSpécifications du format Vorbis Comment. Chaque tag au format Vorbis Comment est composé d'une paire clef-valeur sous la forme "TAG_NAME=Tag Value". La clef est une chaîne de caractère codée en ASCII (à l'exception du caractère "=", exclu car il sert à délimiter le nom du tag de sa valeur) et insensible à la casse (même si le nom du tag est souvent formaté en majuscule par convention). La valeur du tag est une chaîne de caractère codée en UTF8.

Le format Vorbis Comment définit quinze tags standards :

Nom du tag Description
TITLE Le titre du morceau
VERSION Permet de distinguer plusieurs versions d'un même morceau : remix, live, etc.
ALBUM Le titre de l'album
TRACKNUMBER Le numéro de piste dans un album
ARTIST Le nom de l'artiste ou de l'auteur
PERFORMER Le nom de l'interprète, orchestre, etc.
COPYRIGHT Les informations de copyright
LICENSE La licence applicable au morceau : Creative Commons, tous droits réservés, etc.
ORGANIZATION Organisation ayant produit le morceau comme le nom de la maison de disque
DESCRIPTION Une description ou un commentaire quelconque sur le contenu
GENRE Le genre du morceau : rock, pop, etc.
DATE La date ou l'année d'enregistrement du morceau
LOCATION Le lieu où le morceau a été enregistré
CONTACT Une information de contact de l'auteur ou du distributeur
ISRC Numéro ISRC du morceau


Au-delà de ces tags standards, tout tag arbitraire peut bien évidemment être ajouté. Le risque étant que les lecteurs audio ne sachent comment interpréter ces tags non standards.

Les tags Vorbis Comment peuvent être définis un nombre de fois illimité. Par exemple, il est tout à fait possible de définir plusieurs fois le tag ARTIST : "ARTIST=John Lennon" et "ARTIST=Paul McCartney".

II-B. Le support des tags binaires

Le standard Vorbis Comment ne prévoit pas le stockage de contenu autre que textuel. Ceci est problématique pour le stockage de contenu binaire comme les images.

Le développeur du codec FLAC ayant souhaité ajouter le support des images dans son format, il a prévu la possibilité d'ajouter un "bloc image" comparable à la frame APICSpécifications id3v2.4 du standard ID3v2 du format MP3.

III. L'implémentation du standard Vorbis Comment

Les deux classes principales de la librairie sont les classes OggTagger et FlacTagger. Elles permettent respectivement la lecture des informations dans les fichiers Ogg (.ogg, .oga) et FLAC natifs (.flac, .fla).

III-A. La lecture des tags textuels

Le constructeur des classes OggTagger et FlacTagger prend en paramètre une chaîne de caractère correspondant au chemin du fichier. Les tags du fichier sont alors immédiatement lus.

Il est possible de forcer la lecture des tags d'un autre fichier sans avoir à instancier un nouvel objet en utilisant la méthode ReadMetadata.

Lecture des fichiers Ogg
Sélectionnez

OggTagger ogg = new OggTagger(@"C:\Song.ogg");
ogg.ReadMetadata(@"C:\Song2.ogg");


Les tags sont stockés dans un objet de type SortedList<string, List<string>> pour gérer les tags multiples. Il est possible de récupérer l'intégralité des tags du fichier avec la méthode GetAllTags.

Lecture des tags
Sélectionnez
 
string artist = ogg.Artist; // == tags["ARTIST"][0] || null
ReadOnlyCollection<string> artists = tags["ARTIST"];
ogg.Title = "My Immortal";
ogg.AddTag("LYRICS", "I am singing in the rain...");
ogg.SetTag("LYRICS", "I am not singing in the rain...");
ogg.RemoveTag("LYRICS");


Pour enregistrer les tags dans le fichier, il suffit d'appeler la méthode SaveMetadata.

Enregistrement des tags
Sélectionnez

ogg.SaveMetadata();

III-B. La prise en charge des tags "images"

Les tags "images" ne sont prises en charge que dans les fichiers Ogg FLAC ou FLAC natifs. Les images sont encapsulées dans des objets de type System.Windows.Media.Imaging.BitmapFrame (classe disponible dans l'assemblage PresentationCore.dll de l'API WPF).

Lecture de la pochette du disque
Sélectionnez

OggTagger ogg = new OggTagger(@"C:\SongFLAC.ogg");
Collection<ID3PictureFrame> arts = ogg.FlacArts; 
BitmapFrame cover = null;
foreach (ID3PictureFrame picture in arts)
{
	if (picture.PictureType == ID3PictureType.FrontCover)
		cover = picture.Picture;
}

III-C. Le lecture des informations techniques

La librairie ne se limite pas à l'accès aux tags mais permet de récupérer de nombreuses informations techniques sur les fichiers.

Voici la liste des informations auxquelles la classe OggTagger permet d'accéder :

Propriétés Type de retour Commentaire
Codec OggCodec (énumération) Codec du fichier Ogg : Vorbis, Speex ou FLAC
SpeexBand SpeexBand (énumération) Largeur de bande utilisée pour le fichier Speex : Narrowband (8 000 Hz), WideBand (16 000 Hz) ou UltraWideband (32 000 Hz)
Channels byte Nombre de canaux
MinimumVorbisBitrate int Bitrate minimum du fichier Ogg Vorbis
SampleRate int Taux d'échantillonnage
MaximumVorbisBitrate int Bitrate maximum du fichier Ogg Vorbis
VorbisSpeexNominalBitrate int Bitrate nominal du fichier Ogg Vorbis et Speex
IsVariableBitrate bool Indique si le fichier est encodé en débit variable
VorbisQuality float Niveau de qualité du fichier Ogg Vorbis, de 0 (64 kb/s) à 1 (500 kb/s)
CodecVersion string Version du codec utilisé
Samples long Nombre d'échantillons
Duration float Durée du morceau en secondes
AverageBitrate int Débit moyen calculé
Ratio float Taux de compression du fichier
FlacBitsPerSample byte Taille de l'échantillon du fichier Ogg Flac
UncompressedFileLength long Taille calculé du fichier sans compression


Voici la liste des informations auxquelles la classe FlacTagger permet d'accéder :

Propriétés Type de retour Commentaire
Channels byte Nombre de canaux
SampleRate int Taux d'échantillonnage
CodecVersion string Version du codec utilisé
Samples long Nombre d'échantillons
Duration float Durée du morceau en secondes
AverageBitrate int Débit moyen calculé
Ratio float Taux de compression du fichier
BitsPerSample byte Taille de l'échantillon
UncompressedFileLength long Taille calculée du fichier sans compression

III-D. La gestion du bloc "padding" dans les fichiers FLAC natifs

Les tags Vorbis Comment sont enregistrés au début du fichier ce qui suppose la réécriture complète du fichier en cas de modification. Toutefois, les développeurs du format FLAC ont prévu la possibilité d'insérer un bloc "padding" au début de fichier pour servir de variable d'ajustement pour l'écriture des métadonnées. Ainsi, ce bloc peut être réduit pour laisser plus de place aux tags ou au contraire agrandit pour prendre la place des tags supprimés. Il est alors possible d'éviter la longue reconstruction du fichier, très lente dans le cas du FLAC, un format de compression sans perte dont les fichiers font souvent plusieurs dizaines de mégaoctets par morceaux.

La librairie gère le bloc "padding". Par défaut, ce bloc servira donc autant que faire se peut de variable d'ajustement pour accélérer la sauvegarde des modifications sur les tags. Il est toutefois possible de placer la propriété OptimizeFileSizeWhenSaving à vraie, ce qui aura pour effet de mettre la taille du bloc "padding" à 0 et de récupérer l'espace disque éventuellement laissé vacant par la suppression des tags.

Lorsque que la reconstruction du fichier est nécessaire parce que la taille du bloc "padding" n'est pas suffisante pour enregistrer les tags, ou lorsque la propriété OptimizeFileSizeWhenSaving est vraie, le développeur a la possibilité d'indiquer la taille du bloc "padding" qu'il souhaite voir insérer dans le fichier à l'occasion de sa reconstruction. Pour cela, il convient de définir la propriété DesiredPaddingSize (la valeur par défaut est fixée à 4 Ko).

III-E. Diagrammes des classes OggTagger et FlacTagger

Diagrammes des classes OggTagger et FlacTagger

IV. Exemple d'utilisation de la librairie

Le code source de la librairie est livré avec un projet WPF montrant comment utiliser la classe FlacTagger dans le cadre d'une application cliente.

Application de tests

Après avoir choisi un fichier FLAC en cliquant sur l'unique bouton, un objet FlacTagger est instancié et passé à la propriété DataContext de ma fenêtre WPF.

Ouverture du fihcier FLAC
Sélectionnez

OpenFileDialog open = new OpenFileDialog();
open.Filter = "Fichiers FLAC (*.flac)|*.flac";
if (!open.ShowDialog().Value) return;

FlacTagger flac = new FlacTagger(open.FileName);
DataContext = flac;


Il suffit ensuite d'utiliser les capacités avancées de Data Binding de WPF pour récupérer les valeurs des tags côté interface.

Binding des informations de tags
Sélectionnez

<TextBlock Text="{Binding Artist}" />
<TextBlock Text="{Binding Title}" Grid.Row="1" />
<TextBlock Text="{Binding Album}" Grid.Row="2" />
<TextBlock Text="{Binding TrackNumber}" Grid.Row="3" />
<TextBlock Text="{Binding Genre}" Grid.Row="4" />
<TextBlock Text="{Binding Date}" Grid.Row="5" />
<Image Source="{Binding Arts[0].Picture}" 
       MaxWidth="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Source.PixelWidth}" 
       MaxHeight="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Source.PixelHeight}" 
       Stretch="Uniform" Grid.Row="6" Grid.Column="1" />


Voici le code XAML pour "binder" les informations techniques du fichier FLAC. Remarquez l'utilisation de la propriété StringFormat de la classe Binding (disponible dans le Framework .NET 3.5 SP1) pour formater la chaîne.

Binding des informations techniques
Sélectionnez

<TextBlock Text="{Binding Channels}" />
<TextBlock Text="{Binding SampleRate, StringFormat={}{0:N0} Hertz}" Grid.Row="1" />
<TextBlock Text="{Binding CodecVersion, StringFormat={}FLAC {0}}" Grid.Row="2" />
<TextBlock Text="{Binding Duration, StringFormat={}{0:N0} secondes}" Grid.Row="3" />
<TextBlock Text="{Binding AverageBitrate, StringFormat={}{0:N0} bits par seconde}" Grid.Row="4" />
<TextBlock Text="{Binding Ratio, StringFormat={}{0:P}}" Grid.Row="5" />
<TextBlock Text="{Binding BitsPerSample, StringFormat={}{0} bits}" Grid.Row="6" />

V. Téléchargements et liens

VI. Conclusions

La librairie Luminescence.Xiph permet d'accéder facilement aux tags des fichiers Ogg et FLAC natifs. Le code est entièrement documenté et livré avec une batterie de tests unitaires. Les sources sont sous LGPL, ce qui permet à l'assemblage d'être utilisé dans des applications propriétaires.

VII. Remerciements

Je remercie l'équipe .NET pour leurs relectures de ce document.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2009 Sylvain Rougeaux. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.