HLSEmbeddingPlayer

웹사이트에 HLS 동영상을 임베드하는 방법 (iframe과 hls.js)

웹 페이지에 HLS 동영상을 넣는 단계별 가이드: 기본 제공 iframe 플레이어, 반응형 마크업, URL 파라미터, 직접 구성하는 hls.js까지 다룹니다.

HLS(HTTP Live Streaming)는 오늘날 대부분의 웹사이트가 주문형 동영상에 사용하는 형식입니다. 거대한 MP4 파일 하나 대신, 작은 텍스트 재생 목록이 같은 동영상의 여러 버전을 가리키며 각 버전은 짧은 세그먼트로 나뉘어 있습니다. 플레이어는 세그먼트 몇 개를 미리 내려받고, 도착 속도를 측정해 버전 사이를 실시간으로 전환합니다. 모바일 데이터로 보는 시청자는 가벼운 버전을, 광랜으로 보는 시청자는 선명한 버전을 받으며, 첫 프레임이 나오기 전에 파일 전체를 기다릴 필요도 없습니다.

이 가이드에서는 UFOLOAD의 HLS 동영상을 내 웹 페이지에 넣는 두 가지 방법을 소개합니다. 하나는 iframe으로 기본 플레이어를 넣는 방법으로 1분 정도면 됩니다. 다른 하나는 hls.js로 직접 <video> 요소를 구동하는 방법으로, 페이지를 완전히 제어할 수 있습니다. 두 방법 모두 같은 스트림을 사용하므로, iframe으로 시작했다가 나중에 다시 업로드하지 않고 hls.js로 옮겨 갈 수 있습니다.

UFOLOAD의 HLS 스트림 구조

파일을 업로드하면 컨버터가 H.264 동영상과 AAC 스테레오 오디오로 인코딩해 렌디션이라고 부르는 버전을 1~4개 만듭니다: 360p, 720p, 1080p, 2160p(4K). 렌디션은 원본보다 커지지 않으므로 720p로 업로드하면 720p와 360p가 만들어지고, 업스케일된 1080p는 생기지 않습니다. 실제로 받는 최고 렌디션은 요금제에 따라서도 달라지며, 현재 한도는 요금제 페이지에 나와 있습니다. 단계가 어떻게 정해지는지 자세히 알고 싶다면 적응형 비트레이트 래더 설명을 읽어 보세요.

각 렌디션은 인덱스가 파일 앞쪽에 있는 일반 MP4로 저장됩니다. 시청자가 재생을 시작하면 스토리지 계층이 이 MP4 파일들을 실시간으로 HLS로 패키징합니다. 마스터 재생 목록(master.m3u8)에는 모든 렌디션이 최대 대역폭, 해상도, 코덱과 함께 나열되고, 렌디션마다 4초 길이 세그먼트의 재생 목록이 따로 있습니다. 키프레임은 세그먼트 경계와 맞도록 배치되어 있어, 플레이어가 동영상 중간에도 화질을 깔끔하게 전환할 수 있습니다.

재생 목록과 세그먼트는 Access-Control-Allow-Origin: * 헤더와 함께 캐시 노드에서 제공되므로, 내 도메인에서 실행되는 플레이어가 직접 요청할 수 있습니다. 모든 URL은 서명되어 있고 만료 시간이 있는데, 이는 뒤에서 hls.js 방식을 다룰 때 중요해집니다.

1단계: 동영상을 업로드하고 준비될 때까지 기다리기

대시보드에서 파일을 끌어다 놓거나 직접 링크를 붙여 넣어 업로드하거나, FTP, WebDAV 또는 API를 사용하세요(curl, Python, Node.js 예제는 API로 동영상 업로드하기 참고). 파일 상태는 uploading, queued, processing, ready 순으로 바뀌며, failed는 사유와 함께 표시되고 대시보드에서 다시 시도할 수 있습니다. 짧은 클립은 몇 분 안에 준비되고 긴 영화는 더 오래 걸리며, 유료 요금제에는 우선 인코딩 대기열이 있습니다.

페이지가 완성될 때까지 기다릴 필요는 없습니다. 파일이 아직 처리 중일 때 누군가 플레이어를 열면 진행률과 함께 처리 중 안내가 표시되고, 처리가 끝나면 자동으로 동영상으로 전환됩니다. 그래도 첫 방문자가 진행 표시줄을 보게 되는 일이 없도록, 페이지를 게시하기 전에 상태가 ready인지 확인하세요.

동영상 식별자가 필요합니다. 대시보드의 공유 패널에서 확인할 수 있고, API는 이를 11자짜리 짧은 코드인 public_id로 반환합니다. 이 코드가 임베드 주소에 들어갑니다.

2단계: iframe으로 플레이어 임베드하기

