hive alpha

/usr/local/m2/setting.json 다음 영역에 대해 기술한다.

{
  "functions": {
    "contents": {
      "hive": {
        ...
      }
    }
  }
}

hivevideofly 서비스의 HLS 가공 컴포넌트다. 원본 미디어를 사전 변환 없이 요청 시점에( Just-in-time ) 세그먼트 단위로 트랜스코딩하여 서빙한다.

  • JIT Packaging (HLS) — 원본을 master.m3u8 · playlist.m3u8fMP4 · 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

# 컨테이너 고정 — 프로파일 이름 뒤 .fmp4 또는 .m2ts
https://example.com/video.mp4/vfly/v1/vod/_default.fmp4/master.m3u8
https://example.com/video.mp4/vfly/v1/vod/_default.m2ts/master.m3u8

프로파일 · 컨테이너 · 구간을 조합해 요청한다.

요청 유형

경로

결과

프로파일

{profile}/master.m3u8

프로파일이 정의한 모든 컨테이너의 랜디션을 노출한다.

컨테이너 고정

{profile}.{container}/master.m3u8

해당 컨테이너의 랜디션만 노출한다.

구간 추출

# 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초까지 ).

캡처

# 10.5초 시점 프레임을 320x180 webp 이미지로
https://example.com/video.mp4/vfly/v1/vod/capture/10.5/320x180.webp

# avif · jpg 포맷
https://example.com/video.mp4/vfly/v1/vod/capture/10/320x180.avif
https://example.com/video.mp4/vfly/v1/vod/capture/10/320x180.jpg

명령어

파라미터

동작

capture

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

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

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

meta

"meta": {
  "enable": false,
  "keyword": "vfly/v1/vod"
}
enable (기본: false)

활성화

keyword (기본: vfly/v1/vod)

VOD 명령을 인식하는 URL 키워드. 이 키워드 이후 경로가 VOD 명령으로 해석된다.

transcoder

HLS Segement 트랜스코더를 구성한다.

"transcoder": {
  "type": "local",
  "timeout": 60
}
type (기본: local)

트랜스코더 타입.

  • local 개발목적의 동시성 1의 트랜스코더로, GPU/CPU 모드를 자동으로 설정한다.

  • hlseg-transcoder={name} 사용할 hlseg-transcodername 을 연결한다.

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

프로파일 설명 (기능하지 않는다.)

hls

HLS Packetizing을 정의한다.

transcode.policy

트랜스코딩 여부 기준.

정책명

Codec

Resolution

Bitrate

always

if_bitrate_exceeds

일치

일치

같거나 낮음

if_spec_mismatch

일치

일치

if_codec_mismatch

일치

조건이 모두 만족하면 트랜스코딩하지 않는다.

transcode.upscale

원본보다 큰 해상도로 트랜스코딩할지 여부

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_.-]*$ 패턴.

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}$ )로 지정한다.

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 랜디션을 제외한다.

컨테이너 선택은 두 가지 방법이 있다.

  • URL 접미 (권장) — 프로파일 이름 뒤에 .fmp4 · .m2ts 를 붙이면 해당 컨테이너 랜디션만 노출한다 (예: _premium.fmp4 ). 접미가 없으면 프로파일이 제공하는 모든 컨테이너를 노출한다.

  • 전용 프로파일 — 컨테이너를 고정한 빌트인을 직접 지정한다: _{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",
      "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 인 항목만 선택된다.

bucket

버킷 이름

region

버킷 리전 (예: ap-northeast-2 )

basepath

객체 키 접두. 미지정 시 metabasepath → 빈 문자열 순으로 폴백한다.

domain

엔드포인트 도메인 (S3 호환 스토리지 지정 시)

accessKey / secretKey

접속 자격 증명

touch

객체 접근 시각 갱신 정책.

  • enable 활성화 여부

  • age 갱신 최소 간격

See also

  • transcoder — 트랜스코딩 시스템 권장사항 및 프리셋.

  • profiles — 프로파일 기반 HLS 구성 개념.

  • HLS JIT Packaging — 원본 세그먼트 확보에 사용한다.

  • canon draft — JIT 재생에 부적합한 원본을 정규화해 입력 원본으로 대체한다.