Tag Archives: Mediatomb

Scripts d’import en Javascript pour Mediatomb

mediatomb-scripts

Après avoir activer le support du javascript dans Mediatomb, il est intéressant de scripter les fichiers common.js et import.js afin d’avoir une hiérarchisation de vos médias qui vous conviendra.

Je n’utilise Mediatomb que pour mes films et mes séries. Ceux-ci sont disponibles dans /zfilms et /zseries.

Les films sont organisés dans des répertoires par genres et les séries sont organisées par saisons.

Évidemment mes scripts ne sont données qu’à titre d’exemple et devront être adaptés à votre organisation. Ils permettent une visualisation par genre et par classement alphabétique.

Voici mon fichier Common.js

//Fonction qui supprime le underscore devant un nom
function StripFirst(name, c)
{
	if (c == undefined) { c = "_"; }
	ret = name;
	if ((name != undefined) && (name != ""))
	{
		if (name.substring(0,c.length) == c)
		{
			ret = name.substring(c.length);
		}
	}
	return ret;
}
 
function CreateSerieArray(chain, location)
{
	for (i = 2; i < location.length -1; i++)
	{
		chain.push(StripFirst(location[i]));
	}
	return chain;
}
 
function escapeSlash(name)
{
    name = name.replace(/\\/g, "\\\\");
    name = name.replace(/\//g, "\\/");
    return name;
}
 
function createContainerChain(arr)
{
    var path = '';
    for (var i = 0; i < arr.length; i++)
    {
        path = path + '/' + escapeSlash(arr[i]);
    }
    return path;
}
 
function getYear(date)
{
    var matches = date.match(/^([0-9]{4})-/);
    if (matches)
        return matches[1];
    else
        return date;
}
 
function getPlaylistType(mimetype)
{
    if (mimetype == 'audio/x-mpegurl')
        return 'm3u';
    if (mimetype == 'audio/x-scpls')
        return 'pls';
    return '';
}
 
function getLastPath(location)
{
    var path = location.split('/');
    if ((path.length > 1) && (path[path.length - 2]))
        return path[path.length - 2];
    else
        return '';
}
function getSeriePath(location)
{
    var path = location.split('/');
    if (path.length > 2)
        return path[2];
    else
        return '';
}
 
function getRootPath(rootpath, location)
{
    var path = new Array();
 
    if (rootpath.length != '')
    {
        rootpath = rootpath.substring(0, rootpath.lastIndexOf('/'));
 
        var dir = location.substring(rootpath.length,location.lastIndexOf('/'));
 
        if (dir.charAt(0) == '/')
            dir = dir.substring(1);
 
        path = dir.split('/');
    }
    else
    {
        dir = getLastPath(location);
        if (dir != '')
        {
            dir = escapeSlash(dir);
            path.push(dir);
        }
    }
 
    return path;
}
 
function abcbox(stringtobox, boxtype, divchar)
{
	// get ascii value of first character 
	var intchar = stringtobox.toUpperCase().charCodeAt(0);
 
	// check for numbers
	if ( (intchar >= 48) && (intchar <= 57) )
	{
		return divchar + '0-9' + divchar;
	}
	// check for other characters
	if ( !((intchar >= 65) && (intchar <= 90)) )
	{
		return divchar + '^\&#\'' + divchar;
	}
	// all other characters are letters
 
	// definition of box types, adjust to your own needs
	// as a start: the number is the same as the number of boxes, evenly spaced ... more or less.
	switch (boxtype)
	{
	case 1:
		var boxwidth = new Array();
		boxwidth[0] = 26;                             // one large box of 26 letters
		break;
	case 2:
		var boxwidth = new Array(13,13);              // two boxes of 13 letters
		break;
	case 3:
		var boxwidth = new Array(8,9,9);              // and so on ...
		break;
	case 4:
		var boxwidth = new Array(7,6,7,6);
		break;
	case 5:
		var boxwidth = new Array(5,5,5,6,5);
		break;
	case 6:
		var boxwidth = new Array(4,5,4,4,5,4);
		break;
	case 7:
		var boxwidth = new Array(4,3,4,4,4,3,4);
		break;
	case 9:
		var boxwidth = new Array(5,5,5,4,1,6);        // When T is a large box...
		break;
	default:
		var boxwidth = new Array(5,5,5,6,5);
		break;
	}
 
	// check for a total of 26 characters for all boxes
	charttl = 0;
	for (cb=0;cb<boxwidth.length;cb++) { charttl = charttl + boxwidth[cb]; }
	if (charttl != 26) {
		print("Error in box-definition, length is " + charttl + ". Check the file common.js" );
		// maybe an exit call here to stop processing the media ??
		end;
	}
 
	// declaration of some variables
	boxnum=0;                         // boxnumber start
	sc=65;                            // first ascii character (corresponds to 'A')
	ec=sc + boxwidth[boxnum] - 1;     // last character of first box
 
	// loop that will define first and last character of the right box
	while (intchar>ec)
	{
		boxnum++;                         // next boxnumber
		sc = ec + 1;                      // next startchar
		ec = sc + boxwidth[boxnum] - 1;   // next endchar
	}
 
	// construction of output string
	output = divchar;
	for (i=sc;i<=ec;i++) {
		output = output + String.fromCharCode(i);
	}
	output = output + divchar;
	return output;
}

 

Et voilà mon fichier import.js:

function addVideo(obj)
{
	const _GENRE_ACTION_POLICIER = "__ACTION_POLICIER"
	const _GENRE_ANIMATION = "__ANIMATION"
	const _GENRE_COMBAT = "__COMBAT"
	const _GENRE_AVENTURE_SF = "__AVENTURE_SF"
	const _GENRE_GUERRE_PEPLUM_WESTERN = "__GUERRE_PEPLUM_WESTERN"
	const _GENRE_COMEDIE = "__COMEDIE"
	const _GENRE_ROMANCE_DRAME = "__ROMANCE_DRAME"
	const _GENRE_HORREUR = "__HORREUR"
	const _GENRE_MUSICAL = "__MUSICAL"
 
	var genres = new Array(_GENRE_ACTION_POLICIER, _GENRE_ANIMATION, _GENRE_COMBAT, _GENRE_AVENTURE_SF, _GENRE_GUERRE_PEPLUM_WESTERN, _GENRE_COMEDIE, _GENRE_ROMANCE_DRAME, _GENRE_HORREUR, _GENRE_MUSICAL);
	var location = obj.location.split('/');
 
	var chain = new Array();
 
	if (location[1].toLowerCase() == "zfilms")
	{
		var title = StripFirst(getLastPath(obj.location));
 
		/*****************
		* ALPHABETIQUE
		*****************/
		//Ajout dans la section ALL
		chain = new Array('-MOVIES-', '-ALL-', title);
		addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
 
		//Ajout dans la bonne lettre
		chain = new Array('-MOVIES-', '-ALPHABETICAL-', abcbox(title, 6, '-'), title);
		addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
 
		/*****************
		* GENRE
		*****************/
		var locationU = obj.location.toUpperCase();
		for (i=0; i < genres.length;i++)
		{
			if (locationU.indexOf(genres[i], 0) != -1)
			{
				var g = StripFirst(genres[i] ,"__");
				chain = new Array('-MOVIES-', '-GENRES-', g, title);
				addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
			}
		}
 
		/*****************
		* TRILOGIE
		*****************/
	}
	else if (location[1].toLowerCase() == "zseries")
	{
		var title = getSeriePath(obj.location);
		var titleclean = StripFirst(getSeriePath(obj.location));
		/*****************
		* ALPHABETIQUE
		*****************/
		//Ajout dans la section ALL
		chain = new Array('-SERIES-', '-ALL-');
		chain = CreateSerieArray(chain, location);
		addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
 
		//Ajout dans la bonne lettre
		chain = new Array('-SERIES-', '-ALPHABETICAL-', abcbox(titleclean, 6, '-'));
		chain = CreateSerieArray(chain, location);
		addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
 
		/*****************
		* COMPLET
		*****************/
		if (title.substring(0, 1) == "_")
		{
			chain = new Array('-SERIES-', '-COMPLET-');
			chain = CreateSerieArray(chain, location);
			addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
		}
 
		/*****************
		* INCOMPLET
		*****************/
		else
		{
			chain = new Array('-SERIES-', '-INCOMPLET-');
			chain = CreateSerieArray(chain, location);
			addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);		
		}
	}	
}
 
