hive alpha¶
/usr/local/m2/setting.json 다음 영역에 대해 기술한다.
{
"functions": {
"contents": {
"hive": {
...
}
}
}
}
hive 는 videofly 서비스의 HLS 가공 컴포넌트다.
원본 미디어를 사전 변환 없이 요청 시점에( Just-in-time ) 세그먼트 단위로 트랜스코딩하여 서빙한다.
JIT Packaging (HLS) — 원본을
master.m3u8·playlist.m3u8와fMP4·MPEG2-TS세그먼트로 온디맨드 패키징한다. ( HLS = HTTP Live Streaming )JIT Transcoding — 세그먼트를 요청 시점에 트랜스코딩하며, 프로파일 기반 해상도 · 코덱 조합 래더를 제공한다.
Video On Demand — 프로파일 · 렌디션 단위 재생을 지원한다.
How to use¶
원본 URL 뒤에 키워드( 기본 vfly/v1/vod )와 VOD 명령어를 추가한다.
# 원본
https://example.com/video.mp4
# 원본 + 키워드(vfly/v1/vod) + 명령어
https://example.com/video.mp4/vfly/v1/vod/_default/master.m3u8
Note
클라이언트(플레이어)가 직접 구성하는 URL 은 master.m3u8 뿐이다.
렌디션 재생목록 · 세그먼트 URL 은 마스터가 발급하므로 그대로 따라가면 된다.
명령어 리스트¶
재생¶
# 빌트인 프로파일
https://example.com/video.mp4/vfly/v1/vod/_default/master.m3u8
# 고객향 프로파일
https://example.com/video.mp4/vfly/v1/vod/myprofile/master.m3u8
# 래더 선택 — ladder 쿼리스트링 (생략하면 m2ts)
https://example.com/video.mp4/vfly/v1/vod/_default/master.m3u8?ladder=fmp4
https://example.com/video.mp4/vfly/v1/vod/_default/master.m3u8?ladder=full
master.m3u8 이 노출하는 래더는 ladder 쿼리스트링으로 선택한다.
|
결과 |
|---|---|
|
MPEG2-TS 렌디션만 노출한다. |
|
fMP4 렌디션만 노출한다. |
|
fMP4 · MPEG2-TS 멀티 코덱 래더를 모두 노출한다. |
Warning
iOS · 크롬 native 재생 환경에서는 멀티 코덱이 완전히 지원되지 않는다.
따라서 m2ts 포맷만 기본 래더로 제공되며, 전용 플레이어인 경우에만 호환성을 보장한 상태에서 full 로 요청한다.
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-VFLY-ASSET-ID:6FA2BE4F3C19D0E7A8B25C41F6D3E9087B1C4D2E5F6A7B8C9D0E1F2A3B4C5D6E
#EXT-X-VFLY-TENANT-ID:acme
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.64002A,mp4a.40.2"
...
태그 |
값 |
|---|---|
|
원본 영상의 video-id (64자리 16진수) |
|
가상호스트 meta.tags 의 |
Warning
tenant-id는 공백 없는 ASCII 64자 이하로 쓴다. 벗어나면 설정 배포는 통과하지만#EXT-X-VFLY-TENANT-ID줄이 빠진다.tenant-id를 바꿔도 이미 캐시된 재생목록은 퍼지하기 전까지 이전 값을 싣는다.
구간 추출¶
# 0초 ~ 30초 구간만 재생
https://example.com/video.mp4/vfly/v1/vod/trim/0-30/_default/master.m3u8
# 10초부터 끝까지 (열린 구간)
https://example.com/video.mp4/vfly/v1/vod/trim/10-/_default/master.m3u8
# 처음부터 90.5초까지 (소수 허용)
https://example.com/video.mp4/vfly/v1/vod/trim/-90.5/_default/master.m3u8
명령어 |
파라미터 |
동작 |
|---|---|---|
|
|
|
캡처¶
# landscape 소스 — 320x180 은 가로 320 · 세로 180
https://example.com/landscape.mp4/vfly/v1/vod/capture/10.5/320x180.webp
# portrait 소스 — 320x180 은 가로 180 · 세로 320
https://example.com/portrait.mp4/vfly/v1/vod/capture/10.5/320x180.webp
# webp · jpg 포맷
https://example.com/video.mp4/vfly/v1/vod/capture/10/320x180.webp
https://example.com/video.mp4/vfly/v1/vod/capture/10/320x180.jpg
# 프로파일 기반 — 소스가 아니라 렌디션 출력 세그먼트에서 추출
https://example.com/video.mp4/vfly/v1/vod/_default/capture/10.5/320x180.webp
# 렌디션 명시 — 컨테이너를 고정하고 렌디션 라벨을 붙인다
https://example.com/video.mp4/vfly/v1/vod/_default.fmp4/360p/capture/10.5/640x360.jpg
# 구간 추출과 조합 — {at} 은 구간 시작 기준
https://example.com/video.mp4/vfly/v1/vod/trim/30-90/_default/capture/5/320x180.webp
명령어 |
파라미터 |
동작 |
|---|---|---|
|
|
|
프로파일 · 렌디션 뒤에 capture 를 붙이면 해당 프로파일의 렌디션 출력 세그먼트에서 추출한다.
명령어 |
파라미터 |
동작 |
|---|---|---|
|
|
|
|
|
|
|
|
|
Note
렌디션을 생략하면
master.m3u8이 노출하는 렌디션 중 해상도의 두 축이 모두 요청 크기 이상인 가장 작은 렌디션을 고른다. 그런 렌디션이 없으면 가장 큰 렌디션을 고른다. 같은 해상도가 여럿이면fmp4를 고른다.워터마크 가 정의된 프로파일이면 이미지에도 워터마크가 합성된다.
프로파일 기반 캡처는 다음 경우 실패를 응답한다.
응답 |
실패 원인 |
|---|---|
|
크기 규약 위반 · 구간( |
|
|
|
|
|
트랜스코더 미가용 · 혼잡 |
스프라이트¶
# 5초 간격 썸네일 그리드 이미지
https://example.com/video.mp4/vfly/v1/vod/sprite/5/320x180.jpg
# 그리드 내 좌표 트랙 (플레이어 시킹 미리보기용)
https://example.com/video.mp4/vfly/v1/vod/sprite/5/320x180.vtt
명령어 |
파라미터 |
동작 |
|---|---|---|
|
|
|
분석정보¶
# 소스(원본) 분석정보
https://example.com/video.mp4/vfly/v1/vod/meta.json
# 렌디션 분석정보
https://example.com/video.mp4/vfly/v1/vod/myprofile/fmp4_720p/a1b2c3d4/meta.json
# 구간 추출과 조합한 렌디션 분석정보
https://example.com/video.mp4/vfly/v1/vod/trim/0-30/myprofile/fmp4_720p/a1b2c3d4/meta.json
축 |
경로 |
결과 |
|---|---|---|
소스 |
|
원본 분석정보를 반환한다. |
렌디션 |
|
해당 렌디션의 분석정보를 반환한다. |
Note
렌디션 경로의
{hash8}은 마스터가 발급한 렌디션 경로에서 그대로 가져온다. 클라이언트가 직접 구성하지 않는다.프로파일 단위(
{profile}/meta.json)는 지원하지 않는다. 렌디션 단위만 지원한다.소스 축은 구간 추출(
trim)과 조합되지 않는다. 구간 추출 조합은 렌디션 축에서만 지원한다.
200 응답은 비디오 분석정보 의 srcd (상세) 형태를 따른다. result.video 아래에 상세 분석정보( streams · format )가 실린다.
meta¶
"meta": {
"enable": false,
"keyword": "vfly/v1/vod"
}
enable (기본: false)활성화
keyword (기본: vfly/v1/vod)VOD 명령을 인식하는 URL 키워드. 이 키워드 이후 경로가 VOD 명령으로 해석된다.
transcoder¶
HLS Segment 트랜스코더를 구성한다.
"transcoder": {
"type": "local",
"timeout": 60
}
type (기본: local)트랜스코더 타입.
local개발목적의 동시성 1의 트랜스코더로, GPU/CPU 모드를 자동으로 설정한다.hlseg-transcoder={name}사용할 hlseg-transcoder 의name을 연결한다."transcoder": { "type": "hlseg-transcoder=ondemand", "timeout": 60 }
videofly 가 비활성화되어 있거나 hlseg-transcoder 연결이 유효하지 않다면
503 Service Unavailable를 응답한다.
timeout (기본: 60)요청전송 후 완료 응답을 기다리는 최대 시간(초). 초과하면 응답 미수신으로 판단하여
503 Service Unavailable로 응답한다.
Note
hlseg-transcoder 는 전송·취합(aggregation) 담당이며, 응답 대기·대응 정책은 본 가상호스트 설정이 소유한다.
로그¶
hlseg-transcoder 트랜잭션은 전역로그인 log 에 기록된다.
access.log 의
x-ctx-id와 log 의x-ctx-id는 동일하다.
장애시 응답¶
HLS 서비스 중 장애는 다음과 같이 처리된다.
분류 |
장애응답 |
주요 원인 |
|---|---|---|
|
|
원본 미디어 인식불가 |
|
|
트랜스코더 장애 |
Note
정상 HLS 서비스가 어려운 경우 빠른 실패 후 클라이언트/플레이어에서 재생가능한 수단으로 fallback 처리할 것을 권장한다.
profiles¶
프로파일은 HLS 패키징과 세그먼트 비디오 형식을 정의하며, 고객 환경에 맞추어 자유롭게 정의 가능하다.
재생 URL 의 {profile} 자리에 프로파일 이름을 넣어 선택한다.
Note
자주 사용되는 프로파일은 아래와 같이 _ 로 시작하는 built-in 프로파일로 자유롭게 사용 가능하다.
# 빌트인 프로파일 재생
https://example.com/video.mp4/vfly/v1/vod/_premium/master.m3u8
name |
video |
audio |
max fps |
renditions |
용도 |
|---|---|---|---|---|---|
|
AV1 / H.264 |
AAC |
원본 |
1080p · 720p · 360p · 144p |
기본값. 보편적인 코덱과 해상도 지원. |
|
AV1 / H.264 |
AAC |
30 |
1080p · 720p · 480p · 360p |
가성비 범용 (general purpose) |
|
AV1 / H.264 |
AAC |
30 |
720p · 480p · 360p |
용량 절감 우선 (aggressive compression) |
|
AV1 / H.264 |
AAC |
30 |
2160p · 1440p · 1080p · 720p |
고품질 VOD / OTT, 4K 대응 |
|
원본 유지 |
원본 유지 |
원본 |
original (무변환) |
원본 코덱 호환성만 보장 |
|
AV1 / H.264 |
AAC |
30 |
1440p ~ 144p 7단 |
YouTube 스타일 MBR |
|
AV1 / H.264 |
AAC |
60 |
|
고프레임(HFR) 콘텐츠 |
각 프로파일은 공통 HLS 패키징 정책( hls )과 개별 스트림 목록( renditions )을 포함한다.
"profiles": [
{
"schema_version": "v1",
"name": "example",
"description": "설명을 넣는다."
"hls": {
"transcode": {
"policy": "if_spec_mismatch",
"upscale": false,
"ceiling": "source"
},
"version": 7,
"path": "abs",
"split": "loose",
"segment_duration": 2
},
"renditions": [ ... ]
}
]
Note
각 프로파일의 상세 규격은 런타임 스키마 검증기( ajv )가 전담하므로, 배포 시 필드 타입 · enum 위반은 거부된다.
schema_version프로파일 스키마 버전 (
v1)name프로파일을 식별하는 고유 이름. 재생 URL 의
{profile}값이다.^[A-Za-z0-9_][A-Za-z0-9_-]*$패턴을 따른다.description프로파일 설명 (기능하지 않는다.)
cacheable (기본: true)false면 산출물을 저장하지 않고 요청마다 만든다.hlsHLS Packetizing을 정의한다.
transcode.policy트랜스코딩 여부 기준.
정책명
Codec
Resolution
Bitrate
alwaysif_bitrate_exceeds일치
일치
같거나 낮음
if_spec_mismatch일치
일치
if_codec_mismatch일치
조건이 모두 만족하면 트랜스코딩하지 않는다.
transcode.upscale원본보다 큰 해상도로 트랜스코딩할지 여부
transcode.ceiling (기본: source)master.m3u8에 노출할 최고 렌디션의 기준. 원본 해상도가 렌디션 해상도와 맞지 않을 때 결과가 달라진다.source원본을 축소해야 하는 렌디션 전부와, 원본이 들어가는 렌디션 중 가장 작은 1개를 노출한다. 그 렌디션은 원본 해상도로 출력한다.ladder픽셀 수가 원본 이하인 렌디션만 노출한다. 모든 렌디션이 원본보다 크면 가장 작은 렌디션 1개를 노출한다.
컨테이너별로 적용한다.
transcode.upscale이false일 때만 적용된다.예를 들어 세로 404x720 원본을
_default로 재생하면source는 720p 렌디션을 404x720 으로 추가 노출하고,ladder는 360p 까지만 노출한다.versionHLS playlist 의
EXT-X-VERSION값 (1 이상)pathplaylist 안의 segment 경로 표현 방식.
abs절대경로 (항상/로 시작)rel상대경로
split목표 segment 길이 기준 분할 정책.
설정
설명
loose원본 키프레임을 위배하지 않는다.
balancesegment_duration기준 +-1 초 가능한 적게 분할한다.strict정확히
segment_duration단위로 분할한다.segment_duration목표 HLS segment 길이 (초, 0 초과). 길수록 한번에 트랜스코딩하는 크기가 커져 반응성이 저하된다.
renditions¶
프로파일이 제공하는 멀티 스트림(해상도 · 코덱 조합)을 정의한다.
정의된 순서대로 master.m3u8 에 노출된다.
"renditions": [
{
"name": "fmp4_144p",
"container": "fmp4",
"video": { ... },
"audio": { ... }
}
]
namerendition 고유 이름.
{container}_{name}규칙을 따른다 (예:fmp4_1080p,m2ts_720p).^(fmp4|m2ts)_[a-z0-9][a-z0-9_.-]*$패턴. 컨테이너 접두 뒤 라벨이capture·sprite인 이름(예:fmp4_capture)은 예약어라 쓸 수 없다 (프로파일 로드 거부).containerHLS 패키징 컨테이너 (
fmp4·m2ts중 택1)
video¶
"video": {
"enable": true,
"codec": "av1",
"gpu": { "preset": "p3", "quality": 35 },
"cpu": { "preset": "9", "quality": 35 },
"codec_options": { "profile": "main", "level": "4.1" },
"bit_rate": 2000000,
"frame_rate": 30,
"max_frame_rate": 60,
"resolution": "256x144",
"sizing_policy": "fit_to_orientation_no_upscale",
"padding_policy": "no_pad"
}
enable이 rendition 에 비디오 포함 여부
codec논리적 비디오 코덱 (
h264·av1). 실제 인코더 이름은 구현 정책에서 결정한다.gpuGPU 인코더 설정.
preset속도/품질 preset (^p[1-7]$, 즉p1~p7)quality품질 튜닝 값 (1~63, 낮을수록 고품질,cq에 대응). 필수
cpuCPU 인코더 설정 (GPU 사용 불가 시).
preset속도/품질 preset. 허용 범위는 구현 인코더 정책에서 결정한다.quality품질 튜닝 값 (1~63, 낮을수록 고품질,crf에 대응). 필수
codec_options코덱 세부 옵션.
profile코덱 프로파일 (예:baseline·main·high)level코덱 레벨 (예:4.0·4.1)max_bitrate/min_bitrate최대/최소 비디오 비트레이트 (bps)chroma_subsamplingyuv420p·yuv422p·yuv444p·nv12·autointerlace_modeauto·progressive·top_field_first·bottom_field_first
bit_rate목표 비디오 비트레이트 (bps)
frame_rate요청 출력 프레임레이트 (fps)
max_frame_rate최대 출력 프레임레이트 (fps). 인코더가 이 값을 초과하지 않도록 한다.
resolution{가로}x{세로}형식의 목표 해상도 (^\d+x\d+$, 예:1280x720)sizing_policy (기본: fit_to_orientation_no_upscale)원본을 목표 해상도에 맞추는 방식 (
fit·fit_to_orientation·fill·stretch·center_crop·fit_no_upscale·fill_no_upscale·fit_to_orientation_no_upscale)padding_policysizing_policy처리 후 남는 영역의 패딩 여부.no_pad패딩을 추가하지 않는다(운영 기본 동작).pad목표 해상도까지 레터박스 패딩을 추가한다.
Note
프로파일은 전역 스코프인 functions.contents.hive.profiles 설정만 지원한다. 가상호스트 단위 profile 정의는 지원하지 않는다.
audio¶
"audio": {
"enable": true,
"codec": "aac",
"codec_options": { "profile": "aac_low" },
"sample_rate": 48000,
"bit_rate": 128000,
"channels": 2
}
enable이 rendition 에 오디오 포함 여부
codec오디오 코덱 (
aac·ac3·eac3·opus). 값이 없으면 원본 유지 또는 구현 기본 정책을 따른다.codec_options.profile오디오 코덱 프로파일 (
aac_low·aac_he·aac_he_v2·auto). AAC 기준aac_low는 AAC-LC 에 대응한다.sample_rate샘플레이트 (Hz)
bit_rate목표 오디오 비트레이트 (bps)
channels오디오 채널 수 (1~8)
encrypt¶
EXT-X-KEY 암호화를 구성한다.
"encrypt": {
"enable": false,
"key_file_name": "enc.key",
"token": "",
"token_type": "raw",
"iv": null
}
enable (기본: false)HLS 암호화 활성화
key_file_nameplaylist 에 기록할 키 파일명
token암호화 토큰 또는 키 재료.
Note
공유 프로파일 파일에는 운영용 비밀값을 저장하지 않는 것을 권장한다.
token_typetoken표현 방식.rawtoken을 그대로 사용enc암호화된token을 사용 전 복호화
iv (기본: null)선택적 AES-128 Initial Vector.
0x로 시작하는 16바이트 16진수 문자열(^0x[0-9a-fA-F]{32}$)로 지정한다.
watermark¶
프로파일로 만드는 모든 세그먼트에 이미지 · 영상 · html 워터마크를 서버에서 합성한다.
재생 URL 형식은 그대로이며 {profile} 이 워터마크를 고른다.
{
"schema_version": "v1",
"name": "acme-wm",
"cacheable": false,
"watermark": {
"enable": true,
"items": [
{
"path": "/acme/viewer_mark.html",
"position": "nw",
"offset": "2%+2%",
"width": "30%",
"opacity": "40%"
},
{
"path": "/acme/logo_anim.mov",
"position": "se",
"offset": "2%+2%",
"width": "10%",
"opacity": "80%",
"start": 0,
"end": 10
}
]
},
...
}
enable (기본: false)워터마크 사용 여부.
false이거나items가 비어 있으면 합성하지 않는다.items합성할 워터마크 목록
Important
여러 개를 지정할 수 있다.
선언된 순서대로 비디오에 먼저 합성된다.
즉, 가장 마지막 아이템이 가장 마지막에 합성된다.
path워터마크 파일 경로.
버킷 루트의
/watermark아래 경로를 적는다. hive 가 앞에watermark/를 붙여 읽는다 (예:/acme/logo.png→watermark/acme/logo.png).storage 중 원본 조회용(
scope가src·both이고enableRead가true)에서 읽는다. storage 의basepath는 붙이지 않는다.http(s)주소는 지원하지 않는다...같은 상위 경로 이동은 설정 검증에서 거부한다.
Note
같은 경로에 파일을 덮어써도 워터마크가 갱신되지 않는다. 파일을 바꿀 때는
path를 바꾼다.position (기본: se)워터마크를 붙일 위치. 아래 9곳 중 택1
North (N)0° = 360°East (E)90°South (S)180°West (W)270°Northeast (NE)45°Southeast (SE)135°Southwest (SW)225°Northwest (NW)315°Center (C)-
offset (기본: 0+0)position쪽 가장자리에서 안쪽으로 띄울 거리( 가로+세로 ). 예:20+20은 20px 씩,2%+2%는 영상 폭 · 높이의 2% 씩 띄운다. 가운데 정렬한 방향의 값은 쓰지 않는다.width (기본: 원본 크기)워터마크 폭 (예:
200,10%, 0 초과). 높이는 비율을 유지한다.opacity (기본: 50%)불투명도 (
0%~100%)start (기본: 0)/end (기본: 영상 끝)노출 구간 (초,
start<end). 재생 시간 기준이다.
단위가 없으면 px, % 면 출력 영상 대비 비율이다 (x · width 는 폭, y 는 높이).
빌트인( _* ) 프로파일에는 워터마크가 없다.
종류 |
확장자 |
비고 |
|---|---|---|
이미지 |
|
|
영상 |
|
|
html |
|
png는 확장자가 아니라 파일 내용으로 애니메이션(영상)과 정지(이미지)를 가른다. 애니메이션 PNG 도.png로 올리면 된다.webp는 정지 이미지만 받는다. 애니메이션webp·avif·ts는 지원하지 않는다.지원하지 않는 형식이면 에러다.
Warning
시청자별( html 치환) 프로파일은 반드시
"cacheable": false로 둔다.true면 첫 시청자 값으로 만든 출력물이 저장돼 다른 시청자에게 그대로 나간다.워터마크를 확보하지 못하면 그 프로파일의 init · 세그먼트는
500(VFLY_WATERMARK_ERROR)으로 응답해 재생되지 않는다. 워터마크 없이 나가지 않는다 ( hive 에러리스트32200042).
html¶
hive 가 html 을 투명 배경 이미지로 렌더링해 합성한다. html 안의 {{ args.키 }} 를 요청 쿼리스트링 값으로 바꿔 시청자마다 다른 워터마크를 만든다.
html — 버킷의 watermark/acme/viewer_mark.html 에 올린다.
<html><body><div style="font:bold 40px sans-serif;color:#ffffff;text-shadow:0 0 6px #000">{{ args.uid }}</div></body></html>
프로파일
{
"name": "acme-viewer",
"cacheable": false,
"watermark": {
"enable": true,
"items": [
{ "path": "/acme/viewer_mark.html", "position": "c", "width": "40%", "opacity": "70%" }
]
}
}
요청 — 화면 가운데에 user-id-12345 가 나온다.
https://example.com/video.mp4/vfly/v1/vod/acme-viewer/master.m3u8?uid=user-id-12345
합성 전 |
합성 후 |
|---|---|
|
|
{{ args.키 }}는master.m3u8요청 끝(vfly/v1/vod오른쪽)의 쿼리스트링 값으로 바뀐다.키가 쿼리스트링에 없거나 값이 비어 있으면 에러다.
렌디션별 크기는 이미지와 같이
width에 맞춰 늘거나 줄어든다.width가 없으면 html 이 그린 크기다.body 밖으로 뺀(
position: absolute등) 요소는 잘린다.vh단위 ·loading=lazy는 의도대로 그려지지 않을 수 있다.
built-in 프로파일¶
별도 설정 없이 바로 동작하는 프로파일을 지원한다. 빌트인 프로파일은 _ 로 시작하는 규칙을 가진다.
대부분의 서비스는 빌트인만으로 충분하며, 세밀한 제어가 필요할 때만 profiles 을 정의한다.
# 빌트인 프로파일 재생
https://example.com/video.mp4/vfly/v1/vod/_premium/master.m3u8
name |
video |
audio |
max fps |
renditions |
용도 |
|---|---|---|---|---|---|
|
AV1 / H.264 |
AAC |
원본 |
1080p · 720p · 360p · 144p |
기본값. 보편적인 코덱과 해상도 지원. |
|
AV1 / H.264 |
AAC |
30 |
1080p · 720p · 480p · 360p |
가성비 범용 (general purpose) |
|
AV1 / H.264 |
AAC |
30 |
720p · 480p · 360p |
용량 절감 우선 (aggressive compression) |
|
AV1 / H.264 |
AAC |
30 |
2160p · 1440p · 1080p · 720p |
고품질 VOD / OTT, 4K 대응 |
|
원본 유지 |
원본 유지 |
원본 |
original (무변환) |
원본 코덱 호환성만 보장 |
|
AV1 / H.264 |
AAC |
30 |
1440p ~ 144p 7단 |
YouTube 스타일 MBR |
|
AV1 / H.264 |
AAC |
60 |
|
고프레임(HFR) 콘텐츠 |
Note
video 코덱은 컨테이너를 따른다 — fMP4 렌디션은
AV1, MPEG2-TS 렌디션은H.264._youtube계열의 MPEG2-TS 는 1440p · 240p 렌디션을 제외한다.
컨테이너(래더) 선택은 두 가지 방법이 있다.
쿼리스트링 (권장) —
master.m3u8에 ladder 쿼리스트링 을 붙인다 (예:_premium/master.m3u8?ladder=fmp4). 생략하면 기본m2ts래더를 노출한다.전용 프로파일 — 컨테이너를 고정한 빌트인을 직접 지정한다:
_{tier}_fmp4·_{tier}_m2ts(예:_balance_fmp4,_default_m2ts).
Warning
프로파일은 빌트인과 구분하기 위해 _ 로 시작할 수 없다.
빌트인 프로파일의 정의는 다음과 같다. _{tier}_fmp4 · _{tier}_m2ts 는 아래 정의에서
해당 컨테이너의 rendition 만 남긴 것이다.
{
"schema_version": "v1",
"name": "_default",
"description": "기본 VideoFly profile. fMP4는 AV1, MPEG2-TS는 H.264 rendition을 제공한다.",
"hls": {
"transcode": {
"policy": "if_spec_mismatch",
"upscale": false
},
"version": 7,
"path": "abs",
"split": "loose",
"segment_duration": 2
},
"renditions": [
{
"name": "fmp4_1080p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 32
},
"codec_options": {
"profile": "main"
},
"resolution": "1920x1080"
}
},
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 33
},
"codec_options": {
"profile": "main"
},
"resolution": "1280x720"
}
},
{
"name": "fmp4_360p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 35
},
"codec_options": {
"profile": "main"
},
"resolution": "640x360"
}
},
{
"name": "fmp4_144p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 35
},
"cpu": {
"preset": "9",
"quality": 35
},
"codec_options": {
"profile": "main"
},
"resolution": "256x144"
}
},
{
"name": "m2ts_1080p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 25
},
"codec_options": {
"profile": "high",
"level": "4.2"
},
"resolution": "1920x1080"
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 23
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720"
}
},
{
"name": "m2ts_360p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 33
},
"cpu": {
"preset": "fast",
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "3.0"
},
"resolution": "640x360"
}
},
{
"name": "m2ts_144p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 30
},
"cpu": {
"preset": "fast",
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "2.0"
},
"resolution": "256x144"
}
}
]
}
{
"schema_version": "v1",
"name": "_balance",
"description": "가성비 범용 profile (general purpose). 1080p ~ 360p 4단 래더.",
"renditions": [
{
"name": "fmp4_1080p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 36
},
"codec_options": {
"profile": "main"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 37
},
"codec_options": {
"profile": "main"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "fmp4_480p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 42
},
"cpu": {
"preset": "9",
"quality": 38
},
"codec_options": {
"profile": "main"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "fmp4_360p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 42
},
"cpu": {
"preset": "9",
"quality": 40
},
"codec_options": {
"profile": "main"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "m2ts_1080p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "high",
"level": "4.2"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "m2ts_480p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "m2ts_360p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 33
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "baseline",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
}
]
}
{
"schema_version": "v1",
"name": "_compact",
"description": "용량 중심 profile (aggressive compression). 720p AV1 only + 480p/360p 저용량 래더.",
"renditions": [
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 48
},
"cpu": {
"preset": "9",
"quality": 38
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "fmp4_480p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 48
},
"cpu": {
"preset": "9",
"quality": 40
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "fmp4_360p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 48
},
"cpu": {
"preset": "9",
"quality": 40
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "m2ts_480p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "m2ts_360p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 33
},
"cpu": {
"preset": "fast",
"quality": 28
},
"codec_options": {
"profile": "baseline",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
}
]
}
{
"schema_version": "v1",
"name": "_premium",
"description": "고해상도 프리미엄 profile. 고품질 VOD/OTT 대응. 2160p(4K) ~ 720p 래더.",
"renditions": [
{
"name": "fmp4_2160p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 28
},
"cpu": {
"preset": "9",
"quality": 20
},
"codec_options": {
"profile": "main",
"level": "5.1",
"chroma_subsampling": "yuv420p"
},
"resolution": "3840x2160",
"max_frame_rate": 30
}
},
{
"name": "fmp4_1440p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 30
},
"cpu": {
"preset": "9",
"quality": 22
},
"codec_options": {
"profile": "main",
"level": "5.0",
"chroma_subsampling": "yuv420p"
},
"resolution": "2560x1440",
"max_frame_rate": 30
}
},
{
"name": "fmp4_1080p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 32
},
"cpu": {
"preset": "9",
"quality": 24
},
"codec_options": {
"profile": "main",
"level": "4.0",
"chroma_subsampling": "yuv420p"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 34
},
"cpu": {
"preset": "9",
"quality": 26
},
"codec_options": {
"profile": "main",
"level": "3.1",
"chroma_subsampling": "yuv420p"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "m2ts_2160p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 20
},
"cpu": {
"quality": 14
},
"codec_options": {
"profile": "high",
"level": "5.1",
"chroma_subsampling": "yuv420p"
},
"resolution": "3840x2160",
"max_frame_rate": 30
}
},
{
"name": "m2ts_1440p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 22
},
"cpu": {
"quality": 16
},
"codec_options": {
"profile": "high",
"level": "5.0",
"chroma_subsampling": "yuv420p"
},
"resolution": "2560x1440",
"max_frame_rate": 30
}
},
{
"name": "m2ts_1080p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 25
},
"cpu": {
"quality": 18
},
"codec_options": {
"profile": "high",
"level": "4.0",
"chroma_subsampling": "yuv420p"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 27
},
"cpu": {
"quality": 20
},
"codec_options": {
"profile": "high",
"level": "3.1",
"chroma_subsampling": "yuv420p"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
}
]
}
{
"schema_version": "v1",
"name": "_source",
"description": "무변환 profile. 트랜스코딩 없이 원본 코덱 호환성만 보장하여 재생 가능하게 한다.",
"renditions": [
{
"name": "fmp4_original",
"container": "fmp4",
"audio": {
"enable": true
},
"video": {
"enable": true
}
},
{
"name": "m2ts_original",
"container": "m2ts",
"audio": {
"enable": true
},
"video": {
"enable": true
}
}
]
}
{
"schema_version": "v1",
"name": "_youtube",
"description": "YouTube 스타일 MBR profile. 최대 30fps. 1440p ~ 144p 래더.",
"renditions": [
{
"name": "fmp4_1440p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 35
},
"cpu": {
"preset": "9",
"quality": 26
},
"codec_options": {
"profile": "main",
"level": "5.0"
},
"resolution": "2560x1440",
"max_frame_rate": 30
}
},
{
"name": "fmp4_1080p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "4.0"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 30
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "fmp4_480p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 32
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "fmp4_360p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 33
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "fmp4_240p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 35
},
"codec_options": {
"profile": "main",
"level": "2.1"
},
"resolution": "426x240",
"max_frame_rate": 30
}
},
{
"name": "fmp4_144p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 37
},
"codec_options": {
"profile": "main",
"level": "2.0"
},
"resolution": "256x144",
"max_frame_rate": 30
}
},
{
"name": "m2ts_1080p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "high",
"level": "4.0"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "m2ts_480p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "m2ts_360p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 33
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "m2ts_144p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 30
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "2.0"
},
"resolution": "256x144",
"max_frame_rate": 30
}
}
]
}
{
"schema_version": "v1",
"name": "_youtube_hfr",
"description": "YouTube HFR 스타일 profile. youtube 래더에 720p60 · 1080p60 rendition 추가. 고프레임 콘텐츠 대응.",
"renditions": [
{
"name": "fmp4_1440p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 35
},
"cpu": {
"preset": "9",
"quality": 26
},
"codec_options": {
"profile": "main",
"level": "5.0"
},
"resolution": "2560x1440",
"max_frame_rate": 30
}
},
{
"name": "fmp4_1080p60",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p4",
"quality": 35
},
"cpu": {
"preset": "8",
"quality": 26
},
"codec_options": {
"profile": "main",
"level": "4.2"
},
"resolution": "1920x1080",
"max_frame_rate": 60
}
},
{
"name": "fmp4_1080p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "4.0"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "fmp4_720p60",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p4",
"quality": 36
},
"cpu": {
"preset": "8",
"quality": 28
},
"codec_options": {
"profile": "main",
"level": "3.2"
},
"resolution": "1280x720",
"max_frame_rate": 60
}
},
{
"name": "fmp4_720p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 30
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "fmp4_480p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 32
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "fmp4_360p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 33
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "fmp4_240p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 40
},
"cpu": {
"preset": "9",
"quality": 35
},
"codec_options": {
"profile": "main",
"level": "2.1"
},
"resolution": "426x240",
"max_frame_rate": 30
}
},
{
"name": "fmp4_144p",
"container": "fmp4",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "av1",
"gpu": {
"preset": "p3",
"quality": 38
},
"cpu": {
"preset": "9",
"quality": 37
},
"codec_options": {
"profile": "main",
"level": "2.0"
},
"resolution": "256x144",
"max_frame_rate": 30
}
},
{
"name": "m2ts_1080p60",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 28
},
"cpu": {
"quality": 20
},
"codec_options": {
"profile": "high",
"level": "4.2"
},
"resolution": "1920x1080",
"max_frame_rate": 60
}
},
{
"name": "m2ts_1080p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "high",
"level": "4.0"
},
"resolution": "1920x1080",
"max_frame_rate": 30
}
},
{
"name": "m2ts_720p60",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 28
},
"cpu": {
"quality": 20
},
"codec_options": {
"profile": "high",
"level": "3.2"
},
"resolution": "1280x720",
"max_frame_rate": 60
}
},
{
"name": "m2ts_720p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "main",
"level": "3.1"
},
"resolution": "1280x720",
"max_frame_rate": 30
}
},
{
"name": "m2ts_480p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 35
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "main",
"level": "3.0"
},
"resolution": "854x480",
"max_frame_rate": 30
}
},
{
"name": "m2ts_360p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 33
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "3.0"
},
"resolution": "640x360",
"max_frame_rate": 30
}
},
{
"name": "m2ts_144p",
"container": "m2ts",
"audio": {
"codec": "aac",
"codec_options": {
"profile": "aac_low"
},
"channels": 2
},
"video": {
"codec": "h264",
"gpu": {
"quality": 30
},
"cpu": {
"quality": 23
},
"codec_options": {
"profile": "baseline",
"level": "2.0"
},
"resolution": "256x144",
"max_frame_rate": 30
}
}
]
}
kvcache¶
"kvcache" : {
"url_to_videoid": "5min",
"mezzanine": { }
}
url_to_videoid (기본: 5min)클라이언트 요청 URL에 매칭되는 video-id 캐싱시간
mezzanine¶
다음 세그먼트 요청에 대비해 원본 데이터(=mezzanine)를 가용상태로 유지한다.
"mezzanine": {
"keepalive": "5min",
"onIdle": { ... }
}
keepalive (기본: 5min)지정된 시간동안 mezzanine을 유지한다. 타임아웃은 접근될 때마다 초기화된다.
onIdle유휴 상태로 전환될 때의 정규화 위임. 지정하지 않으면 폐기한다.
onIdle¶
keepalive 가 만료되어 mezzanine 이 캐시에서 내려가는 시점에 canon draft 정규화를 위임한다.
캐시에서 내려갈 뿐 원본이 삭제되는 것이 아니다.
구조는 canon 작업 생성 의 본문과 같다.
대상 원본( origin )은 mezzanine 의 원본 URL 이 자동으로 지정되므로 적지 않는다.
# 정규화하여 원본 스토리지의 원본 경로에 적재한다. (덮어쓰기)
"onIdle": {
"profile": "my_standard_profile",
"dest": [ "originstorage" ]
}
# 다른 저장소 두 곳에 적재하고 원본을 삭제한다.
"onIdle": {
"profile": "my_standard_profile",
"dest": [ "canonarchive", "canonbackup" ],
"delete": [ "originstorage" ]
}
storage¶
원본 조회( src ) 및 산출물 저장( dest )에 사용할 오브젝트 스토리지(S3) 목록을 정의한다.
"storage": {
"list": [
{
"name": "vfly-src",
"scope": "src",
"s3Endpoint": "mystorage@aws_s3",
"bucket": "vfly-src-bucket",
"region": "ap-northeast-2",
"enableRead": true,
"enableWrite": false
},
{
"name": "vfly-dst",
"scope": "dest",
"bucket": "vfly-asset-bucket",
"region": "ap-northeast-2",
"enableRead": true,
"enableWrite": true,
"touch": {
"enable": false,
"age": "300d"
}
}
]
}
name스토리지 식별 이름
scope스토리지 용도. 세 값만 허용하며, 그 외 값은 배포가 거부된다.
설정
설명
src원본 미디어 조회
dest가공 산출물 저장
both조회 · 저장 겸용
enableRead읽기 활성화.
read접근 시 이 플래그가true인 항목만 선택된다.enableWrite쓰기 활성화.
write접근 시 이 플래그가true인 항목만 선택된다.s3Endpoint{endpoint}@{function}형식으로 aws_s3 에 구성된 엔드포인트의 접속정보를 사용한다.# aws_s3에 설정된 mystorage라는 endpoint를 사용한다. "s3Endpoint": "mystorage@aws_s3"
bucket버킷 이름
region버킷 리전 (예:
ap-northeast-2)basepath객체 키 접두. 미지정 시 meta 의
basepath→ 빈 문자열 순으로 폴백한다.domain엔드포인트 도메인 (S3 호환 스토리지 지정 시)
accessKey/secretKey접속 자격 증명
touch객체 접근 시각 갱신 정책.
enable활성화 여부age갱신 최소 간격
See also
transcoder — 트랜스코딩 시스템 권장사항 및 프리셋.
profiles — 프로파일 기반 HLS 구성 개념.
HLS JIT Packaging — 원본 세그먼트 확보에 사용한다.
canon draft — JIT 재생에 부적합한 원본을 정규화해 입력 원본으로 대체한다.