Player

지금 사용 중인 영상은 그대로. 백엔드를 연결하고, 재생 명령 경로와 플레이어 태그를 적용하세요.

1. 기존 영상에서 연동까지

기존 영상이 https://vod.myedu.com/clip.mp4인 경우를 예로 들겠습니다. 아래 도메인은 설명을 위한 예시이며, 실제 연결 시에는 발급받은 서비스 도메인을 사용하세요.

① 지금 사용 중인 영상

기존 페이지에서는 원본 MP4 주소를 <video>에 넣어 재생하고 있습니다.

<video
  src="https://vod.myedu.com/clip.mp4"
  controls playsinline>
</video>

② 비디오 플라이 백엔드 연결

기존 웹서버·스토리지를 백엔드로 연결하면, 같은 영상을 VideoFly 서비스 도메인으로 접근할 수 있습니다. 파일 경로 /clip.mp4는 그대로 유지합니다.

기존 원본https://vod.myedu.com/clip.mp4
백엔드 연결 후https://vod.myedu.edge.videofly.co.kr/clip.mp4

③ 주소 끝에 재생 명령 경로 추가

백엔드 연결 후의 영상 주소 뒤에 /vfly/v1/vod/_default/master.m3u8를 붙입니다. 호스트 변경만으로 끝나는 것이 아니라, 이 명령 경로까지 포함한 주소가 플레이어에 넣을 재생 URL입니다.

최종 재생 URL https://vod.myedu.edge.videofly.co.kr/clip.mp4/vfly/v1/vod/_default/master.m3u8

clip.mp4를 지우거나 master.m3u8로 바꾸지 않습니다. 원본 파일명 뒤에 명령 경로를 이어 붙입니다.

추가하는 부분의미
/vfly/v1/vod/VideoFly의 주문형 비디오 재생 명령
_default기본 프로파일
/master.m3u8플레이어가 읽을 HLS 마스터 플레이리스트

④ 스크립트와 최종 플레이어 태그 적용

스크립트를 먼저 로드하고, 기존 <video>를 <vfly-player>로 바꿉니다. src에는 위에서 완성한 재생 URL을 넣으세요. 아래 예제 전체를 복사해 적용할 수 있습니다.

<script src="https://assets.videofly.co.kr/player/v1/vfly-player.js"></script>

<vfly-player
  src="https://vod.myedu.edge.videofly.co.kr/clip.mp4/vfly/v1/vod/_default/master.m3u8"
  rendition="720p"
  controls playsinline>
</vfly-player>

controls는 재생 버튼과 화질 메뉴를 표시합니다. 자동재생이 필요하면 muted autoplay를 함께 추가하세요. 스크립트 로드만으로 태그가 등록되며 전역 VflyPlayer도 사용할 수 있습니다.

동작 확인

console.log(VflyPlayer.version);

const player = document.querySelector('vfly-player');
player.addEventListener('engine-ready', (event) => {
  console.log(event.detail.rendition, event.detail.renditions);
});

2. 왜 이 플레이어인가

어디서든 재생

브라우저에 맞는 재생 엔진을 자동 선택하고, 단말이 못 트는 형식은 호환 형식으로 바꿔 보냅니다. engine="auto" 가 기본입니다.

보는 만큼만 전송

화면에 보일 때만 로드하고, 벗어나면 멈춥니다. 재생 직전 구간은 미리 준비해 둡니다. viewport · prewarm 이 기본으로 켜져 있습니다.

첫 화면은 바로

720p 로 바로 시작하고, 단말과 회선에 맞춰 화질을 자동으로 올립니다. rendition · abr.

3. 자주 쓰는 속성

속성기본값설명
src—필수. 프로파일이 포함된 HLS 재생 URL. 예: …/clip.mp4/vfly/v1/vod/_default/master.m3u8master 지정 시 시작 화질 확정. rendition playlist 직접 지정 시 단일 화질 재생, rendition 속성 무시
rendition720p시작 화질 {N}p (짧은 변 기준). 정확히 없으면 아래 → 위 순으로 맞춤재생 중에는 바뀌지 않음
min-rendition
max-rendition
—화질 목록 범위. 메뉴 · 수동 선택 · 시작 화질 · 자동 전환 모두 이 안에서재생 중 바꾸면 즉시 반영
poster자동로딩 전 표시 이미지. 미지정 시 시작 시각의 capture 이미지 사용명령 경로에서 원본 URL 경계를 찾을 수 있을 때 자동 생성. 직접 지정하면 해당 이미지 URL 사용
controlsfalse컨트롤 UI. 기본은 네이티브 <video> 와 같이 없음, 켜면 표준 스킨
autoplay · mutedfalse자동재생은 muted 와 함께. 소리 있는 자동재생은 브라우저가 막을 수 있음
loopfalse반복 재생. 재생 중 추가 · 제거해도 즉시 반영
viewporton;distance=100vh보일 때만 로드. distance 로 선행 로드 거리 조절, off 면 일반 <video> 와 같음