function addAudio(obj)
{
 
    var desc = '';
    var artist_full;
    var album_full;
 
    // first gather data
    var title = obj.meta[M_TITLE];
    if (!title) title = obj.title;
 
    var artist = obj.meta[M_ARTIST];
    if (!artist) 
    {
        artist = 'Unknown';
        artist_full = null;
    }
    else
    {
        artist_full = artist;
        desc = artist;
    }
 
    var album = obj.meta[M_ALBUM];
    if (!album) 
    {
        album = 'Unknown';
        album_full = null;
    }
    else
    {
        desc = desc + ', ' + album;
        album_full = album;
    }
 
    if (desc)
        desc = desc + ', ';
 
    desc = desc + title;
 
    var date = obj.meta[M_DATE];
    if (!date)
    {
        date = 'Unknown';
    }
    else
    {
        date = getYear(date);
        desc = desc + ', ' + date;
    }
 
    var genre = obj.meta[M_GENRE];
    if (!genre)
    {
        genre = 'Unknown';
    }
    else
    {
        desc = desc + ', ' + genre;
    }
 
    var description = obj.meta[M_DESCRIPTION];
    if (!description) 
    {
        obj.meta[M_DESCRIPTION] = desc;
    }
 
// uncomment this if you want to have track numbers in front of the title
// in album view
 
/*    
    var track = obj.meta[M_TRACKNUMBER];
    if (!track)
        track = '';
    else
    {
        if (track.length == 1)
        {
            track = '0' + track;
        }
        track = track + ' ';
    }
*/
    // comment the following line out if you uncomment the stuff above  :)
    var track = '';
 
    var chain = new Array('-MUSICS-', 'All Audio');
    obj.title = title;
    addCdsObject(obj, createContainerChain(chain));
 
    chain = new Array('-MUSICS-', 'Artists', artist, 'All Songs');
    addCdsObject(obj, createContainerChain(chain));
 
    chain = new Array('-MUSICS-', 'All - full name');
    var temp = '';
    if (artist_full)
        temp = artist_full;
 
    if (album_full)
        temp = temp + ' - ' + album_full + ' - ';
    else
        temp = temp + ' - ';
 
    obj.title = temp + title;
    addCdsObject(obj, createContainerChain(chain));
 
    chain = new Array('-MUSICS-', 'Artists', artist, 'All - full name');
    addCdsObject(obj, createContainerChain(chain));
 
    chain = new Array('-MUSICS-', 'Artists', artist, album);
    obj.title = track + title;
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_ALBUM);
 
    chain = new Array('-MUSICS-', 'Albums', album);
    obj.title = track + title; 
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_ALBUM);
 
    chain = new Array('-MUSICS-', 'Genres', genre);
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER_MUSIC_GENRE);
 
    chain = new Array('-MUSICS-', 'Year', date);
    addCdsObject(obj, createContainerChain(chain));
}
 
