Diese Geschichte begann vor ungefähr 1,5 Jahren. Es ist mit dem Abspielen von Musik in verschiedenen Browsern und Plattformen verbunden, auf denen sie ausgeführt werden. Ein Weg voller
„Schmerz und Leid“ der Erkenntnis, dass eine einfache Aufgabe auf den ersten Blick möglicherweise nicht so einfach ist, und „unbedeutende“ Details, denen Sie am Anfang keine Bedeutung beimessen, können alles beeinflussen.
Kleinere Details für die Neugierigsten :)1. Herunterladen von Daten zu jedem nächsten Titel aus dem Netzwerk.
2. Für jedes Audioelement: new Audio () oder <audio> benötigen Sie die Erlaubnis des Benutzers - eine Benutzeraktion auf der Seite.
Hintergrund
Wahrscheinlich ist jeder, der mindestens einmal in seinem Leben einen Audio-Player für Browser geschrieben hat, auf das Problem der browserübergreifenden Kompatibilität und plattformübergreifenden Probleme gestoßen.
Während ich an dem neuen MVP arbeitete, stieß ich auf verschiedene Funktionen zur Wiedergabe von Audio in Browsern.
Und alles begann mit der Tatsache, dass es notwendig war, während der Wiedergabe zwei Spuren gleichmäßig zu überblenden - dies ist das erste Feature. Unser Team wollte die Titel wie im Radio wechseln. Und die zweite Funktion - jede nachfolgende Spur wird vom Netzwerk angefordert.

Forschungen
Dann verwendeten fast alle unsere Projekte die Sound Manager 2-Bibliothek.
Fast sofort stellen Sie fest, dass das gleichzeitige Abspielen von zwei Audiodateien auf Mobilgeräten nicht überall gleich funktioniert!
In Chrome (~ 62 Version) für PC wurden Titel so abgespielt, wie sie sollten. Auf Mobilgeräten (auch in Chrome) funktionierte die Titelwiedergabe, jedoch nur bei aktivem Bildschirm. Wenn der Bildschirm gesperrt war, wurde der nächste Titel nach dem aktuellen Player nicht abgespielt. Wie bei iOS / macOS funktionierte die Wiedergabe auf ähnliche Weise. Weitere Informationen erhalten Sie
hier - Abschnitt „Single Audio Stream“.
Also ging
ich über drei Meere und suchte Stück für Stück nach Informationen über die Funktionen von Browsern mit Audio.
Ok, ich versuche eine Lösung mit Web Audio, ohne Bibliotheken zu verwenden. Ja, diese Technologie ist für andere Zwecke gedacht: Synthese, Tonverarbeitung, für Spiele usw., anstatt nur Titel abzuspielen. Für das Experiment war es jedoch notwendig, es zu versuchen, da Sie damit Sounds aus verschiedenen Quellen in einem
Audioausgang zusammensetzen können - Lautsprecher / Kopfhörer / Telefonlautsprecher / usw. Es gibt Leute, die gezielt nach
den Möglichkeiten suchen, Sound auf Mobilgeräten mithilfe der Web-Audio-API abzuspielen.
Nach der Implementierung wurden bestimmte Nuancen deutlich.
Zunächst müssen Sie warten, bis der gesamte Track vollständig geladen ist. Bei einer langsamen Internetverbindung machen sich Pausen bemerkbar, da der zweite Titel möglicherweise bis zum Ende des ersten Titels keine Zeit zum Laden hat. Ein vollständiger Download kann vermieden werden, indem eine Reihe von HTML5-Audio-Tags verwendet werden, die als Tonquellen für Web-Audio dienen. In diesem Fall ist es jedoch wieder unmöglich, zwei Sounds gleichzeitig abzuspielen.
Zweitens, wenn Sie einen Track in Fragmenten über das Netzwerk herunterladen und programmgesteuert dekodieren, erhöht dies die Belastung der CPU. Dies war für einen PC akzeptabel, für mobile Geräte jedoch von entscheidender Bedeutung.
Drittens gab es Probleme bei der Dekodierung. Wenn Fragmente von mp3 / ogg / wav-Dateien zum Client kamen, wurden diese Stücke leise
dekodiert und abgespielt. Wenn jedoch Teile der mp4-Datei, die als Container für HE-AAC fungierte, in den Browser kamen, konnten sie nicht dekodiert werden. Dies gilt in gewissem Umfang auch für den Opera-Browser, in dem die Wiedergabe von MP3-Dateien von Version zu Version instabil ist - sie wird manchmal reproduziert und es wird der Fehler angezeigt, dass dieses Format nicht unterstützt wird.
Viertens wurde der Name des Titels auf dem gesperrten Bildschirm auf einer Platte mit einem nativen Audioplayer (auf dem iPad) nicht angezeigt / nicht geändert. beim Umschalten zwischen Spuren. Vielleicht aufgrund der Tatsache, dass die Tests das iPad mit Version 9 von iOS verwendeten - es gab zu diesem Zeitpunkt kein anderes.
Infolgedessen musste Web Audio zu diesem Zeitpunkt aufgegeben werden. Trotzdem ist Crossfade nichts für Browser, Standard-Musikkompositionen in guter Qualität wiegen ziemlich viel.
Da wir das Überblenden ablehnen, implementieren wir ein einfaches Ein- und Ausblenden am Anfang bzw. am Ende des Musiktitels.
Der Code im vorletzten Jahr wurde leicht modifiziert und getestet. Als Ergebnis der Tests tauchten verschiedene Nuancen auf (in der Tabelle gezeigt). All dies mithilfe der Sound Manager 2-Bibliothek.