4. 전체 레퍼런스

속성 전체
속성기본값설명
min-auto-rendition
max-auto-rendition
—자동 전환(ABR) 범위. 위 목록 범위 안에서 자동 전환만 좁힘. 수동 선택은 묶이지 않음
sprite비활성탐색 바 썸네일 미리보기 {interval}/{size} (예: 5/320x180)
keywordvflysrc에서 원본 URL을 추출하는 경계 키워드. sprite URL 조립에 사용
preloadcontrols 연동none · metadata · auto. 미지정이면 controls 가 켜질 때 metadata, 아니면 none
playsinlinetrue인라인 재생. iPhone 전체화면 강제 진입 방지. "false" 면 네이티브 기본
disableRemotePlaybackfalseAirPlay · Cast 차단
prewarmtrue재생 앞 구간을 미리 요청해 준비. "false" 로 끔. 요청 방식 지정 가능 (GET · HEAD · GET:<range>)
abrtrue자동 화질 전환. 응답 지연을 보고 내리고 올림. 직접 재생 엔진에서만 동작
engineautoauto 는 브라우저에 맞게 자동, native 는 내장 HLS 강제 (미지원이면 VFLY_ENGINE_UNSUPPORTED)
  • 속성은 초기화 때 한 번 읽습니다. 재생 중 바로 반영되는 것은 src(재로드) · 화질 범위 4속성 · loop. 나머지는 다음 로드부터.
  • src 뒤에 #t=시작,종료 를 붙이면 구간 재생. 서버 요청 URL 에는 붙지 않습니다.
  • 구간 재생 예: …/master.m3u8#t=10,45. 10초부터 45초까지 재생하며, 종료 구간에서는 loop가 있어도 반복하지 않습니다.
  • 화질 범위를 연달아 변경하면 한 번에 적용합니다. 범위 안에 단계가 없으면 min 이상 최소 단계, 그것도 없으면 max 이하 최대 단계 하나를 선택합니다. rendition playlist 직접 지정 시 범위 설정은 무시합니다.
  • controls·playsinline: 속성만 쓰면 true, "true"·"false"는 해당 값, 오타는 기본값으로 처리합니다. disableRemotePlayback은 프로퍼티로 대입하면 즉시 반영합니다.
  • 화질 범위 값이 잘못되면 로드 시점에는 치명 오류, 재생 중에는 직전 범위를 유지합니다.
이벤트 · 오류 코드

발행은 CustomEvent, 내용은 event.detail.

이벤트발생 시점detail
engine-ready재생 준비 완료engine · renditions(선택 가능 화질) · rendition(확정 화질)
engine-error오류code · detail · fatal. 비치명 오류도 발행되므로 fatal 로 거름
renditionchange자동 화질 전환from · to · reason (down-emergency · down-planned · down-error · up · range)
renditionlistchange선택 가능 화질 목록 변경renditions
코드의미fatal
VFLY_ENGINE_UNSUPPORTED재생 환경 미지원true
VFLY_MANIFEST_ERROR매니페스트 파싱 실패 · 화질 목록 공백 · 화질 범위 형식 오류true (재생 중 범위 오류는 false)
VFLY_NETWORK_ERROR매니페스트 · 세그먼트 로드 실패상황별
VFLY_MEDIA_ERROR디코드 실패 · 코덱 재생 불가상황별
VFLY_UNKNOWN_ERROR분류 불가상황별

rendition playlist 직접 지정 시 engine-ready의 rendition은 null입니다. renditionchange는 초기·수동 선택에는 발행하지 않고 자동 전환과 재생 중 범위 변경에 발행합니다. 목록 변경 시에는 renditionlistchange가 먼저 발행됩니다.

play · pause · timeupdate 같은 표준 이벤트는 다시 발행하지 않습니다. 내부 <video> 에서 직접 듣습니다.

