Spotify가 Picture-in-Picture API를 사용하여 Spotify 소형 플레이어를 빌드한 방법

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

전 세계에서 가장 인기 있는 오디오 스트리밍 구독 서비스인 Spotify는 사용자가 오디오 및 동영상 콘텐츠를 소비하는 방식을 개선하기 위해 지속적으로 노력하고 있습니다. 광범위한 음악, 팟캐스트, 오디오북 라이브러리를 제공하며 모바일, PC, 기타 플랫폼에서 매일 수백만 명의 사용자에게 서비스를 제공합니다.

최근 Spotify는 데스크톱 및 웹 플레이어 클라이언트를 위한 Spotify 소형 플레이어를 출시했습니다. 소형 플레이어는 상단에 고정되는 작고 아담한 창에서 필수 재생 컨트롤을 제공하도록 설계되어 사용자가 Spotify를 계속 이용할 수 있습니다. 이 기능은 오랫동안 요청되어 온 기능으로, 사용자가 다양한 창과 앱에서 원활하게 멀티태스킹을 하면서 Spotify에서 좋아하는 아티스트, 재생목록, 팟캐스트를 즐길 수 있도록 지원합니다.

다음은 초기 '캔버스 해킹'에서부터 새로운 Document Picture-in-Picture API를 기반으로 구축된 보다 발전적이고 사용자 친화적인 버전에 이르기까지 소형 플레이어의 개발 과정을 자세히 살펴봅니다.

'캔버스 해킹'

소형 플레이어의 초기 버전은 2019년에 Spotify 웹 플레이어에서 해크 프로젝트로 출시되었습니다. 목표는 브라우저의 <video>용 PiP (Picture-in-Picture) API를 사용하여 항상 맨 위에 있는 창에 앨범 아트를 표시하는 것이었습니다. 그러나 이 API는 주로 동영상 요소를 위해 설계되었으므로 앨범 아트 이미지를 표시할 수 없습니다. Spotify는 앨범 아트를 캔버스 요소에 렌더링하고 HTMLCanvasElement captureStream() 메서드를 사용하여 실시간 MediaStream 객체를 얻는 방식으로 이를 우회했습니다. 그러면 이 스트림이 PIP API에 사용되는 동영상의 소스 역할을 합니다. 이 접근 방식은 Chrome의 '오디오 재생목록' 샘플을 기반으로 합니다.

Spotify는 캔버스를 Media Session API에 설정된 적절한 작업 핸들러와 결합하여 PIP 창에 표시되는 플레이어 컨트롤을 제어했습니다. 이를 통해 사용자는 앨범 아트와 플레이어 컨트롤이 있는 플로팅 창을 이용하여 재생을 제어하면서 다른 작업에 집중할 수 있게 되었습니다.

기본 Spotify 소형 플레이어 창의 스크린샷

이를 통해 Spotify는 기본 소형 플레이어를 포함할 수 있었습니다. 그러나 이 접근 방식에는 몇 가지 제한사항이 있었습니다.

  • PIP 창 내에서는 동영상 자막이 지원되지 않습니다. Spotify에서는 모든 동영상에 자막을 표시해야 했기 때문에 동영상이 재생되자마자 PIP 창을 닫아야 했습니다.
  • 재생 컨트롤은 로컬에서 재생되는 경우에만 표시됩니다. Spotify는 Spotify Connect (및 기타 프로토콜)를 사용한 원격 재생을 허용하며 사용자가 이 재생도 제어할 수 있기를 원합니다.
  • PIP 창의 디자인과 분위기를 맞춤설정하는 기능은 지원되지 않습니다. Spotify는 아트워크만 표시하고 Chrome에서 제공하는 재생 컨트롤을 사용할 수 있으므로 Spotify 브랜딩이나 재생 컨트롤을 추가할 수 없습니다.

