Wie Spotify mit der Picture-in-Picture-API den Spotify-Miniplayer erstellt hat

Guido Kessels
Guido Kessels
François Beaufort
François Beaufort

Spotify, der weltweit beliebteste Abodienst für Musikstreaming, arbeitet kontinuierlich daran, die Art und Weise zu verbessern, wie Nutzer Audio- und Videoinhalte konsumieren. Mit einer umfangreichen Mediathek mit Musik, Podcasts und Hörbüchern wird die Plattform täglich von Millionen von Nutzern auf Mobilgeräten, PCs und anderen Plattformen genutzt.

Vor Kurzem hat Spotify den Spotify-Miniplayer für die Desktop- und Webplayer-Clients veröffentlicht. Der Miniplayer bietet wichtige Wiedergabesteuerungen in einem kleinen, kompakten Fenster, das immer im Vordergrund bleibt und Nutzern so einen ständigen Zugriff auf Spotify ermöglicht. Diese Funktion wurde schon lange von Nutzern gefordert und ermöglicht es ihnen, nahtlos in verschiedenen Fenstern und Apps zu multitasken, während sie ihre Lieblingskünstler, -playlists und -Podcasts auf Spotify genießen.

Im Folgenden findest du einen detaillierten Blick auf die Entwicklung des Miniplayers, vom ursprünglichen „Canvas-Hack“ bis hin zur erweiterten, nutzerfreundlichen Version, die auf der neuen Document Picture-in-Picture API basiert.

Der „Canvas-Hack“

Die erste Version des Miniplayers wurde 2019 als Hackprojekt im Webplayer von Spotify eingeführt. Ziel war es, die Picture-in-Picture (PiP) API für <video> des Browsers zu verwenden, um Albumcover in einem immer sichtbaren Fenster anzuzeigen. Diese API wurde jedoch hauptsächlich für Videoelemente entwickelt und es war nicht möglich, Albumcover-Bilder zu zeigen. Spotify hat das Problem umgangen, indem es das Albumcover in einem Canvas-Element gerendert und die HTMLCanvasElement captureStream() Methode verwendet hat, um ein MediaStream-Objekt in Echtzeit zu erhalten. Dieser Stream dient dann als Quelle für das Video, das für die PiP API verwendet wird. Dieser Ansatz basiert auf dem Beispiel „Audioplaylist“ von Google Chrome.

Spotify kombinierte den Canvas mit den entsprechenden Aktions-Handlern, die in der Media Session API festgelegt sind, um zu steuern, welche Playersteuerungen im PiP-Fenster angezeigt werden. So hatten Nutzer ein schwebendes Fenster mit Albumcover und Player-Steuerelementen, mit denen sie die Wiedergabe steuern konnten, während sie sich auf andere Aufgaben konzentrierten.

Screenshot des einfachen Spotify-Miniplayer-Fensters

So konnte Spotify einen einfachen Miniplayer anbieten. Der Ansatz hatte jedoch einige Einschränkungen:

  • Videountertitel werden im PiP-Fenster nicht unterstützt. Da Spotify Untertitel für alle Videos anzeigen musste, musste das PiP-Fenster geschlossen werden, sobald ein Video gestartet wurde.
  • Die Steuerelemente des Videoplayers sind nur sichtbar, wenn die Wiedergabe lokal erfolgt. Spotify ermöglicht die Remote-Wiedergabe über Spotify Connect (und andere Protokolle) und möchte, dass Nutzer diese Wiedergabe auch steuern können.
  • Das Erscheinungsbild des PiP-Fensters kann nicht angepasst werden. Spotify konnte nur Artwork anzeigen und die von Chrome bereitgestellten Playersteuerelemente verwenden. Das Hinzufügen des Spotify-Brandings oder zusätzlicher Playersteuerelemente war nicht möglich.

Da sie die Benutzeroberfläche nicht steuern und keine Spotify-spezifischen Funktionen hinzufügen konnten (z. B. einem Titel ein „Mag ich“ hinzufügen), war dieser Ansatz für den Desktop-Client nicht geeignet.

Bild-im-Bild-Modus für Dokumente: Die Weiterentwicklung des Miniplayers

Anfang 2023 erfuhr Spotify, dass Google Chrome wieder Interesse an der Einführung einer neuen API hat, mit der beliebige HTML-Inhalte im PiP-Fenster angezeigt werden können. Diese API wird als Document Picture-in-Picture API bezeichnet. Diese Entwicklung war für Spotify spannend, da sie damit die vollständige Kontrolle über das Erscheinungsbild des PiP-Fensters hat. Spotify hat während des Origin Trials mit dem Chrome-Team zusammengearbeitet, um einen neuen Miniplayer auf der Grundlage der Document Picture-in-Picture API zu entwickeln.