const video = player.video;
video.addEventListener('timeupdate', () => {
  console.log(video.currentTime);
});
동작 상세
  • preload — 네이티브와 같은 뜻. none 은 재생 시도까지 로드를 미루고 engine-ready 도 그때 발행. autoplay 면 실제 노출 전에 metadata 만 미리 준비.
  • autoplay — 소리 있는 자동재생은 브라우저가 거부할 수 있고, 거부돼도 오류 없이 일시정지 상태로 둡니다.
  • viewport — 뷰포트 밖이면 포스터만 보이고 로드는 distance 만큼 앞서 시작. 재생 중 벗어나면 정지 · 로딩 중단, 다시 들어오면 이어서. 사용자가 직접 정지한 것은 자동으로 재개하지 않습니다. PiP 는 보이는 것으로 칩니다.
  • 노출과 자동재생 — distance는 초기 선행 로드에만 적용하며 자동재생은 실제 노출 시 시작합니다. 노출 전 pause()는 자동재생을 취소합니다. IntersectionObserver 미지원 시 즉시 로드합니다.
  • 화질 선택 — controls 가 켜져 있으면 설정 메뉴에 Quality 가 보이고, 범위 안의 재생 가능 화질만 나열. 자동(Auto) 은 abr 이 켜진 직접 재생에서만. 수동 전환은 재생 위치와 상태를 유지합니다.
  • sprite — 지정하면 탐색 바에 구간 썸네일. 로드 실패 시 미리보기만 꺼지고 재생에는 영향 없음.
  • 이미지 경로 — poster는 {원본 URL}/{keyword}/v1/vod/capture/{시작 시각}/1280x720.jpg, sprite는 {원본 URL}/{keyword}/v1/vod/sprite/{interval}/{size}.vtt로 구성합니다.
  • 프리워밍 요청 — 직접 재생과 네이티브 경로를 세미콜론으로 구분해 지정할 수 있습니다. 예: prewarm="GET;GET:0-0". attachTo 옵션은 { prewarm: { enable, method } }입니다.
master 요청과 전체 화질 목록 · ladder=full

직접 재생(hls.js·MMS)에서는 명령 경로가 포함된 master.m3u8 요청에 ladder=full을 자동으로 더해 전체 화질 후보를 확인합니다. 따라서 기본 연동 예제에서는 이 쿼리를 직접 추가할 필요가 없습니다.

  • 조건: /{keyword}/v1/vod/ 경계가 있고, 마지막 경로가 정확히 master.m3u8이며, 기존 쿼리에 ladder가 없는 경우.
  • …/master.m3u8 → …/master.m3u8?ladder=full. 기존 쿼리는 유지하며 &ladder=full을 붙입니다.
  • 네이티브 HLS 경로는 src 그대로 요청합니다. 자동 추가를 끄려면 ?ladder=m2ts처럼 ladder를 명시하세요.
  • master 요청은 load당 1건입니다. 요청 실패 시 재시도하지 않고 치명 VFLY_NETWORK_ERROR를 알립니다.
  • src 속성·프로퍼티와 poster·sprite 계산 기준은 원래 주소를 유지합니다.
재생 품질 수집 · CMCD

CMCD v2 이벤트 모드로 재생 품질을 수집 서버에 보고합니다. 수집 대상을 지정해야 켜지며, 단순히 플레이어를 배치하는 것만으로 수집이 시작되지는 않습니다.

VflyPlayer.cmcd = {
  targets: [{
    url: 'https://collect.example.com/cmcd',
    collectKey: 'k1',
  }],
};
  • 위 수집 서버 주소와 키는 예시입니다. 실제 수집 서버 주소·키를 설정하고 플레이어를 로드하세요.
  • 전역 VflyPlayer.cmcd 또는 attachTo(video, { cmcd })에서 설정합니다. 인스턴스 설정이 우선하며, <vfly-player>에는 전용 속성 없이 전역 설정을 적용합니다.
  • targets 항목: url, collectKey, events(기본 ps·e·bc·t·rr·ce), interval(기본 30초), batchSize(기본 5).
  • 추가 설정: enable, metadata(viewerId·playerName·experiment), topPlayableBitrate, request(query·header 모드와 keys), loader.
  • 설정은 load 시점에 반영합니다. 재생 중 변경은 다음 load부터 적용하며 load마다 새 세션(sid)을 만듭니다.

5. JS API · React

직접 만든 <video> 에 붙이는 명령형 표면. <vfly-player> 와 동작이 같습니다. 위의 스크립트를 먼저 로드한 뒤 실행하세요.

const player = VflyPlayer.attachTo(videoElement, {
  src: 'https://vod.myedu.edge.videofly.co.kr/clip.mp4/vfly/v1/vod/_default/master.m3u8',
  rendition: '720p',
});

