< Tech-Blog 

Subsonic Automatischer Mediafolder-Scan eines einzelnen Medienordners

...und es geht doch ! published: 4. November 2018

Subsonic und der Mediafolder-Scan

Das Problem (bzw. die fehlende Funktion):

Subsonic kann automatisiert nur einmal am Tag alle Medienordner auf neue Dateien durchsuchen. Für die meisten Benutzer von Subsonic ist das ausreichend. Wer jedoch häufig neue Dateien einspielt oder eine sehr grosse Mediensammlung (>100000 Files) kommt mit dem Automatik-Scan schnell an die Grenzen der erträglichen Wartezeiten. Bei mir dauert der nächtliche Fullscan 3,5 Stunden. Nachts ...kein Problem, tagsüber .... NO GO!

 

Der Wunsch, das Ziel:

Subsonic sollte neue Dateien automatisch scannen und in die Datenbank aufnehmen. Um die Zeitaufwände gering zu halten sollte der Vorgang automatisch und selektiv durchführen. Das heisst: Werden in einem Medienverzeichnis neue Verzeichnisse und Dateien erstellt soll subsonic nur das betroffene Medienverzeichnis durchsuchen und die neuen Dateien indizieren.

 

Die Idee, der Lösungsansatz:

Mit dem Linuxtool "inotify" und einem zusätzlichen PHP-Script wird das betroffene Medienverzeichnis überwacht und bei Bedarf autmatisch neu eingelesen.

Der Ablauf:

  1. Inotify überwacht alle Dateisystemoperation in den definierten Medienordnern

  2. Bei Änderungen (umbenennen, verschieben, löschen) und neuen Dateien wird von inotify ein PHPscript aufgerufen und mit Paramtern gestartet

  3. Das PHPscript nutzt die API-Schnittstelle von Subsonic und führt folgende Aktionen aus:
    1. Setzt alle Medienordner (bis auf den von Änderungen betroffenen) unter Einstellungen -> Musikordner auf "deaktiviert"
    2. Das PHPscript löst einen Scan aus und überwacht über die API den Scanstatus
    3. Nach dem Scan-Ende setzt das PHPscript wieder alle Medienordner auf "aktiviert"
    4. Das Script verschickt eine "Fertig!"-eMail an den Admin

 

Die Voraussetzungen:

  1. Die verschiedenen Medien (Filme, Musik, Hörspiele, Podcasts, usw.) liegen in eigenen Verzeichnissen.

  2. Die Medienordner liegen in einem Dateisystem das von inotify überwacht werden kann

  3. Eine Möglichkeit PHPscripts auszuführen (am besten ein Linuxsystem)

 

Die Lösung (Verfahrensbeschreibung):

Intofify überwacht die gewünschten Verzeichnisse und startet bei Bedarf das PHPscript.
Das PHPscript greift über CURL auf den Subsonicserver zu und setzt nur das betroffene Verzeichnis auf "aktiviert"
Das Script startet über die subsonic-API den Scan und überwacht danach über die API den ScanStatus (während eines Scans liefert die API den Status "true").
Sobald der Scanstatus auf "false" springt setzt das PHPscript mit einem weiteren CURL-Aufruf wieder alle Medienordner auf "aktiviert"
und verschickt über die PHP-Funktion mail() eine eMail an den Admin.

1. Inotify-Script

#!/bin/sh
while inotifywait -e modify -e create -e delete /pfad/zum/medienverzeichnis; do
    /usr/bin/php /pfad/zum/phpscript.php >/dev/null &
done

Der Aufruf / Start des Inotifyscripts erfolgt über: 

/pfad/zum/inotifyscript.sh >/dev/null &

(das & am Ende der Zeile bewirkt eine dauerhaftes Ausführen des Scripts im Hintergrund)

 