대시보드는 업로드 직후와 모든 동영상의 공유 패널에서 iframe 스니펫을 제공합니다. 아래 첫 번째 블록과 같은 형태입니다. VIDEO_ID를 내 동영상의 식별자로 바꾸세요. 플레이어 페이지 자체는 검색 엔진에 색인되지 않는데, 임베드에는 바로 이것이 바람직합니다. 순위에 오르는 것은 플레이어 프레임이 아니라 내 페이지입니다.

대시보드에서 제공하는 스니펫 · html
<iframe width="640" height="360"
  src="https://iframe.andromedans.live/e/VIDEO_ID"
  title="My video"
  frameborder="0"
  allow="autoplay; fullscreen; picture-in-picture"
  allowfullscreen></iframe>

고정 픽셀 크기는 휴대폰에서 깨집니다. 반응형 페이지에서는 iframe을 16:9 비율을 유지하는 상자로 감싸고 프레임이 그 상자를 채우도록 하세요. 플레이어가 프레임 전체를 채우므로 동영상이 깔끔하게 크기 조정됩니다.

반응형 임베드 · html
<div style="position:relative;aspect-ratio:16/9;max-width:960px">
  <iframe src="https://iframe.andromedans.live/e/VIDEO_ID"
    title="My video"
    style="position:absolute;inset:0;width:100%;height:100%;border:0"
    loading="lazy"
    allow="autoplay; fullscreen; picture-in-picture"
    allowfullscreen></iframe>
</div>

주소에 추가할 수 있는 파라미터

  • autoplay=1은 플레이어가 로드되면 재생을 시작합니다. 브라우저는 대부분 소리가 있는 자동 재생을 차단하므로 mute=1과 함께 사용하세요.
  • mute=1은 음소거 상태로 동영상을 시작하며, 시청자는 언제든 음소거를 해제할 수 있습니다.
  • loop=1은 동영상이 끝나면 처음부터 다시 재생합니다.
  • t=30은 30초 지점부터 재생을 시작하므로, 긴 동영상의 특정 순간으로 바로 연결하는 링크에 유용합니다.

주소의 파라미터는 항상 Player studio의 같은 설정보다 우선합니다. 스킨, 강조 색상, 로고, 버튼 배치처럼 모든 곳에 적용할 기본값은 Player studio에서 정하고, 특정 페이지만 다르게 동작해야 할 때 파라미터를 사용하세요. 임베드하는 도메인마다 별도의 플레이어 프로필을 둘 수도 있습니다.

팁

플레이어에 임베드가 허용되지 않는다는 메시지가 표시된다면, 내 페이지의 도메인이 허용된 임베드 도메인 목록에 없을 가능성이 큽니다. 이 목록이 어떻게 동작하는지는 도메인 잠금과 지역 제한을 참고하세요.

3단계(선택): hls.js로 스트림 재생하기

iframe이 가장 빠른 방법이지만, 직접 만든 컨트롤 바, 캐러셀 안의 동영상, 내 코드에서 보내는 분석 이벤트처럼 마크업을 직접 다루고 싶을 때도 있습니다. 이 경우 재생 목록 주소와 플레이어 라이브러리가 필요합니다. Safari를 제외한 브라우저는 HLS를 기본적으로 재생하지 못하므로, 보통 HLS 세그먼트를 표준 <video> 요소에 공급하는 JavaScript 라이브러리인 hls.js를 선택합니다. Safari와 iOS는 HLS를 기본 지원하므로 필요하지 않습니다.

재생 목록 주소는 동영상 객체의 links.playback 필드입니다. API 키는 절대 브라우저 코드에 노출되면 안 되므로, 이 주소는 서버에서 API 키로 요청하세요. 같은 호출이 links.expires_at도 반환하며, 링크는 서명되어 있고 유효 기간이 있으므로 데이터베이스에 저장해 두지 말고 페이지를 렌더링할 때마다 새 링크를 요청하세요.

서버 측(Node.js 18+): 서명된 재생 목록 링크 받기 · js
const BASE = 'https://ufoload.com/api/v1'

export async function playbackUrl(fileId) {
  const res = await fetch(`${BASE}/files/${fileId}`, {
    headers: { Authorization: `Bearer ${process.env.UFOLOAD_API_KEY}` },
  })
  if (!res.ok) throw new Error(`UFOLOAD API: ${res.status}`)
  const { file, links } = await res.json()
  if (file.status !== 'ready') return null // still processing
  return links.playback // signed master.m3u8 URL
}

기본값이 아닌 유효 기간이 필요하다면 POST /files/{id}/links에 60초에서 30일 사이의 ttl을 지정할 수 있고, 링크를 IP 주소나 쿠키에 묶을 수도 있습니다. 자세한 내용은 API 문서에 있습니다. 키가 필요 없는 공개 엔드포인트 GET /api/v1/public/files/{id}도 있습니다. 시청 페이지와 임베드 페이지가 이를 사용하며, 이 링크는 6시간 동안 유효합니다.

