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 strumieniowania audio, nieustannie staramy się poprawiać sposób korzystania z treści audio i wideo przez użytkowników. Oferuje pokaźną bibliotekę muzyki, podcastów i audiobooków, dzięki czemu codziennie odwiedzają ją miliony użytkowników korzystających z urządzeń mobilnych, komputerów i innych platform.

Niedawno firma Spotify wydała miniodtwarzacz Spotify dla klientów korzystających z odtwarzacza na komputerze i odtwarzacza internetowego. Miniodtwarzacz został zaprojektowany tak, aby zawierał podstawowe elementy sterujące odtwarzaniem w małym, niewielkim oknie, które pozostaje na górze, i zapewnia użytkownikom stały dostęp do Spotify. O tę funkcję od dawna prosiliśmy i umożliwia użytkownikom płynne wykonywanie wielu zadań w różnych oknach i aplikacjach, słuchając ulubionych wykonawców, playlist i podcastów w Spotify.

Poniżej szczegółowo omawiamy proces tworzenia miniodtwarzacza – od początkowego „hackingu” do bardziej zaawansowanej i przyjaznej dla użytkownika wersji opartej na nowym interfejsie Document Picture-in-Picture API.

Ataki typu Canvas

Pierwsza wersja miniodtwarzacza została opublikowana w 2019 roku w usłudze Web Player w Spotify jako projekt hakerski. Celem było wykorzystanie interfejsu API obrazu w obrazie (PiP) przeglądarki dla elementu <video> w celu wyświetlania okładki albumu w oknie, które zawsze jest wyświetlane. Ten interfejs API został jednak opracowany przede wszystkim z myślą o elementach wideo i nie można było wyświetlać okładek albumów. Spotify obchodziło ten problem, renderując okładkę albumu w elemencie canvas i używając metody HTMLCanvasElement captureStream(), aby uzyskać obiekt MediaStream w czasie rzeczywistym. Służy on jako źródło filmu używanego na potrzeby interfejsu PiP API. Podejście opierało się na przykładzie z „Playlista audio” w Google Chrome.

Spotify połączył obszar roboczy z odpowiednimi modułami obsługi działań skonfigurowanymi w interfejsie Media Session API, aby kontrolować, które elementy sterujące odtwarzaczem pojawią się w oknie obrazu w obrazie. Dzięki temu użytkownicy mieli dostęp do pływającego okna z okładką albumu i elementami sterującymi odtwarzacza, które mogli używać do sterowania odtwarzaniem i jednocześnie skupiać się na innych zadaniach.

Zrzut ekranu przedstawiający podstawowe okno miniodtwarzacza Spotify.

Dzięki temu Spotify miał podstawowy miniodtwarzacz. Podejście to miało jednak kilka ograniczeń:

  • W oknie obrazu w obrazie nie są obsługiwane napisy do filmów. Spotify musiało wyświetlać napisy do wszystkich filmów, więc musieli zamknąć okno PIP od razu po rozpoczęciu odtwarzania filmu.
  • Elementy sterujące odtwarzaczem są widoczne tylko wtedy, gdy odtwarzanie odbywa się lokalnie. Spotify umożliwia zdalne odtwarzanie za pomocą Spotify Connect (i innych protokołów) i chce, aby użytkownik również mógł sterować tym odtwarzaniem
  • Nie ma możliwości dostosowywania wyglądu i sposobu działania okna funkcji obraz w obrazie. Spotify może wyświetlać tylko elementy graficzne i korzystać z elementów sterujących dostępnych w Chrome, przez co nie można dodać marki Spotify ani dodatkowych elementów sterujących odtwarzaczem.

Brak kontroli nad interfejsem użytkownika i niemożność dodania w tym miejscu funkcji Spotify (np. polubienie utworu) sprawiły, że uznali, że to podejście nie sprawdzi się w przypadku klienta komputerowego.

Dokument (obraz w obrazie): ewolucja miniodtwarzacza

Na początku 2023 roku firma Spotify dowiedziała się o zwiększonym zainteresowaniu Google Chrome udostępnieniem nowego interfejsu API, który umożliwiłby wyświetlanie dowolnych treści HTML w oknie obrazu w obrazie. Nazywamy to interfejsem Document Picture-in-Picture API. Ta propozycja była ekscytująca dla Spotify, ponieważ umożliwiała im pełną kontrolę nad wyglądem okna funkcji PIP. Podczas testu origin firma Spotify współpracowała z zespołem Chrome nad stworzeniem nowego miniodtwarzacza opartego na interfejsie Document Picture-in-Picture API.

Document PiP API umożliwia otwarcie nowego, zawsze aktywnego okna, do którego możesz dołączać elementy. Ponieważ Spotify Web Player to aplikacja internetowa React, Spotify wykorzystuje metodę createPortal() ReactDOM, aby renderować niestandardowe komponenty w oknie PIP z poziomu głównej aplikacji, dając pełną kontrolę nad wyglądem i funkcjami miniodtwarzacza.

Nowy interfejs Document Picture-in-Picture API rozwiązuje też wcześniejsze problemy Spotify:

  • Filmy w tym oknie to zwykłe elementy wideo, które w pełni obsługują napisy.
  • Mając pełną kontrolę nad interfejsem, elementy sterujące odtwarzaczem można wyświetlać nawet wtedy, gdy odtwarzanie odbywa się zdalnie przez Spotify Connect.
  • Spotify zadbało o wygodę użytkowników i dostosował wygląd i sposób działania oraz elementy sterujące odtwarzaczem.
  • Firmie udało się wprowadzić obsługę interfejsu Document PiP API w kliencie Spotify na komputery, co pozwoliło udostępnić miniodtwarzacz milionom użytkowników komputerów.

Zrzut ekranu nowego miniodtwarzacza Spotify.

Tworzenie okna obraz w obrazie za pomocą React

Poniższy przykład pokazuje, jak korzystać z obrazu w obrazie dokumentu w React, podobnie jak robi to zespół Spotify. Utworzysz 2 komponenty React: MyFeature i PiPContainer.

Komponent MyFeature odpowiada za zarządzanie oknem obrazu w obrazie. Renderuje przycisk, który przełącza okno obrazu w obrazie i renderuje komponent PiPContainer. Subskrybuje też zdarzenie "pagehide" okna obrazu w obrazie, aby aktualizować jego 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 wykorzystuje metodę createPortal() ReactDOM, aby renderować treści w oknie obraz w obrazie.

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

W miarę jak Spotify będzie się rozwijać i ulepszać, zespół niezmiennie będzie starał się ulepszać miniodtwarzacz i planować dalsze udoskonalanie jego funkcji oraz wygody użytkowania. Chociaż nie mogą jeszcze skupić się na konkretnych funkcjach, są już podekscytowani przyszłymi możliwościami miniodtwarzacza.

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

Interfejs Document Picture-in-Picture API zapewnia elastyczność i kontrolę, umożliwiając stworzenie bardziej intuicyjnego i łatwego w obsłudze miniodtwarzacza. Mamy nadzieję, że inni dostawcy przeglądarek uwzględnią możliwości, jakie oferuje ten interfejs API, i rozważą wprowadzenie ich obsługi. Dzięki temu Spotify będzie bardziej spójną i wygodną usługą dla wszystkich użytkowników, niezależnie od wybranej przez nich przeglądarki.

Podziękowania

Dziękujemy wszystkim w Spotify, którzy zaangażowali się w stworzenie miniodtwarzacza.

Spotify chce również podziękować zespołowi Google Chrome za współpracę i wzięcie pod uwagę opinii Spotify dotyczących interfejsu Document Picture-in-Picture API.