Jak Spotify wykorzystała interfejs Picture-in-Picture API do stworzenia miniodtwarzacza Spotify

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

Spotify, najpopularniejsza na świecie usługa subskrypcji strumieniowego przesyłania dźwięku, stale stara się ulepszać sposób, w jaki użytkownicy korzystają z treści audio i wideo. Oferuje ona obszerną bibliotekę muzyki, podcastów i audiobooków, a codziennie korzysta z niej na urządzeniach mobilnych, komputerach i innych platformach miliony użytkowników.

Niedawno Spotify wprowadził miniodtwarzacz Spotify dla klientów na komputery i odtwarzaczy internetowych. Miniodtwarzacz oferuje najważniejsze elementy sterowania odtwarzaniem w małym, kompaktowym oknie, które pozostaje na górze, zapewniając użytkownikom stały dostęp do Spotify. Ta funkcja była od dawna oczekiwana. Umożliwia ona użytkownikom płynne wykonywanie wielu zadań w różnych oknach i aplikacjach, a zarazem słuchanie ulubionych wykonawców, playlist i podcastów w Spotify.

Poniżej znajdziesz szczegółowy opis procesu tworzenia miniodtwarzacza, od początkowego „hackowania” na płótnie do bardziej zaawansowanej, przyjaznej dla użytkownika wersji opartej na nowym interfejsie Document Picture-in-Picture API.

„Canvas hack”

Pierwsza wersja miniodtwarzacza została uruchomiona w 2019 roku w odtwarzaczu internetowym Spotify jako projekt hackerski. Celem było wykorzystanie interfejsu API obrazu w obrazie (PiP) w przeglądarce w przypadku <video>, aby wyświetlać okładkę albumu w oknie zawsze na wierzchu. Jednak ten interfejs API został zaprojektowany przede wszystkim pod kątem elementów wideo, a nie wyświetlania okładek albumów. Spotify obejście to, renderując okładkę albumu do elementu canvas i korzystając z metody HTMLCanvasElement captureStream() , aby uzyskać obiekt MediaStream w czasie rzeczywistym. Ten strumień służy następnie jako źródło filmu używanego w interfejsie PiP API. To podejście opiera się na próbce „Lista odtwarzania audio” w Google Chrome.

Spotify połączył kanwę z odpowiednimi elementami obsługi działań ustawionymi w interfejsie Media Session API, aby kontrolować, które elementy sterujące odtwarzaczem mają się wyświetlać w oknie PiP. Dzięki temu użytkownicy mogli wyświetlać pływające okno z okładką albumu i elementami sterującymi odtwarzaniem, które pozwalały im kontrolować odtwarzanie, gdy skupiali się na innych zadaniach.

Zrzut ekranu przedstawiający podstawowe okno miniodtwarzacza Spotify.

Dzięki temu Spotify mógł wprowadzić podstawowy Miniplayer. Takie podejście miało jednak kilka ograniczeń:

  • Nie można wyświetlać napisów do filmu w oknie PiP. Ponieważ Spotify musiał wyświetlać napisy do wszystkich filmów, musiało zamknąć okno PiP, gdy tylko rozpoczęło się odtwarzanie filmu.
  • Elementy sterujące odtwarzaczem są widoczne tylko wtedy, gdy odtwarzanie odbywa się lokalnie. Spotify umożliwia odtwarzanie na odległość za pomocą Spotify Connect (i innych protokołów) i chce, aby użytkownik mógł też sterować odtwarzaniem.
  • Nie można dostosować wyglądu okna PiP. Spotify może wyświetlać tylko grafikę i używać elementów sterujących odtwarzaczem udostępnianych przez Chrome, co uniemożliwia dodanie elementów marki Spotify lub dodatkowych elementów sterujących odtwarzaczem.

Brak kontroli nad interfejsem użytkownika i niemożność dodania funkcji specyficznych dla Spotify (np. polubienia utworu) sprawiły, że nie uznali tego podejścia za odpowiednie dla swojego klienta na komputery.

Dokumenty w trybie obrazu w obrazie: ewolucja miniodtwarzacza

