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.mp4https://vod.myedu.edge.videofly.co.kr/clip.mp4③ 주소 끝에 재생 명령 경로 추가
백엔드 연결 후의 영상 주소 뒤에 /vfly/v1/vod/_default/master.m3u8를 붙입니다. 호스트 변경만으로 끝나는 것이 아니라, 이 명령 경로까지 포함한 주소가 플레이어에 넣을 재생 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 속성 무시 |
rendition | 720p | 시작 화질 {N}p (짧은 변 기준). 정확히 없으면 아래 → 위 순으로 맞춤재생 중에는 바뀌지 않음 |
min-renditionmax-rendition | — | 화질 목록 범위. 메뉴 · 수동 선택 · 시작 화질 · 자동 전환 모두 이 안에서재생 중 바꾸면 즉시 반영 |
poster | 자동 | 로딩 전 표시 이미지. 미지정 시 시작 시각의 capture 이미지 사용명령 경로에서 원본 URL 경계를 찾을 수 있을 때 자동 생성. 직접 지정하면 해당 이미지 URL 사용 |
controls | false | 컨트롤 UI. 기본은 네이티브 <video> 와 같이 없음, 켜면 표준 스킨 |
autoplay · muted | false | 자동재생은 muted 와 함께. 소리 있는 자동재생은 브라우저가 막을 수 있음 |
loop | false | 반복 재생. 재생 중 추가 · 제거해도 즉시 반영 |
viewport | on;distance=100vh | 보일 때만 로드. distance 로 선행 로드 거리 조절, off 면 일반 <video> 와 같음 |
4. 전체 레퍼런스
속성 전체
| 속성 | 기본값 | 설명 |
|---|---|---|
min-auto-renditionmax-auto-rendition | — | 자동 전환(ABR) 범위. 위 목록 범위 안에서 자동 전환만 좁힘. 수동 선택은 묶이지 않음 |
sprite | 비활성 | 탐색 바 썸네일 미리보기 {interval}/{size} (예: 5/320x180) |
keyword | vfly | src에서 원본 URL을 추출하는 경계 키워드. sprite URL 조립에 사용 |
preload | controls 연동 | none · metadata · auto. 미지정이면 controls 가 켜질 때 metadata, 아니면 none |
playsinline | true | 인라인 재생. iPhone 전체화면 강제 진입 방지. "false" 면 네이티브 기본 |
disableRemotePlayback | false | AirPlay · Cast 차단 |
prewarm | true | 재생 앞 구간을 미리 요청해 준비. "false" 로 끔. 요청 방식 지정 가능 (GET · HEAD · GET:<range>) |
abr | true | 자동 화질 전환. 응답 지연을 보고 내리고 올림. 직접 재생 엔진에서만 동작 |
engine | auto | auto 는 브라우저에 맞게 자동, 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.abr | ABR 정책 전역 설정(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 서비스 적용