Erweiterung der Weboberfläche

Ich habe mir den Code für den FileBrowser jetzt mal genauer anschaut und muss sagen: Der ist super-duper-optimal implementiert! Schönen Dank an den Autor!
Es wird nur die aktuelle Hierache gescannt und jeweils mit JSON über Websocket transportiert. Gut zu debuggen im Browser und auch relativ schlank. Es können beliebig tiefe Verzeichnisstrukturen transportiert werden.Hier ein Beispiel wie das mit meiner SD-Karte aussieht (ca. 65 Karten/Hörspiele):

Macht 3,5KB an Daten. Ladezeit ca. 1-2 Sek., das liegt aber vermutlich an der SD-Karte (Arduino ListFiles Demo dauert auch etwas länger). Der JSON Dokumentpuffer ist mit 8KB großzügig dimensioniert.
Ich sehe hier absolut kein Problem. @Christian wie viele Dateien hast Du denn im Verzeichnis?

Wo man noch optimieren könnte ist das allokieren des JSON-Objekts. Hier gibt es statische oder dynamische Allokierung. Vielleicht dynamisch?, Warum ist diese Methode im Code auskemmentiert? Es gibt hier Dokumentation auf der Webseite der Bibliothek. Vielleicht mag sich da jemand einlesen? Die verwendete JSON Bibliothek scheint aber für uC Verwendung optimiert zu sein…

Bloß nicht!
Heap-Fragmentierung!

DynamicJsonDocument doc(2048);

This allocation strategy reduces heap fragmentation.

Also ich verstehe das so das die dynamische Allokierung hier genau das verhindert/reduziert.

Beim Wrover kann man den psram nehmen, das wird auch schon gemacht glaube ich. Ansonsten habe ich das als kacke in Erinnerung und extra deswegen ausgebaut.
Trainiere gerade aufm Rad, aber das musste ich doch loswerden :joy:

So lange es hier kein Problem gibt würde ich das auch 1:1 so belassen!

Also, da ich ja nicht so richtig aus dem Quark komme, müsst ihr nicht warten.
Der aktuelle Stand + die Erweiterung von tueddy ist ja funktionsfähig.

Vorschlag.
Ich frickel in meinem Fork weiter und dann müsste man grundsätzlich entscheiden, ob man überhaupt die Änderung in Richtung gzip im Flash und die Websocket-Verbindung übernehmen möchte. Denn dass macht es inkompatibel zum aktuellen Stand. Aufteilung in HTML / JS / CSS. Ich habe den Fehler gemacht, zu viele Features gleichzeitig zu ändern.

  • Wenn ja, schließen wir die Feature Lücke zum jetzigen Stand (Tueddy’s Cover hab ich z.B. schon übernommen)
  • Wenn nein, könnte man (wenn man möchte) Features (Kosmetik) aus meinem Fork „portieren“.

Die Entscheidung, ob man nun ein JSON oder Text-String schickt könnten wir anschließend treffen.

So ist die Idee mal entstanden: Refactoring - #38 von biologist
Und man muss ja auch kein akutes Problem lösen wenn man etwas umstellt :wink:

Exakt. Das wäre auch der Ansatz, wenn man lieber JSON anstatt von „per Trennzeichen“ möchte. Manuell Zusammenbauen. Der Aufwand hält sich in Grenzen.
Aktuell: <Command>#<item>*<Value>
JSON: {"<Command>":{"<Item>":"<Value>"}}

@tueddy findet es unsinnig- ich finde es gut - dafür gibt es Forks :wink:


Man könnte das JSON noch etwas verschlanken:

{"n":"Dateiname","d":1}

Aus „name“ wird „n“, aus „dir“ wird „d“ und aus true wird 1.
Auf ein Element macht es nicht viel aus, aber auf ein größeres Array ist es dann vllt. schon spürbar.