Na początku 2023 r. Spotify dowiedział się o odnowionym zainteresowaniu Google Chrome wprowadzeniem nowego interfejsu API, który umożliwi wyświetlanie dowolnych treści HTML w oknie PiP. Interfejs ten jest znany jako Document Picture-in-Picture API. Ta zmiana była ekscytująca dla Spotify, ponieważ dawała firmie pełną kontrolę nad wyglądem okna PiP. Podczas próby Origin Spotify współpracowało z zespołem Chrome nad stworzeniem nowego miniodtwarzacza na podstawie interfejsu Document Picture-in-Picture API.

Interfejs API dokumentu w trybie Picture-in-Picture umożliwia otwieranie nowych okien, które zawsze są widoczne na wierzchu, i dodawanie do nich elementów. Odtwarzacz internetowy Spotify jest aplikacją internetową opartą na React. Spotify używa metody createPortal() w bibliotece ReactDOM do renderowania niestandardowych komponentów w oknie PiP z głównej aplikacji, co zapewnia pełną kontrolę nad wyglądem i funkcjami Miniplayera.

Nowy interfejs API Picture-in-Picture dla dokumentów rozwiązał też wcześniejsze problemy Spotify:

  • Filmy w oknie PiP są zwykłymi elementami wideo i w pełni obsługują napisy.
  • Dzięki pełnej kontroli nad interfejsem elementy sterujące odtwarzaczem mogą być wyświetlane nawet wtedy, gdy odtwarzanie odbywa się zdalnie za pomocą Spotify Connect.
  • Spotify mógł wdrożyć wygląd i działanie elementów sterujących odtwarzaczem, co poprawiło wrażenia użytkowników.
  • Udało im się wdrożyć obsługę interfejsu Document PiP API w kliencie Spotify na komputery, dzięki czemu mogli udostępnić miniodtwarzacz milionom użytkowników korzystających z komputerów.

Zrzut ekranu przedstawiający nowe okno miniodtwarzacza Spotify.

Tworzenie okna obrazu w obrazie za pomocą React

Ten przykład pokazuje, jak można używać okna Picture-in-Picture w dokumentach w React tak jak zespół Spotify. Utworzysz 2 komponenty React: MyFeaturePiPContainer.

Komponent MyFeature odpowiada za zarządzanie oknem z obrazem w obrazie. Wyświetla przycisk, który przełącza okno obrazu w obrazie, i renderuje komponent PiPContainer. Subskrybuje też zdarzenie "pagehide" okna Obraz w obrazie, aby aktualizować stan po zamknięciu okna.

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>
    </>
  );
};

Komponent PiPContainer używa metody createPortal() w ReactDOM do renderowania treści w oknie obrazu w oknie.

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;
};

Co dalej?

Spotify stale się rozwija i wprowadza innowacje, dlatego nadal ulepszamy miniodtwarzacz i planujemy dalsze ulepszanie jego funkcji oraz wrażeń użytkowników. Chociaż nie możemy jeszcze obiecać konkretnych funkcji, jesteśmy podekscytowani możliwościami, jakie niesie ze sobą miniodtwarzacz.

Zrzut ekranu pokazujący różne kształty okna miniodtwarzacza Spotify.

Interfejs API dokumentu w okienku zapewnił elastyczność i kontrolę, dzięki którym udało się stworzyć bardziej intuicyjny i przyjazny użytkownikowi miniodtwarzacz. Mamy nadzieję, że inni dostawcy przeglądarek zauważą możliwości, jakie oferuje ten interfejs API, i rozważą jego obsługę. Dzięki temu Spotify będzie mógł zapewnić spójne i ulepszone wrażenia wszystkim użytkownikom, niezależnie od wybranej przeglądarki.

Podziękowania

Dziękujemy wszystkim pracownikom Spotify, którzy brali udział w tworzeniu miniodtwarzacza.

Spotify dziękuje też zespołowi Google Chrome za współpracę i uwzględnienie opinii Spotify w przypadku interfejsu Document Picture-in-Picture API.