Raspberry Pi et Subsonic : le mode Jukebox !

Se servir de Subsonic et du Raspebbry Pi pour faire de l’Airplay avec un smartphone, c’est possible.

Pour ma part, à titre d’exemple, mon raspberry pi est planqué dans un meuble, duquel sortent deux enceintes stéréo. Quand je fais une soirée, je sors mon tél, je lance le client subsonic, et je lance la lecture de la musique. Les potes sont subjugués.

En fait, on se sert du mode « Jukebox » incorporé à Subsonic. Ce mode permet de lire la musique directement là ou se trouve le serveur. Bien sûr, vous devez avoir paramétrer un compte subsonic qui autorise l’exécution du mode Jukebox. Nous allons donc nous servir de notre client subsonic pour obliger son daemon tournant sur votre Raspi de lire la musique directement à partir de sa sortie audio. Et, accrochez-vous, car en procédant comme cela, la RAM ne prends rien du tout, puisque qu’après tout on ne fait que lire un son directement depuis un support de stockage interne/externe, rien de gourmand, donc.

Le problème est que, par défaut, ce mode ne fonctionne pas vers un Raspberry Pi, du moins pas avec une (énorme) majorité de personnes. Voici donc la marche à suivre afin d’y parvenir :

D’abord, il nous faut télécharger une version un peu speciale de JAVA8. Cette version supporte le module JavaFX du JDK pour les processeurs ARM. Cette archive se trouve ici !

Une fois téléchargée, allez à son emplacement via un « cd », et procédez de la façon suivante :

Nous allons d’abord créer un dossier d’extraction :

mkdir -p /opt

Dans lequel nous allons dézipper/installer l’archive précédemment téléchargée :

sudo tar zxvf [le nom complet du tar] -C /opt

Ensuite, il nous faut faire comprendre à Raspian que la nouvelle version de Java qu’on vient d’installer est celle à utiliser par défaut :

sudo update-alternatives --install "/usr/bin/java" "java" "/opt/jdk1.8.0/bin/java" 1

sudo update-alternatives –set java /opt/jdk1.8.0/bin/java

Maintenant c’est à Subsonic que nous devons le faire comprendre, en créant/mettant à jour la variable d’environnement JAVA_HOME :

sudo nano /etc/environment

Ajouter/modifier la ligne :

JAVA_HOME="/opt/jdk1.8.0"

Ensuite on met également à jour la console bash :

sudo nano ~/.bashrc

Ajouter tout à la fin :

export JAVA_HOME="/opt/jdk1.8.0"

export PATH=$PATH:$JAVA_HOME/bin

Si ce n’est déjà fait, on installe lame et ffmpeg pour un transcodage optimal :

sudo apt-get install ffmpeg lame

On créé les liens symboliques pour mettre à jour lame et ffmpeg au sein de subsonic :

sudo ln -fs /usr/bin/ffmpeg /var/subsonic/transcode

sudo ln -fs /usr/bin/lame /var/subsonic/transcode

Il nous faut ensuite aller modifier le code source de subsonic pour lui faire reconnaitre directement la carte son du Raspi :

sudo nano /usr/bin/subsonic

Trouvez la ligne « -verbose:gc « , et juste AU-DESSUS, aoutez celle-ci :

-Djavax.sound.sampled.SourceDataLine=#ALSA

La dernière étape consiste à choisir quelle sortie audio du Raspi on souhaite utiliser (Jack3.5/HDMI/Auto) .

Privilégiez le Jack3.5 ou le HDMI, l’Auto a tendance à ne pas marcher.

sudo amixer -c 0 cset numid=3 N

N est à remplacer par (1=Jack/2=HDMI)

Suite à cela, faites un :

sudo service subsonic restart

Voilà, il ne vous reste plus qu’à tester sur votre smartphone via une application client subsonic le mode jukebox lié au serveur présent sur le raspberry pi.

Si cela ne fonctionne pas malgré des heures à repasser toutes les manipulations précédentes, vérifiez-bien que vous avez branché les enceintes au raspi.(=Vécu :] )