function addWeborama(obj)
{
    var req_name = obj.aux[WEBORAMA_AUXDATA_REQUEST_NAME];
    if (req_name)
    {
        var chain = new Array('-Online Services-', '-Weborama-', req_name);
        addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_PLAYLIST_CONTAINER);
    }
}
 
function addImage(obj)
{
    var chain = new Array('-Photos-', '-All Photos-');
    addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
 
    var date = obj.meta[M_DATE];
    if (date)
    {
        var dateParts = date.split('-');
        if (dateParts.length > 1)
        {
            var year = dateParts[0];
            var month = dateParts[1];
 
            chain = new Array('-Photos-', '-Year-', year, month);
            addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
        }
 
        chain = new Array('-Photos-', '-Date-', date);
        addCdsObject(obj, createContainerChain(chain), UPNP_CLASS_CONTAINER);
    }
 
    var dir = getRootPath(object_root_path, obj.location);
 
    if (dir.length > 0)
    {
        chain = new Array('-Photos-', '-Directories-');
        chain = chain.concat(dir);
 
        addCdsObject(obj, createContainerChain(chain));
    }
}
 
function addYouTube(obj)
{
    var chain;
 
    var temp = parseInt(obj.aux[YOUTUBE_AUXDATA_AVG_RATING], 10);
    if (temp != Number.NaN)
    {
        temp = Math.round(temp);
        if (temp > 3)
        {
            chain = new Array('-Online Services-', '-YouTube-', '-Rating-', 
                                  temp.toString());
            addCdsObject(obj, createContainerChain(chain));
        }
    }
 
    temp = obj.aux[YOUTUBE_AUXDATA_REQUEST];
    if (temp)
    {
        var subName = (obj.aux[YOUTUBE_AUXDATA_SUBREQUEST_NAME]);
        var feedName = (obj.aux[YOUTUBE_AUXDATA_FEED]);
        var region = (obj.aux[YOUTUBE_AUXDATA_REGION]);
 
        chain = new Array('-Online Services-', '-YouTube-', temp);
 
        if (subName)
            chain.push(subName);
 
        if (feedName)
            chain.push(feedName);
 
        if (region)
            chain.push(region);
 
        addCdsObject(obj, createContainerChain(chain));
    }
}
 