Wie @biologist schon geschrieben hat, sollte das statisch bleiben, sodass es auf dem Stack landet. Zum einen ist es schneller und zum anderen kann es sein, dass irgendwann aufgrund von Heap-Fragmentierung keine 8k mehr am Stück frei sind. Dann funktioniert der Browser nicht mehr. Das gab es in der Vergangenheit schon mal.

Ich habe es sinngemäß so verändert:

f=Dateiname
d=Verzeichnis

@Christian Gefällt mir sehr gut deine GUI-Anpassungen!
Ich denke das manuelle Zusammenbauen von JSON wäre doch ein guter Mittelweg. Dann hat man es einheitlich mit JSON und dennoch keinen Lib-Overhead.

Hehe, ich wusste, dass du dich daran erinnern würdest :smiley:. Ja das Problem brauchen wir nicht nochmal. Die Umstellung auf 8k static war auf jeden Fall gut. Sie war halt nicht perfekt für den Fall, dass zu viele Files übertragen werden. Wobei das nur den Fall betrifft, dass wir keinen PSRAM haben. Ist PSRAM da, dann wird von diesem 64k allokiert:

Wobei ich das nie evaluiert habe, wie performant das im Vergleich ist.

1 „Gefällt mir“

@Christian Wo findet sich Dein Fork, konnte den hier nicht ausfindig machen. Kannst Du einmal hier den Link teilen?

Hallo
@biologist @tueddy

Ich habe mich jetzt einige Stunden mit der neuen Version " herumgequält" . Kann es sein dass es beim Abspielen beim Titelwechsel jetzt erheblich länger dauert als mit dem alten WebUi ? Ich habe im SD_MMC-Mode und SPI-Mode lange Pausen bis zu 2-3 Sekunden und beim Start jedes Files knackt es erheblich , so als würde es dauern bis die Musik „einrastet“. Das hatte ich bisher nicht . In der Version von @tueddy vom 19.11. funktioniert es noch . Ich habe zeitgleich auch meine Ordner mit der alten Tonuino-Struktur von 01-99 umgestellt auf z.Bsp.
/Musik/Queen/Greatest Hits/files.mp3
/Storybooks/PawPatrol/Die Zugrettung/files.mp3
Dadurch sind die Zuweisungen natürlich länger . Kann das schaden .
Meine Files hatten alle unterschiedlich Bitraten und ich habe zu guter letzt alles auf 128kbps umgestellt . Jetzt geht es wieder .

Und ja , mein Enkel ist 5 Jahre alt und mag Queen

VG

@compactflash Wann genau kommen diese Pausen denn? Wenn du einen Titelwechsel via WebGUI forcierst? Oder generell?

Generell , am Anfang und bei jedem Titelsprung , aber massiv und mit lautem knistern . Ich schreib ja „einrasten“ . Ich kann es nicht anders beschreiben, so wie früher beim Suchen einer Radiostation , je näher man kam umso besser wurde es.
Meine Musik hat mindestens 192-320kbps und ich habe es unverändert auf die SD´s kopiert . Ich habe die SD´s nochmals neu formatiert, dann auf 160kbps reduziert immer noch Probleme und mit 128kbps ist es ok .

@compactflash das soll natürlich nicht sein! Ich konnte solche Aussetzer bisher nicht feststellen.
Treten die Pausen auch auf wenn Du ohne Weboberfläche auf den nächsten Titel springst?
Du könntest auch testweise das Abspeichern des Coverbildes auskommentieren um zu schauen ob es daran liegt… In AudioPlayer.cpp die Funktion

void audio_id3image(File& file, const size_t pos, const size_t size)

auskommentieren. Dannn wird kein Cover gespeichert.
Oder Du schaust einmal auf die SD-Karte (mit dem PC). Wie groß ist die Datei „.cover“?

