Die Architektur eines Musik-Players mit Wiedergabelisten unter Verwendung von Rails, Redis und HTML5

9

Ich entwickle eine App mit mehreren Musikwiedergabelisten, einer Ansicht für jede Playlist und einem Player.

Ich verwende bereits die HTML5-Verlaufs-API in meinem System (für andere Funktionen) und verwende sie weiter, um dies zu verhindern Die Seite lädt zwischen den Anfragen und damit die Musik auf jeder Seite.

Ich bin fest davon überzeugt, dass es am besten ist, die Tracks zu verwalten, die der Player zwischen den Views spielt. Wie zu erwarten, klickt ein Benutzer derzeit auf einen Link und erhält eine Liste mit Titeln. Die Tracks werden in den Player geladen und nacheinander abgespielt, einfach. Mit der fortwährend spielenden Musik muss ich jedoch sicherstellen, dass die richtige Playlist der Titel trotz des sich ändernden Inhalts auf der Seite in der richtigen Reihenfolge abgespielt wird und es sich nun um eine dynamische URL handelt.

Wenn der Benutzer jedoch zu einer anderen Seite navigiert, die Wiedergabe auf einem Titel in der neuen Wiedergabeliste drückt, muss ich in der Lage sein, diesen Eintrag in den Player zu laden und den Rest der Wiedergabeliste effektiv zu laden, während der Benutzer fortfährt navigieren.

Ich verwende Redis, um eine Liste der Track-IDs für eine Playlist zu speichern, um die Verzögerung zwischen den Tracks zu reduzieren. Als Ergebnis habe ich für jede Wiedergabeliste ein anderes Redis-Set. Ich habe auch meine Next und Previous Track API Aufrufe basierend auf dem aktuellen Track erstellt, so dass der nächste Track aus dem Redis Set in den Player geladen werden kann.

Wie bereits erwähnt, kann ich mich nicht entscheiden, welche Playlist gerade abgespielt wird, damit der Player weiß, von welchem ​​Redis aus er die Tracks aufrufen soll. Mein Denken hat mir ein paar verschiedene Ideen hinterlassen:

a) Benutzerdefinierte HTML5-Datenattribute - Ich könnte die aktuell wiedergegebene Playlist als Datenattribut auf dem Player festlegen und sie dann aktualisieren. Ich könnte dann auf dieses Attribut verweisen, wenn ich entscheide, von welchem ​​Redis ich den nächsten Track laden soll.

Alternativ könnte ich die aktuelle Wiedergabeliste und alle Spuren (und ihre Attribute) als JSON-Objekte in Datenattribute auf der Seite ablegen. Playlists könnten Tausende von Tracks lang sein, also lehne ich diese ab, weil der Quellcode schrecklich aussehen würde, geschweige denn die damit verbundenen Leistungsprobleme. Habe ich recht?

b) LocalStorage - Die Browserunterstützung ist begrenzt. Je mehr Unterstützung für diese Lösung, desto besser in diesem speziellen Fall. Trotzdem konnte ich die aktuelle Wiedergabeliste im Benutzerbrowser speichern. Dies hat mich dazu gebracht, mich zu fragen, ob es auch praktisch wäre, die JSON-Objekte der Tracks in LocalStorage zu speichern, um die zusätzlichen DB-Aufrufe zu verhindern.

c) In Session - Ich könnte die Sitzung aktualisieren, um eine Variable für die gerade abgespielte Playlist zu speichern.

d) Redis - Ich könnte meine Verwendung von Redis erweitern, um eine Zeichenfolge zu speichern, die auf den Namen der aktuellen Wiedergabeliste verweist. Ich könnte es dann zwischen jedem nächsten / vorherigen Track-Anruf überprüfen.

Durch das Schreiben dieser Frage habe ich bereits eine bessere Vorstellung davon, welchen Weg ich nehmen werde, aber wenn jemand einen Rat für dieses Szenario hat, dann würde ich gerne hören.

Danke.

UPDATE: Ich habe 95% einer Lösung implementiert, die Redis dafür verwendet. Ich habe ein paar Performance-Probleme, aber mit Seiten ~ 10 zu laden. Überhaupt nicht großartig.

Im Prinzip hat jeder Benutzer 2 Wiedergabelisten: Current und Armed. Jede Anfrage lädt die Track-IDs in die Redis Armed-Playlist und wenn die Play-Taste auf einem Track gedrückt wird, ist die Current Redis-Playlist abgelaufen und wird durch die Bewaffnete ersetzt.

Mit den Tasten Next und Previous rufen Sie einfach die ID des nächsten oder vorherigen Tracks in der aktuellen Playliste ab und laden die Musikquelle für den Player. Das Konzept funktioniert gut und ich bin zufrieden damit.

Wie bereits erwähnt, ist die Leistung zwischen den Seitenanforderungen jedoch gering und muss erheblich verbessert werden. Mein SQL ist optimiert, ich ziehe nur die erforderlichen Attribute heraus und ich habe SQL-Indizes wo nötig, also suche ich nach anderen Alternativen im Moment.