페이지에서 플레이어를 만듭니다. 아래 블록은 지원되는 환경에서는 hls.js를 사용하고, Safari에서는 기본 재생으로 대체하며, 그 밖의 경우에는 간단한 메시지를 보여 줍니다. 라이브러리 파일은 직접 호스팅하거나 버전을 고정하고, 최신 버전을 무작정 불러오지 마세요.

클라이언트 측 · html
<video id="player" controls playsinline preload="metadata"
       poster="POSTER_URL" style="width:100%;aspect-ratio:16/9;background:#000"></video>
<script src="/vendor/hls.min.js"></script>
<script>
  const video = document.getElementById('player')
  const src = 'PLAYLIST_URL_FROM_YOUR_SERVER'

  if (window.Hls && Hls.isSupported()) {
    const hls = new Hls()
    hls.loadSource(src)
    hls.attachMedia(video)
    hls.on(Hls.Events.ERROR, (_, data) => {
      if (!data.fatal) return
      if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls.startLoad()
      else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls.recoverMediaError()
      else hls.destroy()
    })
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = src // Safari, iOS
  } else {
    video.outerHTML = '<p>This browser cannot play HLS video.</p>'
  }
</script>

동영상 객체에는 커버 이미지용 links.poster와 마우스 오버 미리보기 썸네일용 links.sprite도 들어 있어, 탐색 바를 직접 만들 때 활용할 수 있습니다. hls.js를 쓰면 UFOLOAD 플레이어가 대신 해 주던 기능, 즉 화질 메뉴, 챕터, 자막 선택, 로고 오버레이, 그리고 광고가 제공되는 경우의 광고를 포기하게 됩니다. 이것이 실제 트레이드오프이며, 아래 표에 정리했습니다.

iframe과 hls.js 중 무엇을 쓸까

질문iframe 플레이어페이지의 hls.js
설정 시간1분, 복사해서 붙여 넣기1시간 이상, 그리고 작은 서버 엔드포인트
플레이어 기능화질 메뉴, 챕터, 자막, 마우스 오버 미리보기, 로고, 제공 시 광고직접 만드는 만큼
수익화광고가 제공되면 플레이어에서 표시되고 집계됨불가능. 광고 계층이 UFOLOAD 플레이어에 있기 때문
스타일Player studio에서 스킨, 색상, 로고, 버튼 설정원하는 HTML과 CSS 무엇이든
링크 만료자동으로 처리됨페이지를 렌더링할 때마다 새 링크 요청
도메인 잠금허용된 임베드 도메인이 적용됨직접 제공하는 링크에는 적용되지 않으므로 짧은 TTL과 IP 또는 쿠키 바인딩 사용

문제 해결 체크리스트

  • 검은 화면 또는 끝없이 도는 로딩 표시. 브라우저 네트워크 패널을 열고 master.m3u8을 찾아보세요. 403이면 링크가 만료되었거나 시청자가 국가 또는 IP 규칙으로 차단된 것이니 새 링크를 요청하세요.
  • HTTPS 페이지에서 브라우저가 차단함. 모든 것이 HTTPS여야 합니다. iframe이나 hls.js에 http:// 주소를 절대 넣지 마세요.
  • 자동 재생이 되지 않음. 소리가 있는 자동 재생은 브라우저가 차단합니다. mute=1을 추가하거나, hls.js에서는 play()를 호출하기 전에 video.muted = true를 설정하세요.
  • 동영상 대신 처리 중 안내가 표시됨. 파일이 아직 준비되지 않았습니다. status가 ready가 될 때까지 GET /files/{id}를 주기적으로 호출하세요.
  • 낮은 화질만 재생됨. 플레이어는 보수적으로 시작하고 처리량을 측정하는 즉시 화질을 올립니다. 요금제와 원본도 최고 렌디션을 제한하므로 요금제와 기능 페이지와 비교해 보세요.

페이지가 잘 동작하면 핫링크로부터 보호하거나, 광고가 제공되는 경우 수익을 내고 싶어질 수 있습니다. 두 가지 모두 다음 가이드에서 다룹니다: 동영상 임베드 위치 제한하기, 플레이어 광고로 동영상 사이트 수익화하기. 아직 어디에 호스팅할지 고민 중이라면 동영상 호스팅 체크리스트에 비교할 항목이 정리되어 있습니다.

무료 계정으로 사용해 보세요

동영상을 업로드하고 몇 분 만에 HLS 플레이어와 API 키를 받으세요. 요금제 한도는 요금제 페이지에 나와 있습니다.