Mit der Document PiP API können Sie ein neues Fenster öffnen, das immer im Vordergrund angezeigt wird und an das Sie Elemente anhängen können. Da der Spotify Webplayer eine React-Webanwendung ist, verwendete Spotify die createPortal()-Methode von ReactDOM, um benutzerdefinierte Komponenten aus der Hauptanwendung in das PiP-Fenster zu rendern. So hat Spotify die volle Kontrolle über das Aussehen und die Funktionen des Miniplayers.

Mit der neuen Picture-in-Picture API für Dokumente wurden auch die vorherigen Probleme von Spotify behoben:

  • Videos im PiP-Fenster sind reguläre Videoelemente und werden vollständig mit Untertiteln unterstützt.
  • Da du die Benutzeroberfläche vollständig steuern kannst, werden die Steuerelemente des Players auch dann angezeigt, wenn die Wiedergabe per Spotify Connect aus der Ferne erfolgt.
  • Spotify konnte sein Design und die Playersteuerung einbinden und so die Nutzerfreundlichkeit verbessern.
  • So konnte das Team die Unterstützung für die Document PiP API in den Desktop-Client von Spotify einbinden und den Miniplayer für Millionen von Desktop-Nutzern verfügbar machen.

Screenshot des neuen Spotify-Miniplayer-Fensters

Bild-im-Bild-Fenster mit React erstellen

Im folgenden Beispiel wird gezeigt, wie Sie das Bild-im-Bild-Fenster für Dokumente in React verwenden können, genau wie das Spotify-Team. Sie erstellen zwei React-Komponenten: MyFeature und PiPContainer.

Die Komponente MyFeature ist für die Verwaltung des Bild-im-Bild-Fensters zuständig. Es wird eine Schaltfläche gerendert, mit der das Bild-im-Bild-Fenster ein- und ausgeblendet wird, und die PiPContainer-Komponente. Außerdem wird das Ereignis "pagehide" des Bild-im-Bild-Fensters abonniert, um den Status zu aktualisieren, wenn das Fenster geschlossen wird.

const MyFeature = () => {
  const [pipWindow, setPiPWindow] = useState<Window | null>(
    documentPictureInPicture.window
  );

  const handleClick = useCallback(async () => {
    if (pipWindow) {
      pipWindow.close();
    } else {
      const newWindow = await documentPictureInPicture.requestWindow();
      setPiPWindow(newWindow);
    }
  }, [pipWindow]);

  useEffect(() => {
    const handleWindowClose = (): void => {
      setPiPWindow(null);
    };

    pipWindow?.addEventListener("pagehide", handleWindowClose);

    return () => {
      pipWindow?.removeEventListener("pagehide", handleWindowClose);
    };
  }, [pipWindow]);

  return (
    <>
      <button onClick={handleClick}>
        {pipWindow ? "Close PiP Window" : "Open PiP Window"}
      </button>
      <PiPContainer pipWindow={pipWindow}>Hello World 👋!</PiPContainer>
    </>
  );
};

Die PiPContainer-Komponente verwendet die Methode createPortal() von ReactDOM, um Inhalte im Bild-im-Bild-Fenster zu rendern.

type Props = PropsWithChildren<{
  pipWindow: Window | null;
}>;

const PiPContainer = ({ pipWindow, children }: Props) => {
  useEffect(() => {
    if (pipWindow) {
      cloneStyles(window.document, pipWindow.document);
    }
  }, [pipWindow]);

  return pipWindow ? createPortal(children, pipWindow.document.body) : null;
};

Nächste Schritte

Spotify arbeitet kontinuierlich an der Weiterentwicklung und Innovation. Wir sind bestrebt, den Miniplayer zu verbessern und seine Funktionen und die Nutzerfreundlichkeit weiter zu optimieren. Konkrete Funktionen können noch nicht genannt werden, aber das Team ist sehr gespannt auf die zukünftigen Möglichkeiten des Miniplayers.

Screenshot der verschiedenen Formen des Spotify-Miniplayer-Fensters

Die Picture-in-Picture API für Dokumente bietet die Flexibilität und Kontrolle, um einen intuitiveren und nutzerfreundlicheren Miniplayer zu erstellen. Wir hoffen, dass andere Browseranbieter die Vorteile dieser API erkennen und eine Unterstützung in Betracht ziehen. So kann Spotify allen Nutzern unabhängig von ihrem ausgewählten Browser eine einheitliche und optimierte Nutzung bieten.

Danksagungen

Vielen Dank an alle bei Spotify, die am Miniplayer mitgewirkt haben.

Spotify möchte sich auch beim Google Chrome-Team für die Zusammenarbeit bedanken und dafür, dass es das Feedback von Spotify zur Document Picture-in-Picture API berücksichtigt hat.