Optionen, die ich in Erwägung ziehe:

  1. Füllen Sie die bewaffnete Wiedergabeliste nur aus, wenn auf der neuen Seite auf einen Track geklickt wird. Dies würde zusätzliche Verarbeitung sparen, wenn der Benutzer nicht wirklich auf eine der neuen Spuren hören möchte.

  2. Indem Sie Redis verwenden und die Mager-Track-Objekte in den Redis-Playlists speichern und nicht nur die Track-ID, liegt die Performance-Verzögerung weitgehend zwischen den Seitenanforderungen und nicht in der tatsächlichen Wiedergabe von Titeln und Navigieren in einer Playlist.

  3. Nutzen Sie eine Master-Redis-Playlist, die alle Anwendungen enthält, aus denen die aktuellen und die bewaffneten Playlists auswählen können. Dies könnte über eine stündliche Rake-Aufgabe aufrechterhalten werden und würde lange DB-Aufrufe bei Seitenanforderungen verhindern. Ich bin nur nervös, wie weit dies hinsichtlich der Speichernutzung auf dem Server und der Anzahl der Tracks in der DB skalieren würde.

Pete 28.01.2012, 17:34
quelle

3 Antworten

1

Wenn Sie den clientseitigen Anwendungsstatus modellieren müssen, ist es am besten, eine Quelle des Status zu haben. Dies ist das eine der Probleme auf der Clientseite Javascript MV (V) C-Frameworks versuchen zu lösen. Ich bin hauptsächlich mit backbone.js und ember vertraut. damit ich mit denen sprechen kann.

Backbone.js

Erstellen Sie ein Modell namens Playlist und eine Sammlung namens Playlists . Fügen Sie Ihrer Playlists sammlung currentPlaylist eine Eigenschaft hinzu, die die aktuelle Wiedergabeliste enthält. Definieren Sie dann eine Ansicht namens PlaylistView und definieren Sie eine Methode render . Verknüpfen Sie Ereignisauslöser und -bindungen so, dass die Wiedergabeliste bei currentPlaylist automatisch neu gerendert wird. Dazu müsste das Template-Rendering auf den Client verschoben werden, aber das möchten Sie wahrscheinlich trotzdem tun, um Server-Roundtrips zu reduzieren und die Belastung des Servers durch Rendering zu reduzieren.

Ember.js

Erstellen Sie einen Controller (ähnlich der Backbone-Sammlung) mit einer Eigenschaft namens currentPlaylist und füllen Sie den Controller mit allen Playlists, die als Ember.object s dargestellt sind. Dann können Sie in einer auf der Seite enthaltenen Playlist-Lenkervorlage an playlists.currentPlaylist binden und die Vorlage wird automatisch neu gerendert, wenn playlists.currentPlaylist sich ändert.

Ich verlasse offensichtlich die überwiegende Mehrheit der Details, aber das sind die Framework-Dokumentation, Beispiele und Tutorials.

Haftungsausschluss : Ich bin neu bei clientseitigen Frameworks, was ein Grund dafür ist, dass ich die meisten Details weggelassen habe. Ich schätze jeden, der mich korrigieren kann, wenn ich mich irre.

    
Patrick Klingemann 26.02.2012 21:35
quelle
1

Eine Mischung aus Sitzung und lokalem Speicher wäre ein guter Ansatz.

Aber anstatt die ganze Playliste zu holen, hole einfach die X (zum Beispiel 10) nächsten Tracks und vielleicht auch die X vorherigen. Sobald der Spieler zum letzten Lied kommt, holt er die nächsten 10 Lieder, die vorherigen können im Klienten berechnet werden.

Das Datenmodell könnte nur ein Hash sein, wobei Element [0] das aktuelle Lied ist, Elemente [X] die nächsten Lieder und [-X] die vorherigen Lieder.

Das Speichern der Playlist-Informationen auf der Client-Seite erscheint mir sinnvoll, aber Sie können die Session auch verwenden, um auf den aktuellen Song und die Playlist zu verweisen. Wenn ein Benutzer zurückkommt oder Ihre Site wirklich neu lädt, erhalten Sie den Song, ohne eine Datenbank zu erstellen ruf an.

    
yagooar 18.03.2012 07:24
quelle
0

Ich würde vorschlagen, c) In Sitzung.
Auf Sitzungsdaten kann sowohl auf Client- als auch auf Serverseite relativ einfach zugegriffen werden.

Wenn Sie Ihren Redis-Cache mit bestimmten Benutzerdaten füllen, wird das nicht besonders gut skaliert.

LocalStorage - Korrekt, dies wird für einen Großteil der Benutzer am aktuellen Datum fehlschlagen.

CustomData Attribute - einfach nur unordentlich, wie bereits erwähnt.

Nur meine 2 Cent.

    
nelsonenzo 02.02.2012 19:43
quelle