2. PHP-Script
Das PHPscript greift über CURL auf den Subsonicserver zu und setzt den betroffenen Ordner auf "aktiviert". Klingt kompliziert ist aber mit Firefox einfach zu erledigen.

  1. Firefox öffnen und subsonic-Seite öffnen, anmdelden und zu Einstellungen -> Musikordner navigieren. Rechte Maustaste auf den mittleren Frame -> Frame in einem neuen Tab öffnen. Im neuen Fenster / Tab rechte Maustaste -> Element untersuchen -> Netzwerkanalyse, dann den gewünschten Ordner auf "Aktiviert" setzten und alle anderen auf "Deaktiviert" (kein Haken im Kästchen). Im Anschluss "speichern".

  2. In der Netzwerkanalyse findet sich jetzt unter anderem ein "POST"-Aufruf. Rechte Maus auf diesen Eintrag -> kopieren -> als cUrl Adresse kopieren

  3. Starte einen CURL-Converter und wandlen die kopierte URL in PHP um

  4. Kopiere das Ergebnis in dein PHPscript und ergänze folgende Zeile:
    ...
    Suche nach:
    curl_setopt($ch, CURLOPT_POST, 1)
    füge danach ein:
    curl_setopt($ch, CURLOPT_USERPWD, "benutzername" . ":" . "passwort");
    ---

  5. Setzte im Firefox wieder alle Medien-Ordner auf "Aktiviert" und führe Schritt 2.2-2.4 erneut aus.

  6. Im PHPscript fügen wir zwischen den beiden soeben erstellten Abschnitten den Scan-Start und die Statusüberwachung ein:

    ##### start scan
    $startscan = "https://url-des-subsonic-servers:port/rest/startScan?u=benutzername&p=passwort&v=1.12.0&c=mediascanner";
    $start = simplexml_load_file($startscan);

    ##### check status
    $status = "https://url-des-subsonic-servers:port/rest/getScanStatus?u=benutzername&p=passwort&v=1.12.0&c=mediascanner"
    $statuscheck = simplexml_load_file($status);


    danach binden wir einen "Loop" für den Scanstatus ein:

    function scanagain() {
    $url = "https://url-des-subsonic-servers:port/rest/getScanStatus?u=benutzername&p=passwort&v=1.12.0&c=mediascanner";
    $xml = simplexml_load_file($url);
    $array = json_decode(json_encode((array)$xml), TRUE);
    $substatus = $array['@attributes']['status'];
    $scanstatus = $array['scanStatus']['@attributes']['scanning'];
    if (($substatus == 'ok') && ($scanstatus == 'true')) {
        scanagain();
        } else {
    $to      = 'deine@email.de';
    $subject = 'mediascan Verzeichnisname fertig';
    $message = 'mediascan Verzeichnisname fertig';
    $headers = 'From: subsonic-single-folder-mediascan@email.de' . "\r\n" .
        'Reply-To: noreply@mail.de' . "\r\n" .
        'X-Mailer: PHP/' . phpversion();
    mail($to, $subject, $message, $headers);

    ### An diese Stelle kopieren wir das CURL-Script aus 2.5 ein !!!!!

    }
    scanagain();

  7. Abspeichern -> Rechte auf ausführbar setzen -> Testen

Die beiden Scripts im Listing:

  1. inotifyscript.sh

    #!/bin/sh
    while inotifywait -e modify -e create -e delete /pfad/zum/medienverzeichnis;
    do /usr/bin/php /pfad/zum/phpscript.php >/dev/null & done

  2. subsonic-single-folder-scan.php

    <?php

    ### An diese Stelle kopieren wir das CURL-Script aus 2.5 ein !!!!! (Einzelnen Ordner auf "Aktiviert" setzen, alle anderen deaktivieren)

    ##### start scan
    $startscan = "https://url-des-subsonic-servers:port/rest/startScan?u=benutzername&p=passwort&v=1.12.0&c=mediascanner";
    $start = simplexml_load_file($startscan);

    ##### check status
    ##$status = "https://url-des-subsonic-servers:port/rest/getScanStatus?u=benutzername&p=passwort&v=1.12.0&c=mediascanner"
    ##$statuscheck = simplexml_load_file($status);

    function checkstatusagain() {

    $url = "https://url-des-subsonic-servers:port/rest/getScanStatus?u=benutzername&p=passwort&v=1.12.0&c=mediascanner";
    $xml = simplexml_load_file($url);
    $array = json_decode(json_encode((array)$xml), TRUE);
    $substatus = $array['@attributes']['status'];
    $scanstatus = $array['scanStatus']['@attributes']['scanning'];
    if (($substatus == 'ok') && ($scanstatus == 'true')) {
    sleep(10);
        checkstatusagain();
        } else {
    $to      = 'deine@email.de';
    $subject = 'mediascan Verzeichnisname fertig';
    $message = 'mediascan Verzeichnisname fertig';
    $headers = 'From: subsonic-single-folder-mediascan@email.de' . "\r\n" .
        'Reply-To: noreply@mail.de' . "\r\n" .
        'X-Mailer: PHP/' . phpversion();
    mail($to, $subject, $message, $headers);

    ### An diese Stelle kopieren wir das CURL-Script aus 2.5 ein !!!!! (Alle Medienordner aktivieren)

    }
    checkstatusagain();

    ?>

FERTIG.