Wir fügen die Protokollierung aller Ereignisse hinzu, um den Moment des Übergangs zwischen den Titeln zu bestimmen und um zu verstehen, an welchem Punkt sie aufhören zu spielen.

Tab-AktivierungIn Safari 9+ wird der Sound nicht immer angezeigt, wenn die Registerkarte aktiviert ist.
Hieraus kann angenommen werden, dass die Ausführung von JS im Hintergrund gedrosselt wird oder dass der Ausführungsthread vollständig stoppt (Ereignisse und
Timer ). Später wird jedoch klar, dass dies teilweise eine korrekte Schlussfolgerung war. Im Folgenden werden wir eine weitere Nuance betrachten, die mit dem Abspielen von Titeln verbunden ist, und verstehen, warum kein Ton angezeigt wird.
BemerkungUm mit dem Fortschritt (Fortschrittsbalken) zu arbeiten und ihn beispielsweise für einen Track zu rendern, empfiehlt es sich, requestAnimationFrame anstelle von setInterval / setTimeout zu verwenden. Sie können den kumulativen Effekt vermeiden, wenn Sie die Registerkarte deaktivieren (Registerkarte Hintergrund) und dann aktivieren und vorübergehend einfrieren, was mit allen Berechnungen und dem erneuten Zeichnen des Fortschrittsstatus verbunden ist.
Gleichzeitig stellte sich die Frage: Was ist mit der automatischen Wiedergabe von Titeln auf einem PC und auf Mobilgeräten?
Autoplay bezieht sich auf den automatischen Start der Wiedergabe eines Titels ohne Benutzeraktion beim Laden einer Seite.
Was Safari im Hinblick auf die
automatische Wiedergabe beim
Laden der Seite betrifft, ist dies nicht möglich. Sie benötigen eine
Benutzerinteraktion mit der Seite, wie auf
Mobilgeräten . Dies gilt sowohl für
Videoinhalte als auch für
Audioinhalte .
Zu dieser Zeit gab es also Folgendes:
- Es ist unmöglich (nicht wünschenswert), zwei oder mehr Töne gleichzeitig wiederzugeben.
- Für das Pseudo-Auto-Play des Tracks ist eine Benutzerberechtigung erforderlich - die erste Interaktion, später wurde sie als "Finger an das Gerät verkaufen" bezeichnet.
- im Hintergrund (Hintergrundregisterkarte / Sperrbildschirm) JS (alles hängt vom Browser ab):
entweder friert vollständig ein;
entweder Drosselung;
beides funktioniert genauso wie mit der aktiven Registerkarte;
- Sie können die Wiedergabe automatisch ohne Ton starten, aber es ist nicht klar, warum (für Audioinhalte)?
- Irgendwo in der Ferne taucht der Gedanke auf, aber wie kann man JS dazu bringen, weiterhin im Hintergrund zu arbeiten?
Andere Bibliotheken, die die Funktionen des Players implementierten, gingen davon aus, dass es möglicherweise eine Lösung für dieses Problem gibt. Trotz der Tatsache, dass auf GitHub viele Probleme mit einer Beschreibung der Probleme beim Abspielen von Titeln in verschiedenen Browsern beobachtet wurden, bestand immer noch die Hoffnung, dass Sie auf den Grund gehen würden: Warum funktioniert es nicht und wie funktioniert es? Wie sich herausstellte, nein ...
Einige Codebeispiele mit Videodemonstration der Arbeit von Bibliotheken:
- Sound Manager 2 - Github-Seiten , Github-Repository , Video: macOS Safari 12 ; iOS Safari 10 mit entsperrtem Bildschirm
- Heuler
Howler v2.0.9 - Github-Seiten , Github-Repository , Video: macOS Safari 12 , iOS Safari 10
Howler v2.0.15 - Github-Seiten , Github-Repository , Video: macOS Safari 12
Howler v2.1.1 - Github-Seiten , Github-Repository , Video: macOS Safari 12 , iOS Safari 10
Unter macOS wurde die Videoaufnahme ohne Ton erstellt. Sie müssen sich daher die Lautstärkeanzeige ansehen - das Bild des Lautsprechers auf der Registerkarte.
Weitere Beispielvideos finden Sie im Repository.
Im interaktiven Beispiel für Howler v2.1.1 - manchmal können Sie mehrere Sounds gleichzeitig hören. Dies ist auf das Hinzufügen eines Pools von Audioelementen zurückzuführen, die vom Benutzer entsperrt wurden (dies sollte in zukünftigen Versionen der Bibliothek behoben werden).
Was ist der Grund für die Inoperabilität dieser Bibliotheken?
Ich habe oben geschrieben:
"Im Hintergrund (Registerkarte" Hintergrund ") friert JS entweder vollständig ein oder wird gedrosselt .
" Hier taucht also ein weiterer Punkt auf: Bibliotheken im Code verwenden die Erstellung neuer Audioobjekte über new Audio (). Wenn sie dynamisch erzeugt werden, d.h. Wenn ein vorhandenes Audioobjekt nicht verwendet wird und der Benutzer in keiner Weise mit der Site interagiert, die Registerkarte inaktiv ist oder der Bildschirm gesperrt ist, können einige Browser der Ansicht sein, dass der Ton dieses Audioelements erst abgespielt werden sollte, wenn die Registerkarte wieder aktiv ist oder der Benutzer dies nicht tut jede Aktion.
Ein Beispieltest auf
Github-Seiten und im
Repository auf Github mit neuem Audio (). Video:
macOS Safari 12 ;
iOS Safari 10 mit entsperrtem Bildschirm.
Es scheint, dass es kein universelles Werkzeug gibt und es notwendig ist, nach einer anderen Kompromisslösung zu suchen.Dann setzen wir uns mit den Jungs aus dem Team zusammen, um zu diskutieren, und was ist wirklich wichtig für die Arbeit des Audio-Players? Denn es wäre möglich, die Experimente unendlich fortzusetzen, aber wir müssen vorwärts gehen.
Zunächst wurden wichtige Punkte identifiziert, die das Erreichen des gewünschten Ergebnisses verhinderten:
- Safari unter macOS spielt keine Titel ab, wenn die Registerkarte inaktiv ist.
- Auf Smartphones mit iOS und Android gibt es keine Möglichkeit, Musik im Hintergrund zu hören (wenn der Bildschirm gesperrt ist). Ich möchte eine aggressive Umleitung von Benutzern zu einer mobilen Anwendung (in Zukunft) vermeiden, da frühere Erfahrungen zeigen, dass ein großer Teil der Benutzer keine mobile Anwendung installieren möchte ;;
- Der Player arbeitet nicht korrekt mit einer dynamischen Wiedergabeliste, d. h. wenn nicht im Voraus bekannt ist, was der nächste Track sein wird.
Darüber hinaus konnten die zur Erreichung der Ziele erforderlichen Ziele formuliert werden:
- Stellen Sie den Player im Hintergrund bereit - in verschiedenen Browsern und auf verschiedenen Plattformen.
- Ermöglichen Sie dem Benutzer die Auswahl der zu verwendenden Elemente: Hören Sie Musik auf der Website oder in der mobilen Anwendung.
- bieten die Möglichkeit, den Player (oder Ansatz) in verschiedenen zukünftigen Projekten zu verwenden.
Eine neue Phase bei der Suche nach einer Lösung für das Problem hat begonnen. Zu diesem Zeitpunkt wurden verschiedene Bibliotheken nicht mehr verwendet, alle Studien wurden mit HTML5 Audio durchgeführt. Das Ergebnis war, dass eine Option mit
engagierten Mitarbeitern gefunden wurde . iOS ließ diese Entscheidung nicht wieder gewinnen - die Wiedergabe im Hintergrund funktioniert nicht, aber es stellte sich heraus, dass sie in Android (Chrome, Opera, Safari) funktioniert.
HTML5 Audio + Dedicated Workers-
Testbeispiel auf Github-Seiten und im
Github-Repository .
Wenn der Worker initialisiert wird, werden Daten zum aktuellen Track angefordert. Der Mitarbeiter sendet außerdem ein Signal, um den Fortschrittsstatus - wie lange der Titel abgespielt wird - vom Hauptstrom abzurufen, und entscheidet anhand dieser Daten, wann Daten über den nächsten Titel vom Netzwerk angefordert werden sollen.