사용자 인터페이스에 대한 제어 권한이 없고 여기에 Spotify 관련 기능 (예: 트랙에 좋아요 표시)을 추가할 수 없었기 때문에 이 접근 방식이 데스크톱 클라이언트에게 적합하지 않다고 느꼈습니다.

PIP 모드 문서: 소형 플레이어의 진화

2023년 초 Spotify는 PIP 창 내부에 임의의 HTML 콘텐츠를 표시할 수 있는 Document Picture-in-Picture API라는 새로운 API를 출시하려는 Chrome의 새로운 관심에 대해 알게 되었습니다. Spotify는 PIP 창을 완전히 제어할 수 있다는 점에서 이러한 발전에 흥미로웠습니다. Spotify는 오리진 트라이얼에서 Chrome팀과 협력하여 Document Picture-in-Picture API를 기반으로 구축된 새로운 소형 플레이어를 개발했습니다.

Document PIP API를 사용하면 요소를 연결할 수 있는 새로운 상시 사용 설정 창을 열 수 있습니다. Spotify Web Player는 React 웹 애플리케이션이므로 Spotify는 ReactDOM의 createPortal() 메서드를 사용하여 기본 애플리케이션에서 PIP 창으로 맞춤 구성요소를 렌더링했으며, 소형 플레이어의 모양과 기능을 완전히 제어할 수 있었습니다.

새로운 Document Picture-in-Picture API는 Spotify의 이전 문제도 해결했습니다.

  • PIP 창 안의 동영상은 일반 동영상 요소이며 자막을 완벽하게 지원합니다.
  • UI를 완전히 제어할 수 있어 Spotify Connect를 사용해 원격으로 재생이 이루어지는 경우에도 재생 컨트롤을 표시할 수 있습니다.
  • Spotify는 디자인과 분위기와 플레이어 컨트롤을 통합하여 사용자 환경을 개선할 수 있었습니다.
  • Spotify의 데스크톱 클라이언트에 Document PIP API를 지원하여 수백만 명의 데스크톱 사용자에게 소형 플레이어를 제공할 수 있게 되었습니다.

새로운 Spotify 소형 플레이어 창의 스크린샷

React를 사용하여 PIP 모드 창 만들기

다음 예는 Spotify팀과 마찬가지로 React에서 Document PIP 모드를 사용하는 방법을 보여줍니다. React 구성요소 두 개(MyFeature, PiPContainer)를 만듭니다.

MyFeature 구성요소는 PIP 모드 창을 관리합니다. PIP 모드 창을 전환하는 버튼을 렌더링하고 PiPContainer 구성요소를 렌더링합니다. 또한 PIP 모드의 "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 구성요소는 ReactDOM의 createPortal() 메서드를 사용하여 PIP 모드 창에 콘텐츠를 렌더링합니다.

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는 계속해서 발전하고 혁신을 이어감에 따라 소형 플레이어를 향상시키고 기능과 사용자 환경을 더욱 개선해 나갈 계획입니다. 아직 특정 기능을 구현할 수는 없지만 소형 플레이어의 향후 가능성에 큰 기대를 가지고 있습니다.

Spotify 소형 플레이어 창의 다양한 모양 스크린샷

Document Picture-in-Picture API는 더 직관적이고 사용자 친화적인 소형 플레이어를 만들 수 있는 유연성과 제어 기능을 제공합니다. 다른 브라우저 공급업체도 이 API가 제공하는 기회를 포착하고 이에 대한 지원을 통합하는 것을 고려하기를 바랍니다. 이를 통해 Spotify는 사용자가 선택한 브라우저와 관계없이 모든 사용자에게 일관되고 향상된 환경을 제공할 수 있습니다.

감사의 말씀

소형 플레이어 개발에 참여해주신 Spotify의 모든 분께 감사드립니다.

Spotify는 또한 협업을 돕고 Document Picture-in-Picture API에 Spotify의 의견을 반영해 주신 Chrome팀에도 감사의 말을 전합니다.