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 쿼리스트링으로 선택한다.

ladder

결과

m2ts (기본)

MPEG2-TS 렌디션만 노출한다.

fmp4

fMP4 렌디션만 노출한다.

full

fMP4 · MPEG2-TS 멀티 코덱 래더를 모두 노출한다.

Warning

iOS · 크롬 native 재생 환경에서는 멀티 코덱이 완전히 지원되지 않는다. 따라서 m2ts 포맷만 기본 래더로 제공되며, 전용 플레이어인 경우에만 호환성을 보장한 상태에서 full 로 요청한다.

master.m3u8 과 렌디션 playlist.m3u8 의 헤더에 식별 태그를 싣는다. 같은 원본의 재생목록은 모두 같은 값을 싣는다.

#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"
...

태그

값

#EXT-X-VFLY-ASSET-ID

원본 영상의 video-id (64자리 16진수)

#EXT-X-VFLY-TENANT-ID

가상호스트 meta.tags 의 tenant-id 값. 설정하지 않으면 이 줄이 없다.

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

명령어

파라미터

동작

trim

{start}-{end}

  • 재생 명령 앞에 붙여 해당 구간만 추출해 재생한다.

  • {start} · {end} 는 초 단위(소수 허용).

  • 한쪽을 생략하면 열린 구간이다 ( 10- = 10초부터 끝까지, -30 = 처음부터 30초까지 ).

캡처

# 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

{at}/{긴축}x{짧은축}.{ext}

  • {at} 초(소수 허용) 시점의 1 프레임을 이미지로 생성한다.

  • 해상도는 원본의 종횡비를 유지한다 (contain, 패딩 없음).

  • 최대 해상도 7680x4320 초과 요청시 400 응답한다.

  • {ext} 는 webp · jpg 중 택1.

프로파일 · 렌디션 뒤에 capture 를 붙이면 해당 프로파일의 렌디션 출력 세그먼트에서 추출한다.

명령어

파라미터

동작

{profile}/capture

{at}/{긴축}x{짧은축}.{ext}

  • 동작은 capture 와 같고, 추출 원본만 렌디션 출력 세그먼트다.

  • 렌디션은 요청 크기에 맞춰 자동으로 고른다 (아래 note 참고).

{profile}/{rendition}/capture

{at}/{긴축}x{짧은축}.{ext}

  • 동작은 capture 와 같고, 추출 원본만 렌디션 출력 세그먼트다.

  • {rendition} 은 컨테이너 접두를 뺀 렌디션 라벨이다 (예: fmp4_360p → 360p ).

  • 같은 라벨이 여러 컨테이너에 있으면 {profile}.{container} 로 컨테이너를 고정한다.

trim/{clip}/{profile}/capture

{at}/{긴축}x{짧은축}.{ext}

  • 동작은 {profile}/capture 와 같고, {clip} 구간의 출력에서 추출한다.

  • {at} 은 구간 시작을 0 초로 하는 시각이다.

  • trim/{clip}/{profile}/{rendition}/capture 로 렌디션을 명시할 수 있다.

Note

  • 렌디션을 생략하면 master.m3u8 이 노출하는 렌디션 중 해상도의 두 축이 모두 요청 크기 이상인 가장 작은 렌디션을 고른다. 그런 렌디션이 없으면 가장 큰 렌디션을 고른다. 같은 해상도가 여럿이면 fmp4 를 고른다.

  • 워터마크 가 정의된 프로파일이면 이미지에도 워터마크가 합성된다.

프로파일 기반 캡처는 다음 경우 실패를 응답한다.

응답

실패 원인

400 Bad Request

크기 규약 위반 · 구간( {clip} ) 위반

404 Not Found

{at} 이 출력 길이 밖

422 Unprocessable Entity

{profile} 미정의 · {rendition} 미정의 또는 여러 컨테이너에 있어 모호

503 Service Unavailable

트랜스코더 미가용 · 혼잡

스프라이트

# 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

명령어

파라미터

동작

sprite

{interval}/{W}x{H}.{ext}

  • {interval} 초(양의 정수) 간격으로 프레임을 추출한다. 각 프레임 크기는 {W}x{H} .

  • jpg 는 썸네일 그리드 이미지, vtt 는 그리드 내 좌표 트랙을 생성한다.

  • jpg 와 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

축

경로

결과

소스

meta.json

원본 분석정보를 반환한다.

렌디션

{profile}/{rendition}/{hash8}/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) 담당이며, 응답 대기·대응 정책은 본 가상호스트 설정이 소유한다.

로그

장애시 응답

HLS 서비스 중 장애는 다음과 같이 처리된다.

분류

장애응답

주요 원인

.m3u8

415 Unsupported Media Type

원본 미디어 인식불가

.ts | .m4s

503 Service Unavailable

트랜스코더 장애

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

용도

_default

AV1 / H.264

AAC

원본

1080p · 720p · 360p · 144p

기본값. 보편적인 코덱과 해상도 지원.

_balance

AV1 / H.264

AAC

30

1080p · 720p · 480p · 360p

가성비 범용 (general purpose)

_compact

AV1 / H.264

AAC

30

720p · 480p · 360p

용량 절감 우선 (aggressive compression)

_premium

AV1 / H.264

AAC

30

2160p · 1440p · 1080p · 720p

고품질 VOD / OTT, 4K 대응

_source

원본 유지

원본 유지

원본

original (무변환)