Zu diesem Zeitpunkt wurde auch das folgende Beispiel getestet (
Github-Seiten ,
Github- Repository ), wenn das HTML5-Audio-Tag in das DOM eingebettet ist (Video:
macOS Safari 12 ,
iOS Safari 10 ) und SRC beim Wechseln zwischen Spuren einfach ersetzt. Bisher funktioniert dieses Beispiel unter macOS in 12 Safari. Leider gibt es derzeit keine Möglichkeit, die Funktionalität dieses Beispiels unter macOS in Safari 10 und 11 zu testen, aber zu diesem Zeitpunkt funktionierte dieses Beispiel während der Tests nicht (
Richtlinien für die automatische Wiedergabe ,
Einschränkungen für die automatische Wiedergabe ).
Zusammenfassend betrachtet der Safari-Browser für iOS und macOS keine neue Instanz des Audioelements, die vom Benutzer aktiviert werden soll, wenn es im Hintergrund eines Ereignisses erstellt wurde, z. B. ajax, setTimeout, onended.
In Bezug auf die Wiedergabe von Titeln in iOS Safari und iOS Chrome wurde außerdem festgestellt, dass Titel im Hintergrund (wenn der Bildschirm gesperrt ist) nur mit
HLS abgespielt werden können . Für iOS- und MacOS-Plattformen ist dieses Format Standard und die Übertragung wird vom Betriebssystem unterstützt. Für Android Chrome und Edge ist auch eine native Implementierung verfügbar. Und für PCs in Chrome können Sie Software-Handler verwenden, z. B.
hls.js ,
Bitmovin Player usw.
Ein
Link zum Github-Repository bietet ein Beispiel für Code, der den einfachsten Anwendungsfall abdeckt - einfach den auf dem Server generierten Stream abspielen, ohne zurückspulen, zum nächsten Titel wechseln usw. Beispiele werden vorgestellt mit: dem Audio-Tag, dem Video-Tag, der hls.js-Bibliothek und dem Player von Bitmovin. Dieser Inhalt erfordert Node.js.
Schlussfolgerungen
Der erste Punkt ist leider, dass es aufgrund der Vielfalt der Browser keine universelle Lösung gibt, die es ermöglicht, Musik in Browsern überall gleich gut zu hören. Überall gibt es Einschränkungen und wie die Praxis zeigt, können Sie ganz bequem damit leben.
Der zweite Punkt: Manchmal lohnt es sich, Grenzfälle so schnell wie möglich zu überprüfen, z. B. eine native Implementierung. Finden Sie eine Art minimal akzeptabler Anforderungen und überprüfen Sie schnell deren Leistung, anstatt eine Bibliothek als Grundlage zu verwenden. Dadurch erhalten Sie ein besseres Verständnis dafür, wie diese Bibliotheken intern angeordnet sind und warum bestimmte Funktionen funktionieren oder nicht. Andernfalls können Sie im Projekt ziemlich weit laufen und nachdem Sie festgestellt haben, dass etwas schief geht. Und es kann sich herausstellen, dass das Verlassen der Bibliothek ziemlich teuer sein wird. Ein wesentlicher Teil des Codes muss neu geschrieben werden.
Der dritte Punkt: Achten Sie unbedingt auf die Zielgruppe Ihres Dienstes - von welchen Browsern und Betriebssystemen Ihre Benutzer stammen. Dies ist mit verschiedenen Metriken und Fehlerüberwachungssystemen relativ einfach zu verfolgen. Ein solcher Ansatz hilft zu verstehen, welche Plattformen und Browser unterstützt werden müssen und welche ohne Aufwand verwendet werden können.
Und schließlich
Ich kündige einen kleinen Wettbewerb zum Abspielen von Musik auf iOS mit HLS-Technologie an.
Die Beschreibung finden Sie unter dem
Link auf Github .