Vous aimerez aussi...

  • Salut,

    Merci pour ce tuto, y’a juste une erreur dans tes commandes :

    -Djavax.sound.sampled.SourceDataLine=#ALSA /

    au lieu de :

    -Djavax.sound.sampled.SourceDataLine=#ALSA

    C’est pas parfaitement fluide par contre… peut être à cause de ma bibliothèque conséquente (200go).

    Pour utiliser la mode jukebox depuis un smartphone android : http://sourceforge.net/projects/subsonic/files/android/3.3.beta1/

    (L’application officielle n’implémente pas le mode Jukebox)

    Bonne continuation 😉

  • GregPouet

    Salut !
    Super tuto encore une fois 😉
    A ton avis, est -il possible de faire du streaming video avec subsonic sur le raspberry pi ?

    • Salut,
      Alors je vais faire de la théorie : miniDLNA peut le faire donc Subsonic doit aussi pouvoir le faire. La seule (grosse) contrainte que je vois c’est le transcodage. Pour moi le Raspberry ne peut pas le faire. A priori plusieurs lecteurs arrivent à utiliser le GPU (VLC ou OMXPlayer) mais le streaming semble être une autre histoire.
      Donc si c’est pour envoyer la video telle qu’elle est sans la réencoder je pense que oui.

      • GregPouet

        Ah ben dans ma ptite tete reveuse, ca aurait été pour regarder les videos qui sont restées chez moi qd je serai en tongues sur la plage avec ma tablette ^^ Donc il faudrait réencoder pour que ca puisse passer dans les tuyaux je pense…

        PS: je viens de voir de toute facon que l’option « streaming video » est payante avec subsonic 🙁

        • Le streaming video semble être un sujet casse tete sur le Raspberry

  • josebobby

    salut !

    j’ai suivi ton tuto mais au moment de relancer subsonic j’ai une erreur dans subsonic_sh.log:

    /usr/bin/subsonic: 124: /usr/bin/subsonic: -verbose:gc: not found

    si tu as une idée…
    Merci

    • Regarde le contenu de /usr/bin/subsonic (je crois que c’est un script) à la ligne 124 si elle n’est pas mal formatée suite à la modification demandée par le tuto

  • josebobby

    ${JAVA} -Xmx${SUBSONIC_MAX_MEMORY}m \
    -Dsubsonic.home=${SUBSONIC_HOME} \
    -Dsubsonic.host=${SUBSONIC_HOST} \
    -Dsubsonic.port=${SUBSONIC_PORT} \
    -Dsubsonic.httpsPort=${SUBSONIC_HTTPS_PORT} \
    -Dsubsonic.contextPath=${SUBSONIC_CONTEXT_PATH} \
    -Dsubsonic.defaultMusicFolder=${SUBSONIC_DEFAULT_MUSIC_FOLDER} \
    -Dsubsonic.defaultPodcastFolder=${SUBSONIC_DEFAULT_PODCAST_FOLDER} \
    -Dsubsonic.defaultPlaylistFolder=${SUBSONIC_DEFAULT_PLAYLIST_FOLDER} \
    -Djava.awt.headless=true \
    -Djavax.sound.sampled.SourceDataLine=#ALSA
    -verbose:gc \
    -jar subsonic-booter-jar-with-dependencies.jar > ${LOG} 2>&1 &

    Je pense que c’est bon non?

    • Il manque le \ à la fin de la ligne avec #ALSA. Ne pas oublier l’espace entre le A et le \

  • josebobby

    OK ça marche j’ai corrigé merci

    Maintenant j’ai:
    Error: Unable to access jarfile subsonic-booter-jar-with-dependencies.jar

    • Il faut surement indiquer le chemin complet du JAR ou bien ajouter le répertoire dans le CLASSPATH

  • josebobby

    Qu’est ce que tu appel le CLASSPATH ? A quoi ça correspond dans le fichier subsonic ?

    Merci pour ton aide je verrai la suite demain bonne nuit ++

    • Modifie simplement le nom du fichier JAR en y ajoutant le chemin complet

      • jossebobby

        Bonsoir,

        Est-ce que tu as une idée du chemin à emprunter pour accéder à ce fichier?

        Merci

        • Pas du tout. Essayes la commande :
          find / -name "nom_du_fichier.jar"

          • T’as pas de chance toi ! 🙂
            Il ne trouve pas /usr/bin/subsonic.war ce qui à mon avis est normal car le war ne doit surement pas être là !
            Je vais regarder pour refaire le tuto et le corriger

  • jossebobby

    Salut,

    C’est bon j’ai corriger en indiquant le chemin complet maintenant j’ai ça:

    446 [main] INFO org.springframework.context.support.ClassPathXmlApplicationContext – Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@cbcfc0: display name [org.springframework.context.support.ClassPathXmlAp$
    [GC (Allocation Failure) 2048K->876K(6912K), 0,0357900 secs]
    1482 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader – Loading XML bean definitions from class path resource [applicationContext-deployer.xml]
    [GC (Allocation Failure) 2910K->1329K(6912K), 0,0226650 secs]
    [GC (Allocation Failure) 3377K->1782K(6912K), 0,0820660 secs]
    [GC (Allocation Failure) 3830K->2285K(6912K), 0,0384300 secs]
    [GC (Allocation Failure) 4333K->2914K(6912K), 0,0304050 secs]
    [GC (Allocation Failure) 4962K->3529K(6912K), 0,0287730 secs]
    8362 [main] INFO org.springframework.context.support.ClassPathXmlApplicationContext – Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@cbcfc0]: org.springframework.beans.factory.s$
    8593 [main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory – Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@709393: defining beans [service,org.springfram$
    8967 [main] INFO org.mortbay.log – Logging to org.slf4j.impl.SimpleLogger(org.mortbay.log) via org.mortbay.log.Slf4jLog
    [GC (Allocation Failure) 5577K->4058K(6912K), 0,0303220 secs]
    Error: WAR file not found: /usr/bin/subsonic.war
    Failed to resolve build number from WAR subsonic.war: java.io.FileNotFoundException: subsonic.war/WEB-INF/classes/build_number.txt (Aucun fichier ou dossier de ce type)
    Extracting webapp to /var/subsonic/jetty
    Error: WAR file not found: /usr/bin/subsonic.war
    9581 [main] INFO org.mortbay.log – jetty-6.1.x
    10240 [main] WARN org.mortbay.log – Web application not found subsonic.war
    10243 [main] WARN org.mortbay.log – Failed startup of context org.mortbay.jetty.webapp.WebAppContext@13d7190{/,subsonic.war}
    java.io.FileNotFoundException: subsonic.war
    at org.mortbay.jetty.webapp.WebAppContext.resolveWebApp(WebAppContext.java:943)
    at org.mortbay.jetty.webapp.WebAppContext.getWebInf(WebAppContext.java:780)
    at org.mortbay.jetty.webapp.WebInfConfiguration.configureClassLoader(WebInfConfiguration.java:62)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:444)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
    at org.mortbay.jetty.Server.doStart(Server.java:217)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    at net.sourceforge.subsonic.booter.deployer.SubsonicDeployer.deployWebApp(SubsonicDeployer.java:131)
    at net.sourceforge.subsonic.booter.deployer.SubsonicDeployer.(SubsonicDeployer.java:65)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:414)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:100)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:61)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:877)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:839)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
    at net.sourceforge.subsonic.booter.Main.(Main.java:24)
    at net.sourceforge.subsonic.booter.Main.main(Main.java:63)
    10512 [main] INFO org.mortbay.log – Started SelectChannelConnector@0.0.0.0:4040
    Subsonic running on: http://localhost:4040/
    [GC (Allocation Failure) 6106K->4535K(6912K), 0,0351920 secs]
    11447 [main] INFO org.springframework.remoting.rmi.RmiServiceExporter – Looking for RMI registry at port ‘9412’

  • pedro

    en cherchant des infos je tombe ici donc je laisse ma petite piérre

    pourquoi subsonic ne traiterai pas la vidéo alors qu’il le fait sur dédié ?
    ya une alternative non payante madsonic (mais pour utilisé les 2 sur 2 serveurs dédié madsonic est mieux mais lag pour la vidéo.

    ps : pour regrouper plusieurs serveurs sur un subsonic auquel on pourrait ajjouté des raspberry
    un deezer communautaire :
    http://la-taverne.info/forum/topic-193-sshfs-partage-de-fichiers-securise-serveur-serveur-page-1.html

    • Merci pour le lien ! 🙂

  • pandark

    TUTO NON À JOUR !!

    • OK ! MERCI !
      Serieusement, l’article a plus d’un an et maintenir les 150 posts de ce site c’est pas faisable donc ….

  • KlmRd

    Bonjour, je débute avec Raspberry Pi, je viens d’acheter un Raspberry Pi2 B, le tuto marche-t-il pour ce modèle aussi ? Merci

  • Bonjour,
    Le tuto n’est pas lié au matériel en lui même donc oui il doit fonctionner, si la procédure d’installation de subsonic n’a pas évoluée avec ses dernières mises à jour