원본 코덱 호환성만 보장

_youtube

AV1 / H.264

AAC

30

1440p ~ 144p 7단

YouTube 스타일 MBR

_youtube_hfr

AV1 / H.264

AAC

60

_youtube + 1080p60 · 720p60

고프레임(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 면 산출물을 저장하지 않고 요청마다 만든다.

hls

HLS Packetizing을 정의한다.

transcode.policy

트랜스코딩 여부 기준.

정책명

Codec

Resolution

Bitrate

always

if_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 까지만 노출한다.

version

HLS playlist 의 EXT-X-VERSION 값 (1 이상)

path

playlist 안의 segment 경로 표현 방식.

  • abs 절대경로 (항상 / 로 시작)

  • rel 상대경로

split

목표 segment 길이 기준 분할 정책.

설정

설명

loose

원본 키프레임을 위배하지 않는다.

balance

segment_duration 기준 +-1 초 가능한 적게 분할한다.

strict

정확히 segment_duration 단위로 분할한다.

segment_duration

목표 HLS segment 길이 (초, 0 초과). 길수록 한번에 트랜스코딩하는 크기가 커져 반응성이 저하된다.

renditions

프로파일이 제공하는 멀티 스트림(해상도 · 코덱 조합)을 정의한다. 정의된 순서대로 master.m3u8 에 노출된다.

"renditions": [
  {
    "name": "fmp4_144p",
    "container": "fmp4",
    "video": { ... },
    "audio": { ... }
  }
]
name

rendition 고유 이름. {container}_{name} 규칙을 따른다 (예: fmp4_1080p , m2ts_720p ). ^(fmp4|m2ts)_[a-z0-9][a-z0-9_.-]*$ 패턴. 컨테이너 접두 뒤 라벨이 capture · sprite 인 이름(예: fmp4_capture )은 예약어라 쓸 수 없다 (프로파일 로드 거부).

container

HLS 패키징 컨테이너 ( 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 ). 실제 인코더 이름은 구현 정책에서 결정한다.

gpu

GPU 인코더 설정.

  • preset 속도/품질 preset ( ^p[1-7]$ , 즉 p1 ~ p7 )

  • quality 품질 튜닝 값 (1~63, 낮을수록 고품질, cq 에 대응). 필수

cpu

CPU 인코더 설정 (GPU 사용 불가 시).

  • preset 속도/품질 preset. 허용 범위는 구현 인코더 정책에서 결정한다.

  • quality 품질 튜닝 값 (1~63, 낮을수록 고품질, crf 에 대응). 필수

codec_options

코덱 세부 옵션.

  • profile 코덱 프로파일 (예: baseline · main · high )

  • level 코덱 레벨 (예: 4.0 · 4.1 )

  • max_bitrate / min_bitrate 최대/최소 비디오 비트레이트 (bps)

  • chroma_subsampling yuv420p · yuv422p · yuv444p · nv12 · auto

  • interlace_mode auto · 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_policy

sizing_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_name

playlist 에 기록할 키 파일명

token

암호화 토큰 또는 키 재료.

Note

공유 프로파일 파일에는 운영용 비밀값을 저장하지 않는 것을 권장한다.

token_type

token 표현 방식.

  • raw token 을 그대로 사용

  • 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

../../../../_images/conf_dims2.png
  • 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 는 높이). 빌트인( _* ) 프로파일에는 워터마크가 없다.

종류

확장자

비고

이미지

png · jpg · jpeg · webp

webp 는 정지 이미지만

영상

mp4 · m4v · mov · mkv · webm · avi · flv · wmv · gif · apng

html

html

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

합성 전

합성 후

../../../../_images/hive_watermark_html_before.jpg ../../../../_images/hive_watermark_html_after.jpg
  • {{ 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

용도

_default

AV1 / H.264

AAC

원본

1080p · 720p · 360p · 144p

기본값. 보편적인 코덱과 해상도 지원.

_balance

AV1 / H.264

AAC

30

1080p · 720p · 480p · 360p

가성비 범용 (general purpose)

_compact

AV1 / H.264

AAC

30

720p · 480p · 360p

용량 절감 우선 (aggressive compression)

_premium

AV1 / H.264

AAC

30

2160p · 1440p · 1080p · 720p

고품질 VOD / OTT, 4K 대응

_source

원본 유지

원본 유지

원본

original (무변환)

원본 코덱 호환성만 보장

_youtube

AV1 / H.264

AAC

30

1440p ~ 144p 7단

YouTube 스타일 MBR

_youtube_hfr

AV1 / H.264

AAC

60

_youtube + 1080p60 · 720p60

고프레임(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"
      }
    }
  ]
}

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" ]
}

Note

  • 저장용 프로파일은 서비스용 프로파일과 다르다. 무엇으로 정규화해 어디에 적재할지 명시한다. 암묵적인 적재 위치는 없다.

  • 재생으로 실제 접근된 원본만 위임되므로, 재생되지 않는 콘텐츠까지 정규화하는 낭비가 생기지 않는다.

  • 위임은 비동기다. mezzanine 데이터를 넘기지 않고 대상 식별자만 전달하며, 실패는 재시도하지 않는다. 누락분은 onBatch 가 회수한다.

  • callback 은 지정할 수 없다. 내부 위임 경로는 통보를 사용하지 않는다 ( meta ).

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 재생에 부적합한 원본을 정규화해 입력 원본으로 대체한다.