function addTrailer(obj)
{
    var chain;
 
    chain = new Array('-Online Services-', '-Apple Trailers-', '-All Trailers-');
    addCdsObject(obj, createContainerChain(chain));
 
    var genre = obj.meta[M_GENRE];
    if (genre)
    {
        genres = genre.split(', ');
        for (var i = 0; i < genres.length; i++)
        {
            chain = new Array('-Online Services-', '-Apple Trailers-', '-Genres-',
                              genres[i]);
            addCdsObject(obj, createContainerChain(chain));
        }
    }
 
    var reldate = obj.meta[M_DATE];
    if ((reldate) && (reldate.length >= 7))
    {
        chain = new Array('-Online Services-', '-Apple Trailers-', '-Release Date-',
                          reldate.slice(0, 7));
        addCdsObject(obj, createContainerChain(chain));
    }
 
    var postdate = obj.aux[APPLE_TRAILERS_AUXDATA_POST_DATE];
    if ((postdate) && (postdate.length >= 7))
    {
        chain = new Array('-Online Services-', '-Apple Trailers-', '-Post Date-',
                          postdate.slice(0, 7));
        addCdsObject(obj, createContainerChain(chain));
    }
}
 
// main script part
 
if (getPlaylistType(orig.mimetype) == '')
{
    var arr = orig.mimetype.split('/');
    var mime = arr[0];
 
    // var obj = copyObject(orig);
 
    var obj = orig; 
    obj.refID = orig.id;
 
    if (mime == 'audio')
    {
        if (obj.onlineservice == ONLINE_SERVICE_WEBORAMA)
            addWeborama(obj);
        else
            addAudio(obj);
    }
 
    if (mime == 'video')
    {
        if (obj.onlineservice == ONLINE_SERVICE_YOUTUBE)
            addYouTube(obj);
        else if (obj.onlineservice == ONLINE_SERVICE_APPLE_TRAILERS)
            addTrailer(obj);
        else
            addVideo(obj);
    }
 
    if (mime == 'image')
    {
        addImage(obj);
    }
 
    if (orig.mimetype == 'application/ogg')
    {
        if (orig.theora == 1)
            addVideo(obj);
        else
            addAudio(obj);
    }
}

Mediatomb sur Ubuntu avec support du javascript

mediatomb-javascript

Après avoir essayé plusieurs serveurs DLNA, j’ai finalement porté mon choix sur Mediatomb car il permet d’organiser ses fichiers grâce à des scripts javascript.

Malheureusement la version de Mediatomb disponible dans les dépôts Ubuntu n’a pas été compilée avec le javascript activé.

Voici donc la manipulation à suivre pour recompiler une version de Mediatomb avec le support du Javascript.

Tout d’abord, il faut supprimer les librairies libmoz185 présentes par défaut dans Ubuntu puis installer des librairies nécessaires à la compilation:

sudo apt-get remove libmozjs185*
sudo apt-get install build-essential libnspr4-0d

Ensuite téléchargez les librairies libmozjs2d et  libmozjs-dev initialement développées pour Debian Squeeze. Pensez à prendre les versions correspondant à votre architecture et celle pour Debian Squeeze (c’est important).

Une fois téléchargées, vous pouvez les installer:

sudo dpkg -i libmoz*.deb

Récupérez ensuite les sources de Mediatomb:

sudo apt-get build-dep mediatomb
sudo apt-get source mediatomb

Puis éditez le fichier “debian/rules” pour activer le javascript:

sudo nano <mediatombfolder>/debian/rules

Recherchez –disable-libjs et remplacez le par –enable-libjs.