Ich glaube es liegt an einigen zu großen Covern . Ich bearbeite die MP3´s immer mit iTunes und seit meinem neuen Mac mit Musik . Ich suche dann mit Safari die Cover und wenn ich was finde ziehe ich es einfach herein . Habe da bisher immer so > 600x600 genommen . Das scheint mich jetzt zu treffen, mit 600x600 scheint es zu gehen. Ich werde die nächsten Tage mal alle Cover mit max. 600x600 einfügen und mit >128kbps testen . Mal sehen was passiert . Gebe dann Bescheid .

OK, das könnte der Grund sein. Meine Cover sind meist 150*150px.
Schau mal wie die Dateigröße von „/.cover“…

Hallo,

ich habe gerade auch auf die aktuelle Version upgedatet und ebenfalls die Probleme festgestellt.
Bei mir sind die Hörspiele aufgesplittet in mehrere Dateien und Pro Folge ein Ordner. Die Wartezeit zwischen den Tracks lag bei 3-4 Sekunden. Zudem sind die ersten 10 Sekunden immer doppelt abgespielt wurden.
Dank dem Hinweis die Funktion auskommentiert und nun funktioniert es zufriedenstellend.
Bei den problematischen Hörspielen ist das Coverbild 640x640 und ca. 164kb groß.

Gruß Frank

Ei ei, das ist ja gar nicht schön!

Es sind ja zwei Probleme, lange Wartezeit + Aussetzer beim Start der Wiedergabe. Ich könnte mir vorstellen das kopieren des Bildes in „/.cover“ sorgt für die Verzögerung. Und das servieren über den Webserver dannn die Aussetzer. @FrankP kannst Du das einmal eingrenzen? Also Abspeichern des Bildes drinlassen, dafür die Webhandlermethode rausnehmen? Sind dann noch Aussetzer da? Diese Zeile in Web.cpp auskommentieren:

        wServer.on("/cover", HTTP_GET, handleCoverImageRequest);

Ich habe meine ganzen Audiodateien mal durchgeklickt und kann das Problem jetzt auch reproduzieren. Es tritt mit größeren Albumbildern auf. Das ist dann einfach zuviel für den Prozessor!
Komisch das es niemanden bisher aufgefallen war…

Erste Abhilfe: Die Aussetzer bei Audio-Wiedergabe liegen anscheinend bei zuviel CPU-Zeit für den Webserver wenn er das Bild ausliefert, da kommt der Audio-Task ins Stottern. Ich habe jetzt diese Zeile in Web.cpp hinzugefügt:

    AsyncWebServerResponse *response = request->beginResponse(
        mimeType,
        imageSize,
        [coverFile](uint8_t *buffer, size_t maxLen, size_t total) -> size_t {
            File file = coverFile; // local copy of file pointer
            int bytes = file.read(buffer, maxLen);
            // close file at the end
            if (!file.available()) {
                file.close();
                    Log_Println("cover image serving finished, close file", LOGLEVEL_DEBUG);
            }
            vTaskDelay(portTICK_RATE_MS * 50u);  // ++ Diese Zeile einfüggen +++
            return max(0, bytes); // return 0 even when no bytes were loaded
        }
    );

Also einen vTaskDelay(portTICK_RATE_MS * 50u); hinzufügen.

Die Aktualisierung des Album-Covers wird dadurch zwar etwas langsamer aber dafür spielt Audio ohne Unterbrechungen ab. Man könnte jetzt der Wartezeit noch etwas rumspielen (so 10-50 ms?)

Problem 2: Verzögerung durch langsames Kopieren des Bildes aus der MP3 Datei. Hmm, evt. das Kopieren ganz vermeiden, nur Datei, Position und Länge zwischenspeichern und später im Web-Task die Daten direkt aus der MP3 ausliefern?

Würde mich freuen wenn Ihr den Workaround einmal bei Euch testet.

Ich teste das morgen mal. Konnte das Problem hier mitunter auch nachvollziehen, allerdings war es nicht so ausgeprägt. Waren wohl die Bilder klein, so genau konnte ich das, mangels Zeit, leider nicht analysieren. Danke für deine Arbeit, @tueddy!