Как Spotify использовал API «Картинка в картинке» для создания миниплеера Spotify

Франсуа Бофор
François Beaufort

Spotify, самая популярная в мире служба подписки на потоковую передачу аудио, постоянно стремится улучшить способы потребления пользователями аудио- и видеоконтента. Предлагая обширную библиотеку музыки, подкастов и аудиокниг, он ежедневно обслуживает миллионы пользователей на мобильных устройствах, ПК и других платформах.

Недавно Spotify выпустила Spotify Miniplayer для своих клиентов для настольных компьютеров и веб-плееров. Миниплеер предназначен для предоставления основных элементов управления воспроизведением в небольшом компактном окне, которое остается сверху, предоставляя пользователям постоянный доступ к Spotify. Это давно востребованная функция, которая позволяет пользователям беспрепятственно выполнять несколько задач в разных окнах и приложениях, наслаждаясь любимыми исполнителями, плейлистами и подкастами на Spotify.

Далее следует подробный обзор разработки Miniplayer, от начального «хака холста» до более продвинутой, удобной для пользователя версии, построенной на новом API Document Picture-in-Picture .

«Холстовый хак»

Первоначальная версия Miniplayer была запущена в 2019 году на Spotify Web Player как хакерский проект . Целью было использовать браузерный API «Картинка в картинке» (PiP) для <video> для отображения обложки альбома в окне, всегда находящемся сверху. Однако этот API в первую очередь был разработан для видеоэлементов, и показывать изображения обложек альбомов было невозможно. Spotify обошёл эту проблему, визуализировав обложку альбома в элементе холста и используя метод HTMLCanvasElement captureStream() для получения объекта MediaStream в реальном времени. Этот поток затем служит источником видео, используемого для API PiP. Этот подход был основан на образце «Аудио-плейлиста» Google Chrome .

Spotify объединил холст с соответствующими обработчиками действий, установленными в API сеанса мультимедиа, чтобы контролировать, какие элементы управления проигрывателем будут отображаться в окне PiP. Это дало пользователям плавающее окно с обложками альбомов и элементами управления проигрывателем, которые они могли использовать для управления воспроизведением, одновременно сосредотачиваясь на других задачах.

Снимок экрана основного окна Spotify Miniplayer.

Это позволило Spotify иметь базовый мини-плеер. Однако этот подход имел ряд ограничений:

  • Субтитры видео не поддерживаются в окне PiP. Поскольку Spotify требовалось показывать субтитры на всех видео, они были вынуждены закрыть окно PiP, как только видео начало воспроизводиться.
  • Элементы управления проигрывателем видны только в том случае, если воспроизведение происходит локально. Spotify позволяет удаленное воспроизведение с помощью Spotify Connect (и других протоколов) и хочет, чтобы пользователь также мог управлять этим воспроизведением.
  • Нет поддержки настройки внешнего вида окна PiP. Spotify мог отображать только изображения и использовать элементы управления проигрывателем, предоставляемые Chrome, что не позволяло им добавлять фирменный стиль Spotify или дополнительные элементы управления проигрывателем.

Отсутствие контроля над пользовательским интерфейсом и невозможность добавить сюда определенные функции Spotify (например, лайк трека) означали, что они не считали этот подход подходящим для их настольного клиента.

Документ «Картинка в картинке»: эволюция миниплеера

В начале 2023 года Spotify узнал о возобновлении интереса Google Chrome к запуску нового API, который позволил бы отображать произвольный HTML-контент внутри окна PiP, известного как API Document Picture-in-Picture . Эта разработка была интересна для Spotify, поскольку она давала им полный контроль над внешним видом окна PiP. Spotify сотрудничал с командой Chrome во время пробной версии Origin для разработки нового мини-плеера, основанного на API Document Picture-in-Picture.

API Document PiP позволяет открыть новое окно, которое всегда находится сверху, к которому можно прикреплять элементы. Поскольку веб-плеер Spotify является веб-приложением React, Spotify использовал метод createPortal() ReactDOM для рендеринга пользовательских компонентов в окно PiP из основного приложения, предоставляя полный контроль над внешним видом и функциями миниплеера.

Новый API Document Picture-in-Picture также решил предыдущие проблемы Spotify:

  • Видео внутри окна PiP представляют собой обычные видеоэлементы и полностью поддерживают субтитры.
  • Благодаря полному контролю над пользовательским интерфейсом элементы управления проигрывателя могут отображаться даже при удаленном воспроизведении с помощью Spotify Connect.
  • Spotify удалось интегрировать их внешний вид и элементы управления проигрывателем, что повысило удобство использования.
  • Им удалось обеспечить поддержку Document PiP API в клиенте Spotify для настольных компьютеров, что позволило им предоставить Miniplayer миллионам пользователей настольных компьютеров.

Снимок экрана нового окна Spotify Miniplayer.

Создайте окно «картинка в картинке» с помощью React

В следующем примере показано, как вы можете использовать документ «Картинка в картинке» в React, как это сделала команда Spotify. Вы создадите два компонента React: MyFeature и PiPContainer .

Компонент MyFeature отвечает за управление окном «Картинка в картинке». Он отображает кнопку, которая переключает окно «Картинка в картинке», и отображает компонент PiPContainer . Он также подписывается на событие "pagehide" чтобы обновлять состояние при закрытии окна.

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

Компонент PiPContainer использует метод createPortal() ReactDOM для рендеринга контента в окно «картинка в картинке».

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

Что дальше

Поскольку Spotify продолжает развиваться и внедрять инновации, они по-прежнему стремятся совершенствовать Miniplayer и планируют и дальше совершенствовать его функции и удобство для пользователей. Хотя они еще не могут остановиться на конкретных функциях, они воодушевлены будущими возможностями миниплеера.

Снимок экрана с различными формами окна Spotify Miniplayer.

API Document Picture-in-Picture обеспечивает гибкость и контроль для создания более интуитивно понятного и удобного для пользователя мини-плеера. Мы надеемся, что другие поставщики браузеров обратят внимание на возможности, которые предлагает этот API, и рассмотрят возможность включения его поддержки. Это позволит Spotify обеспечить единообразный и расширенный опыт для всех пользователей, независимо от выбранного ими браузера.

Благодарности

Спасибо всем в Spotify, кто участвовал в создании миниплеера.

Spotify также хотел бы поблагодарить команду Google Chrome за сотрудничество и за то, что они приняли во внимание отзывы Spotify для API Document Picture-in-Picture.