Vous pouvez également changer le numéro de version dans <mediatombfolder>/debian/changelog et dans le fichier “mediatomb.dsc” afin d’éviter les écrasements suite à des mises à jour.

Il ne vous reste plus qu’à lancer la configuration de Mediatomb:

cd <mediatombfolder>
sudo ./configure

Si tout c’est bien déroulé, vous devriez voir “libjs : yeslibjs : yes”.

Désormais vous pouvez lancer la compilation grâce à la commande:

sudo fakeroot debian/rules binary

Une fois la compilation terminée (cela peut prendre plusieurs minutes),  vous devriez avoir 3 fichiers .deb dans le répertoire parent.

Il ne reste plus qu’à les installer:

sudo apt-get install libjs-prototype
sudo dpkg -i mediatomb*.deb

Voilà, votre serveur Mediatomb est installé et il supporte le javascript :-)

Lister les bases de données MySQL sous Linux

mysql

Aujourd'hui mon serveur MediaTomb a eu un problème, il n'arrivait pas à se connecter à sa base de données. J'ai donc voulu comprendre pourquoi.

Pour celà, j'ai dû lister les bases de données présentes sur mon serveur MySQL.

Tout d'abord, il faut s'authentifier avec des droits suffisants pour lister les bases de données. Personnellement je m'identie toujours en tant que "root":

mysql -u root -p

Une fois identifié, il vous suffit d'utiliser la commande "show databases" dans le terminal:

mysql> show databases;

Cela vous retournera alors quelque chose comme çà:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mediatomb          |
| mysql              |
| zbase              |
| zbasebackup        |
+--------------------+
5 rows in set (0.02 sec)

Ma base mediatomb est bien présente. Après plusieurs minutes de recherche, je me suis aperçu qu'un processus s'était arrêté inopinément. Je l'ai relancé et c'est reparti :)

Choisir son serveur DLNA

dlna

Depuis quelques années, le multimédia est omniprésent dans notre environnement: baladeurs numériques, tablettes, smartphones, …

Afin de faciliter la communication entre les différents périphériques pouvant diffuser ou émettre des contenus multimédia, une norme a été mise en place: DLNA.

Qu'est ce que le DLNA?

DLNA, Digital Living Network Alliance est une norme facilitant l'accès aux contenus multimédia, entre différents périphériques, connectés au sein d'un même réseau informatique.

Rapidement adopté par plus de 250 sociétés leaders dans le monde numérique (Sony, Philips, Samsung, LG, etc…), DLNA est devenu le standard pour la diffusion de contenu multimédia entre plusieurs périphériques.

Le DLNA indique comment un périphérique de type Digital Media Server (DMS) partage les fichiers multimédia qu'il contient avec les périphériques Digital Media Player (DMP) au travers de votre réseau.

Par exemple, votre téléviseur (DMP) pourra directement diffuser les photos qui sont sur votre disque dur réseau (DMS). Autre exemple, votre Freebox Player (DMP) pourra lire un film se trouvant sur votre ordinateur (DMS).

DLNA est donc une norme visant à faciliter la communication entre vos différents périphériques multimédia.

Les différents type de serveurs DLNA

Tous les serveurs DLNA que l'on trouve sur Internet fonctionnent plus ou moins de la même manière puisqu'ils se basent tous sur la même norme.

Toutefois, certains se distinguent par des caractéristiques spécifiques tels que le transcodage de la vidéo ou bien le transcodage de l'audio.

Chaque serveur a des avantages et des inconvénients qui lui sont propre. Il n'y aura donc pas de réponse à la question "Quel est le meilleur serveur DLNA?".

L'utilisation que vous ferez de votre réseau multimédia mais aussi les divers périphériques qui composent votre réseau vous guideront dans le choix de votre serveur de diffusion.

Quand installer un serveur DLNA?

Personnellement j'ai eu le besoin d'installer un serveur DLNA lorsque j'ai reçu ma Freebox Révolution. En effet, mon serveur est dans une pièce à l'étage et mon Freebox Player et ma TV au rez de chaussée.

Il est vite devenu lassant de devoir utiliser des périphériques amovibles afin de pouvoir visionner mes films et autres photos sur ma TV.

La freebox supportant la norme DLNA, il m'a semblé être intéressant de partir sur cette solution.

Comparaison des serveurs DLNA

