Für music-streamer versuche ich, einfach das HTML 5 Audio-Element zu nutzen und den Rest dem Browser und ihrer Weiterentwicklung zu überlassen. Funktionsweise: Mein Javascript erstellt immer ein Audio-Element für das derzeitige Lied, am Ende davon wird das Element mit einem neuen für das nächste Lied ersetzt usw. Natürlich kann man auch vor- und zurückwechseln.
Beim schnellen Wechseln passiert es manchmal, dass der generierte HTML-Code einwandfrei aussieht, das Audio-Element aber inaktiv bleibt (insbesondere signalisiert das ein durchgestrichener Lautsprecher bei der Laustärkeeinstellung). Was passiert da?
Mir fielen mehrere Möglichkeiten ein: Eventuell sind alle Verbindungen zum Server belegt, weil der Browser das Ersetzen des Audio-Elementes nicht mitbekommt und daher alle kurz geöffneten Musikstücke auf einmal versucht zu ziehen. Oder Chrome scheitert daran, den Rest der nur bruchstückhaft im Cache gespeicherte MP3 herunterzuladen.
Es kann auch eine Kombination sein, dass durch den Cache verhindert wird, dass nach dem Freiwerden einer Verbindung der Download fortgesetzt wird. Das ist meine derzeitige Vermutung, mein Workaround legt das nahe.
Aber erstmal die Problemdiagnostik. Gut zu sehen ist es auf diesem Netzwerkprotokoll:
Ich habe eine Reihe von Songs duchgewechselt. Track 24, 25, 26 und zurück zu 25. Und genau, Track 25 lädt nicht. Man sieht im Protokoll, dass der Ladebalken grau bleibt, also kein echter Request abgeschickt wird (oder was bedeutet es sonst, dass der Balken grau ist?). Hier ist das zugehörige Serverprotokoll:
requesting track 23
127.0.0.1 - - [07/Jan/2013 16:40:18] "GET /track/23 HTTP/1.1" 206 11062262 0.9775
requesting track 24
127.0.0.1 - - [07/Jan/2013 16:40:20] "GET /track/24 HTTP/1.1" 206 4937698 0.4218
requesting track 25
127.0.0.1 - - [07/Jan/2013 16:40:23] "GET /track/25 HTTP/1.1" 206 5535170 0.5492
requesting track 26
127.0.0.1 - - [07/Jan/2013 16:40:25] "GET /track/26 HTTP/1.1" 206 2987291 0.2839
localhost - - [07/Jan/2013:16:40:25 CET] "GET /track/26 HTTP/1.1" 206 2987291
http://localhost:4567/ -> /track/26
Am Server kommt nie ein zweiter Request für Track 25 an. Riecht also nach einem Cache/Browserproblem.
Der Code zum Senden der Tracks sieht so aus (music-streamer nutzt Ruby mit Sinatra):
get %r{/track/([0-9]+)} do |id|
puts "requesting track #{id}"
path = Database.new.getPath(id)
type = FileMagic.new(FileMagic::MAGIC_MIME).file(path)
content_type type
send_file path, :type => type
end
Die Datei wird also mit dem richtigen Content-Type rausgesendet, viel mehr passiert hier nicht.
send_file kümmert sich darum, dass die nötigen Header richtig gesetzt werden. Insbesondere setzt es den Last-Modified Header auf das echte Datum, an dem die Datei das letzte Mal editiert wurde. Zusammen mit dem grauen Balken und der nichtvorhandenen Serveranfrage vermutete ich, dass der Browser damit nicht zurechtkommt.
Daher kam ich auf diesen Workaround: Browser-Caching verhindern, indem der Last-Modified-Header auf "jetzt" gesetzt wird:
send_file path, :type => type, :last_modified => DateTime.now.httpdate
So bleibt zwar immer noch etwas Wartezeit, wenn zu viele Tracks auf einmal gesendet werden, aber nach dieser Wartezeit wird der Track geladen.
Die richtige und bessere Lösung wäre wohl, den Browser dazu zu bringen, abgebrochene Lieder nicht weiter zu laden. Dann käme es gar nicht dazu, dass die Maximalanzahl an Verbindungen zum Server überschritten wird.
Es ist natürlich trotzdem möglich, dass der Fehler nur ausgelöst wird, weil im Javascript das alte Audio-Element noch herumfliegt und deswegen die Verbindung bestehen bleibt. Doch selbst wenn dem so wäre, sollte Chrome den Request neu abschicken, wenn das Audio-Element neu erstellt wird. Daher sieht das für mich sehr nach einem echten Bug in Chromium aus.
onli blogging am : HTML 5: Laden für Audio-Element abbrechen
Vorschau anzeigen
onli blogging am : Updates für den music-streamer
Vorschau anzeigen