player.on('renditionchange', (d) => console.log(d.from.name, '→', d.to.name, d.reason));
player.on('engine-error', (detail) => {
  if (detail.fatal) console.error(detail.code);
});
멤버설명
VflyPlayer.attachTo(video, options)플레이어 부착 · 인스턴스 반환. options.src 가 있으면 즉시 로드
VflyPlayer.version산출물 버전 문자열
VflyPlayer.react(R)React 컴포넌트 반환. R 은 호출자의 React (플레이어는 React 를 번들하지 않음)
player.load(src) · play() · pause()새 URL 로드 · 재생 · 일시정지
player.on(event, handler) · off()이벤트 구독 · 해제. on 은 해제 함수를 반환
player.renditions · selectVideoRendition(name)현재 선택 가능 화질 목록 · 수동 전환
player.minRendition 등 범위 4종화질 범위 get/set. 재생 중 반영
player.video내부 <video> (읽기 전용)
player.destroy()엔진 해제 · 리스너 정리. 이후 재사용 불가
player.loop반복 재생 get/set, 즉시 반영. load 뒤에도 유지하며 destroy 시 원래 값으로 복원
player.disableRemotePlayback원격 재생 차단 get/set, 즉시 반영
player.abr자동 화질 전환 get/set, 기본 true. 변경은 다음 load부터 적용
VflyPlayer.abrABR 정책 전역 설정(a·backoff·upBwFactor·healthFactor·healthSegs 등), load 시점 스냅샷
VflyPlayer.prewarm프리워밍 동시성 전역 설정. bootFetchLimit 기본 3, runFetchLimit 기본 2. load 시점 스냅샷
VflyPlayer.cmcd재생 품질 수집 전역 설정. 위 CMCD 안내 참조

<vfly-player> 요소에서도 같은 제어를 쓸 수 있습니다. play() · pause() · togglePaused() · seek(t) · setVolume(v) · toggleMuted() · setPlaybackRate(r) · loadSource(src) · selectVideoRendition(value) · requestFullscreen() · requestPictureInPicture()와 모든 속성의 프로퍼티를 제공합니다. 예: el.minRendition = '480p'. 수동 화질 선택값은 renditions[].name이며 무효 값은 무시합니다.

React

전역 VflyPlayer 로 컴포넌트를 만듭니다. props 는 react-hls-player 와 같은 모양입니다. 스크립트는 <head> 에, 앱 번들보다 앞에, async · defer 없이 둡니다.

import React from 'react';
export default window.VflyPlayer.react(React);
import { useRef } from 'react';
import HlsPlayer from './HlsPlayer';

function App() {
  const playerRef = useRef(null);
  return (
    <HlsPlayer
      src="https://vod.myedu.edge.videofly.co.kr/clip.mp4/vfly/v1/vod/_default/master.m3u8"
      playerRef={playerRef}
      autoPlay muted playsInline
      options={{ rendition: '480p' }}
      onEngineReady={(d) => console.log(d.engine)}
    />
  );
}
  • React 에서는 <vfly-player> 태그를 쓰지 않습니다. React 18 이 미디어 이벤트를 전달하지 않고 muted={false} 를 켬으로 적기 때문입니다.
  • SSR(Next.js 등) 에서는 서버가 빈 <video> 를 그리고 클라이언트가 같은 자리에 붙입니다. 스크립트는 beforeInteractive 로 로드합니다.
  • src·autoPlay는 attachTo로 전달하며 내부 video 속성에 직접 넣지 않습니다. options는 src를 제외한 attachTo 옵션입니다. hls.js 설정은 options.hls에 지정합니다.
  • vflyRef로 인스턴스를 받을 수 있습니다. onEngineReady·onEngineError·onRenditionChange·onRenditionListChange·onTrace로 엔진 이벤트를 연결하며, 핸들러 교체만으로 재부착하지 않습니다.
  • src·autoPlay·options 내용·preload·poster·onTrace 유무를 변경하면 재부착합니다. React StrictMode의 이중 effect는 정상 동작입니다.
  • 같은 부모에서 플레이어 바로 앞 형제를 조건부 렌더링한다면 플레이어를 별도 div로 감싸세요. video에 높이 100% 등의 스타일을 지정했다면 vfly-player에도 적용하세요.
SSR · Next.js용 컴포넌트 예제

서버에서 window를 읽지 않도록 렌더 시점에 전역 플레이어를 확인합니다. 서버는 src 없는 video를 출력하고 클라이언트는 같은 위치에 플레이어를 붙입니다.

'use client';
import React, { useMemo } from 'react';

export default function HlsPlayer(props) {
  const Player = useMemo(
    () => (typeof window !== 'undefined'
      ? window.VflyPlayer.react(React) : null),
    [],
  );
  if (!Player) {
    const { src, playerRef, ...rest } = props;
    return <video ref={playerRef} {...rest} />;
  }
  return <Player {...props} />;
}

Next.js에서는 아래 Script를 루트 레이아웃에 배치해 앱보다 먼저 로드하세요.

import Script from 'next/script';

<Script
  src="https://assets.videofly.co.kr/player/v1/vfly-player.js"
  strategy="beforeInteractive"
/>

내 영상으로 플레이어 태그 만들어 보기: Demo › 05 서비스 적용