11. 비디오 플레이어 🎞

EEuglena·2023년 8월 7일
1

JavaScript30

목록 보기
12/27
post-thumbnail

목표

비디오 플레이어의 컨트롤러 기능을 직접 구현해 보자.

구현할 기능

  • 재생/정지: ▶/|| 버튼 및 화면 클릭으로 재생 및 일시정지 할 수 있다.
  • 스크러빙: 시간 막대를 클릭하여 원하는 위치로 이동하거나 드래그하여 장면을 연속적으로 살펴볼 수 있다.
  • 음량: 음소거 버튼으로 음소거를 적용하고 해제할 수 있고, 음량 막대를 드래그하여 음량을 설정할 수 있다.
  • 재생 속도: 속도 막대를 드래그하여 재생 속도를 조절할 수 있고, 초기화 버튼으로 원래 속도로 되돌릴 수 있다.
  • 탐색: 앞으로 10초/뒤로 10초 버튼으로 각각 10초씩 이동할 수 있다.

레이아웃 만들기

제목, 비디오, 컨트롤러 영역을 구분해 만들었다. 컨트롤 패널에는 버튼과 range 타입의 input을 기능에 맞게 배치했다.

재생 / 정지

재생 버튼 또는 화면을 클릭했을 때 영상이 정지 상태라면 재생하고, 재생 중이라면 정지한다.

비디오가 재생되거나 중지되면 이벤트가 발생하는데, 이를 각각 감지하여 재생 버튼의 아이콘을 바꿔 주었다.

프로그레스 바

프로그레스 바는 range 타입의 input이다. input은 값이 바뀔 때마다 input 이벤트를 발생시키는데, 이를 감지하여 영상의 시간을 이동하였다. 반대로 영상의 시간이 바뀌었을 때도 input에 반영되도록 하였다.

또한 0:00 / 0:00 형식의 타임스탬프도 영상 시간에 따라 재설정되도록 했다. 영상의 현재 위치를 나타내는 currentTime과 영상의 길이를 나타내는 duration은 초 단위의 실수이기 때문에 이에 유의하여 값을 변환해야 한다.

영상 길이는 video.duration으로 받아올 수 있는데, 메타데이터를 불러오기 전에 해당 값은 NaN으로 표시된다. 그래서 메타데이터를 로드했을 때 발생하는 loadedmetadata 이벤트를 이용해서 영상 길이를 불러오면 된다.

음량

음소거 버튼을 통해 음소거를 적용하고 해제할 수 있도록 했다. 음소거 기능만이라면 video.muted = !video.muted로 한 줄만 있어도 됐겠지만 버튼의 아이콘을 바꿔야 하기 때문에 if~else 문을 사용했다.

음량도 input[type="range"]를 이용해서 직접 변경할 수 있다. video.volume으로 [0, 1]의 값을 전달하면 음량을 설정할 수 있다. 여기에 더해 크롬의 기본 플레이어는 음량이 0인 상태를 음소거로 간주하는 추가 로직이 들어가는데, 음량과 음소거를 별개로 처리하는 게 사용하기 더 직관적일 것 같아 이는 제외했다.

재생 속도

보통 비디오 플레이어는 0.5x, 1x, 2x 등의 속도 프리셋을 주고 선택하는 방식이지만 원하는 값을 직접 선택할 수 있게 만들고 싶어서 input[type="range"]를 이용해서 구현했다.

input의 값을 변경해서 배속을 조정하거나 초기화 버튼을 눌러서 1배속으로 돌아올 수 있다. 재생 속도는 video.playbackRate로 조절할 수 있고, 정상 속도에 대한 배율로 계산된다. 값을 처리할 때 2에 대한 로그 스케일로 반영되도록 했는데, 1배속을 기준으로 2배속과 0.5배속이 대칭을 이루도록 하고 싶었기 때문이다. 또 막대 형식으로 값을 조절하면 정확히 얼마인지 알기 힘들기 때문에 "1.0x"와 같은 형식의 레이블로 명시해 주었다.

탐색

탐색 버튼을 이용해 10초 단위로 앞 혹은 뒤로 이동할 수 있다.

CSS 작성

컨트롤 패널은 평소에는 보이지 않다가 플레이어에 커서를 올리면 살짝 올라오면서 나타나도록 하였다.

프로그레스 바에 스타일을 입히기 위해서는 기존 스타일을 해제해야 한다. appearance를 none으로 설정하면 프리셋을 해제할 수 있다. 크롬에서 개발하고 있기 때문에 벤더는 -webkit만 설정했고, slider-runnable-track으로 전체 스크롤 바를, slider-thumb으로 움직이는 막대 부분을 커스터마이즈 할 수 있다.

음량과 속도를 조절하는 막대는 수직으로 설정했으며, 역시 평소에는 보이지 않다가 커서를 가져갔을 때만 보이도록 했다.

완성된 컨트롤 패널의 모습은 위와 같다.

새로 알게 된 점

이번에는 video 태그를 주로 사용해 봤다. 강의에서 사용하지는 않았지만 autoplay, loop, controls 등 유용한 속성이 많았다. 플레이어와 컨트롤러를 양방향으로 연결해줘야 해서 꽤나 번거로웠다.

JS에서는 필요한 속성이 뭔지 검색하는 시간이 좀 걸렸을 뿐 어려운 건 딱히 없었는데 CSS에서 많이 헤맸다. 슬라이드 바 위치를 버튼 위에 배치하기 위해 position: absolute;를 이용했는데, absolute와 relative가 어떻게 작동하는지 정확히 알지 못해서 계속 이상한 모양으로 나왔다. 어떻게 만들기는 했는데, 결과물도 flex와 absolute가 섞인 이상한 형태라서 내가 한 게 맞는 건지도 잘 모르겠다.

input[type="range"] 스타일링도 복잡했다. track과 thumb를 각각 디자인해야 하기도 하고, thumb는 위치도 직접 지정해줘야 해서 시행착오 과정이 길었다. 강의에서는 input이 아니라 div를 이용해서 만들었는데, 진행률에 따른 시각적 변화를 주고 싶으면 이렇게 하는 게 더 좋을 것 같긴 하다.

그리고 유튜브를 보면 스크럽 중에 위나 아래로 끌어서 탐색 배속을 조절하고 프레임별로 볼 수 있는 기능도 있는데 이런 건 어떻게 만들 수 있는지 궁금하다.

소스 코드

Visit Github Repository

0개의 댓글