Le choix de votre serveur DLNA va être orienté par plusieurs points:

  • votre système d'exploitation (Windows, Linux ou Mac)
  • la nature de votre réseau et les types de périphériques DMP qui composent votre réseau informatique (tv, ordinateurs, freebox, ps3, xbox, …)
  • les fonctionnalités que vous souhaitez mettre en place (transcodage vidéo, audio, compression, …)

Pour information, le transcodage permet de convertir un format dans un autre format. Par exemple, vous souhaitez lire un fichier MKV sur votre PS3 qui ne gère pas ce format. Votre serveur DLNA va alors convertir le fichier MKV en XVID afin de le rendre lisible par votre PS3.

Le tableau ci-dessous (que j'ai trouvé sur le blog de Robert Green) récapitule bien les différentes solutions disponibles sur le marché.

La colonne "Serveur" correspond au nom du serveur DLNA. La colonne "Prix" correspond au tarif de vente du logiciel (certains sont gratuits et sont tous aussi performants que les payants). Les colonnes "Windows", "Mac" et "Linux"  permettent de savoir sur quel système d'exploitation le serveur DLNA peut être installé. La colonne "Musique" indique si le serveur gère les flux Audio. La colonne "Photo" indique si le serveur gère les photos et autres images. La colonne "Vidéo" indique si le serveur DLNA gère les flux vidéo. Enfin la colonne "Transcoding" indique si le serveur est capable de convertir un format dans un autre format.

Serveur Prix Windows Mac Linux Music Photo Video Transcoding
Allegro Media
Server
39.95 X X
X


Cidero Internet Radio Station
Server (Java)
Gratuit X X X X X X
Cyber Media Gate (Java) Gratuit X X X X X X
Cyberlink Digital Home Enabler Kit 79.95 X

X X X
Elgato Eyeconnect 49.95
X
X X X
Fuppes Gratuit X
X X X X X
Geexbox Gratuit


X X X
GMediaServer Gratuit

X X X X
JRiver Media Center
39.95 X

  X X X
MediaTomb Gratuit
X X X X X X
Mezzmo 24.95 X

X X X X
MiniDLNA Gratuit

X X X X ?
MythTV Gratuit

X X X X X
Nero
MediaHome
79.99 X

X X X X
Nullriver Medialink 20.00
X
X X X X
On2Share 19.95 X

X X X
PS3 Media Server Gratuit X
X X
X X X X
Rhapsody 12.99/mois X X X X


SimpleCenter Premium 19.99 X

X X X X
Tversity Gratuit X

X X X X
TwonkyMedia 39.95 X X X X X X X
uShare Gratuit

X X X X
Wild Media Server $15 X X X X X X X
Winamp Remote Gratuit X

X ? X ?
Windows Media Connect Gratuit X

X X X X
Yahoo Music Jukebox Gratuit X

X


Ce tableau comparatif date de 2008 mais vous donne une bonne idée des solutions disponible.

Mes serveurs DLNA préférés

Avant de me décider sur un serveur DLNA, j'en ai testé une dizaine pour Windows et une dizaine pour Linux.

Sous Windows, le serveur DLNA le plus complet, simple d'utilisation et agréable à utiliser est Wild Media Server. Un petit temps d'adaptation est nécessaire pour prendre le logiciel mais il propose des fonctionnalités de transcoding très complètes, la possibilité d'organiser vos médias par critères (par exemple vos vidéos pourront être organisées par genre, type, année, …) et il propose des parsers (recherche automatique d'informations) pour iMDB, Allocine et j'en passe.

Sous Linux, le serveur DLNA qui m'a le plus séduit est MediaTomb car il propose une interface web afin de gérer votre bibliothèque multimédia. L'interface reste très sommaire mais le logiciel est parfait sur une installation serveur. De plus, il propose de scanner vos dossiers de manière automatique à interval régulier (que vous définissez).

Enfin, je pense qu'il est nécessaire de parler de PS3 Media Server (PMS) car il est gratuit, disponible sous Windows et Linux et offre des fonctionnalités de transcodage qui vous permettra de lire presque tous les formats sur votre PS3 (n'ayant pas de PS3 et la Freebox ne nécessitant pas de transcodage car elle supporte tous les formats je n'en ai pas eu l'utilité :). Facile d'installation et d'utilisation, PMS sera probablement un des serveurs les plus polyvalents et il répondra sûrement à vos besoins.