Classic/VPC 환경에서 이용 가능합니다.
OTT 서비스에 필요한 인트로/오프닝/엔딩 스킵, 연령 등급 표시, 콘텐츠 경고 기능을 제공합니다. 각 기능은 playlist 아이템 단위로 설정합니다.
인트로/오프닝/엔딩 스킵
각 playlist 아이템에 intro, opening, ending 구간을 지정하면 해당 시점에 스킵 버튼이 자동으로 표시됩니다.
옵션
모든 스킵 옵션은 playlist[] 아이템에 설정합니다.
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
intro |
{ start: string; duration: number } |
undefined |
인트로 구간. 재생 시작 시 스킵 버튼 표시 |
opening |
{ start: string; duration: number } |
undefined |
오프닝 구간. 해당 구간에 진입하면 자동 스킵 또는 스킵 버튼 표시 |
ending |
{ start: string; duration: number } |
undefined |
엔딩 구간. 해당 구간에 진입하면 자동 스킵 또는 스킵 버튼 표시 |
각 구간 객체의 필드는 다음과 같습니다.
| 필드 | 타입 | 설명 |
|---|---|---|
start |
String | 구간 시작 시점. "HH:MM:SS" 형식 (예: "00:00:05", "00:01:30" |
duration |
Integer | 구간 지속 시간 (초) |
타입 정의
// playlist 아이템 구조
{
file: "string",
poster: "string",
// ... 기타 속성
// OTT 스킵 구간
intro: { start: "HH:MM:SS", duration: number },
opening: { start: "HH:MM:SS", duration: number },
ending: { start: "HH:MM:SS", duration: number },
}
기본 사용 예제
const player = new ncplayer("player", {
autostart: true,
muted: true,
playlist: [
{
file: "https://CDN_DOMAIN/episode_01.m3u8",
poster: "https://CDN_DOMAIN/episode_01.jpg",
intro: {
start: "00:00:00",
duration: 5,
},
opening: {
start: "00:00:05",
duration: 90,
},
ending: {
start: "00:45:00",
duration: 60,
},
},
],
});
동작 방식
오프닝/엔딩 구간은 자동 스킵을 지원합니다. 동작 방식은 다음과 같습니다.
- 사용자가 직접 seek하여 오프닝/엔딩 구간에 진입한 경우, 자동 스킵이 우회됩니다.
- 내부 스킵(인트로 스킵 등)으로 오프닝 구간에 진입한 경우, 자동 스킵이 유지됩니다.
스킵 버튼 UI는 컨트롤 바 표시 여부와 무관하게 고정 오버레이로 렌더링되며, center 레이아웃 하단 오프셋 기준으로 위치가 동기화됩니다.
스킵 이벤트
각 구간이 스킵되면 다음 이벤트가 발생합니다. on() 메서드로 수신할 수 있습니다.
| 이벤트 | 설명 |
|---|---|
introSkip |
인트로 구간이 스킵되었을 때 발생 |
openingSkip |
오프닝 구간이 스킵되었을 때 발생 |
endingSkip |
엔딩 구간이 스킵되었을 때 발생 |
const player = new ncplayer("player", {
playlist: [
{
file: "https://CDN_DOMAIN/episode_01.m3u8",
intro: { start: "00:00:00", duration: 5 },
opening: { start: "00:00:05", duration: 90 },
ending: { start: "00:45:00", duration: 60 },
},
],
});
player.on("introSkip", function() {
console.log("인트로 스킵됨");
});
player.on("openingSkip", function() {
console.log("오프닝 스킵됨");
});
player.on("endingSkip", function() {
console.log("엔딩 스킵됨");
});
연령 등급 표시
playlist 아이템의 ageRating 값을 설정하면 재생 시작 후 연령 등급 오버레이가 자동으로 표시됩니다.
지원 등급
| 값 | 설명 | i18n 키 |
|---|---|---|
"all" |
전체 관람가 | ageRating.noticeAll |
"12" |
12세 이상 관람가 | ageRating.notice12 |
"15" |
15세 이상 관람가 | ageRating.notice15 |
"19" |
19세 이상 관람가 (청소년 관람 불가) | ageRating.notice19 |
오버레이 동작
- 재생 시작 후 3초 경과 시 1회 노출됩니다.
- fade + slide 모션으로 표시됩니다.
- 상단에 검정 그라데이션(
opacity 0.3 → 0)이 적용됩니다. - 다국어를 지원합니다. 지원 언어는
ko,en,ja입니다.
기본 사용 예제
const player = new ncplayer("player", {
autostart: true,
muted: true,
playlist: [
{
file: "https://CDN_DOMAIN/episode_01.m3u8",
poster: "https://CDN_DOMAIN/episode_01.jpg",
description: {
title: "드라마 시즌1 EP.01",
profile_name: "OTT 채널",
},
ageRating: "15",
},
],
});
콘텐츠 경고
playlist 아이템의 contentWarnings 배열을 설정하면 재생 시작 시 해당 콘텐츠에 포함된 민감한 요소를 시청자에게 안내하는 경고 오버레이가 표시됩니다.
지원 경고 유형
| 값 | 설명 |
|---|---|
"sexuality" |
선정성 |
"violence" |
폭력성 |
"language" |
언어(욕설/비속어) |
"drugs" |
약물 |
"horror" |
공포 |
"imitation" |
모방 위험 |
"provocative" |
선정적 자극 |
위 7개가 권장 키이며, 임의의 문자열도 사용할 수 있습니다.
기본 사용 예제
const player = new ncplayer("player", {
autostart: true,
muted: true,
playlist: [
{
file: "https://CDN_DOMAIN/episode_01.m3u8",
poster: "https://CDN_DOMAIN/episode_01.jpg",
contentWarnings: ["violence", "language"],
},
],
});
종합 예제
인트로/오프닝/엔딩 스킵, 연령 등급 표시, 콘텐츠 경고를 모두 적용한 예제입니다.
const player = new ncplayer("player", {
autostart: true,
muted: true,
playlist: [
{
file: "https://CDN_DOMAIN/episode_01.m3u8",
poster: "https://CDN_DOMAIN/episode_01.jpg",
description: {
title: "드라마 시즌1 EP.01",
profile_name: "OTT 채널",
},
ageRating: "15",
contentWarnings: ["violence", "language"],
intro: {
start: "00:00:00",
duration: 5,
},
opening: {
start: "00:00:05",
duration: 90,
},
ending: {
start: "00:45:00",
duration: 60,
},
},
{
file: "https://CDN_DOMAIN/episode_02.m3u8",
poster: "https://CDN_DOMAIN/episode_02.jpg",
description: {
title: "드라마 시즌1 EP.02",
profile_name: "OTT 채널",
},
ageRating: "15",
contentWarnings: ["violence"],
intro: {
start: "00:00:00",
duration: 5,
},
opening: {
start: "00:00:05",
duration: 90,
},
ending: {
start: "00:45:00",
duration: 60,
},
},
],
});
// 스킵 이벤트 처리
player.on("introSkip", function() {
console.log("인트로 스킵됨");
});
player.on("openingSkip", function() {
console.log("오프닝 스킵됨");
});
player.on("endingSkip", function() {
console.log("엔딩 스킵됨 — 다음 에피소드로 이동");
// player.next();
});