One Click Multi DRM

Naver Cloud Platform의 One Click Multi DRM을 사용해 Widevine, PlayReady, FairPlay를 한 번에 구성할 수 있습니다. 아래 예제는 DRM 테스트 API를 호출해 옵션을 주입하는 방식입니다.

테스트 플레이어

아래 플레이어는 DRM 테스트 API로부터 옵션을 받아 재생하는 샘플입니다. 브라우저에 따라 Widevine, PlayReady, FairPlay 중 지원되는 DRM이 자동 선택됩니다.

DRM 옵션 로딩 중...

Naver Cloud Platform One Click Multi DRM 예제

https://vpe.sgrsoft.com/api/drmTest 엔드포인트를 호출해 DRM 정보를 받아온 뒤 플레이어 옵션으로 전달합니다.

"use client";

import Hls from "hls.js";
import dashjs from "dashjs";
import { VpePlayer } from "@sgrsoft/vpe-react-sdk";
import { useEffect, useState } from "react";

export default function OneClickMultiDrmExample() {
    const [options, setOptions] = useState<any>(null);

    useEffect(() => {
        fetch("https://vpe.sgrsoft.com/api/drmTest")
            .then((res) => res.json())
            .then((data) => setOptions(data));
    }, []);

    if (!options) {
        return <div className="text-sm text-neutral-500">DRM 옵션 로딩 중...</div>;
    }

    return (
        <VpePlayer
            accessKey="YOUR_ACCESS_KEY"
            hls={Hls}
            dashjs={dashjs}
            options={options}
        />
    );
}

[Backend] Ncloud DRM Helper 설치

npm i vpe-drm-helper
  • Ncloud DRM Helper는 DRM 재생소스를 생성하는데 사용됩니다.
  • Ncloud API Key가 사용됩니다.
  • Ncloud Sub Account를 사용하여 DRM 전용 API Key를 생성하여 사용합니다.
  • 재생소스 생성 작업은 반드시 Backend에서 처리해야 합니다.

[Backend] Ncloud DRM Server 구현

import express from 'express';
import vpeDrmHelper from 'vpe-drm-helper';

const app = express();
const port = 3000;

// DRM Helper 설정
const NDRM = new vpeDrmHelper();
NDRM.isGov = false; // 공공클라우드 사용 여부 설정 (기본값 : false)

NDRM.setUserId('test-user'); // 시청자 아이디
NDRM.setSiteId('{SITEID}'); // One Click Multi DRM Site ID 설정
NDRM.setApiKey('{Ncloud API accessKey}', '{Ncloud API secretKey}'); // 네이버클라우드 플랫폼 ACCESS KEY, SECRET KEY 설정

// DRM 소스를 생성하는 API 엔드포인트
app.get('/drm-source', (req, res) => {
    const drmSource = NDRM.drmSourceHelper({
        dash: '{DASH 재생소스}',
        hls: '{HLS 재생소스}',
    }, '{contentId}'); // contentId 필수, VOD Station, LIVE Station에서 확인 및 설정 가능

    res.json(drmSource);
});

app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});
  • 이 코드는 Express.js를 사용하여 간단한 서버를 설정하고 /drm-source 경로에서 DRM 소스를 생성하여 반환하는 API를 제공합니다.
  • accessKey, secretKey, SITEID, DASH 재생소스, HLS 재생소스, contentId는 실제 값으로 대체해야 합니다.
  • 이 서버를 실행하려면 Node.js와 npm이 설치되어 있어야 하며, vpe-drm-helper 패키지를 설치해야 합니다.

⚠️ {SITEID} / {contentId}는 DRM 라이선스 토큰 생성시 필요합니다. 외부에 노출되면 안됩니다.

⚠️ API 키는 DRM 권한만 추가된 키를 사용해야합니다. 절대로 Master API 키를 사용하지 마세요.

응답 JSON 구조

{
  "playlist": [
    {
      "drm": {
        "com.widevine.alpha": {
          "src": "https://8kmgeiox5271.edge.naverncp.com/dash/~Mm2B8LV1K~dMoZUnpjc4g__/endpoint/sample/221027_NAVER_Cloud_intro_Long_ver_AVC_FHD_2Pass_30fps.mp4/manifest.mpd",
          "licenseUri": "https://multi-drm.apigw.ntruss.com/api/v1/license",
          "licenseRequestHeader": {
            "x-ncp-region_code": "KR",
            "x-ncp-iam-access-key": "ncp_iam_BPASKRX9k5Z9dX3VryI4",
            "x-ncp-apigw-timestamp": 1770471614859,
            "x-ncp-apigw-signature-v2": "ow6caa/GO5/39BVtec1cnh3px0PFUX1OJWHi8D+/nNA=",
            "x-drm-token": "eyJzaXRlSWQiOiJkcm0tMjAyNDA4MjYxMzE1MjgtVmpWeXIiLCJjb250ZW50SWQiOiJ2cGUtc2FtcGxlLXZvZC1kcm0iLCJkcm1UeXBlIjoiV0lERVZJTkUiLCJyZXNwb25zZUZvcm1hdCI6Im9yaWdpbmFsIiwidXNlcklkIjoidGVzdC11c2VyIn0="
          }
        },
        "com.microsoft.playready": {
          "src": "https://8kmgeiox5271.edge.naverncp.com/dash/~Mm2B8LV1K~dMoZUnpjc4g__/endpoint/sample/221027_NAVER_Cloud_intro_Long_ver_AVC_FHD_2Pass_30fps.mp4/manifest.mpd",
          "licenseUri": "https://multi-drm.apigw.ntruss.com/api/v1/license",
          "licenseRequestHeader": {
            "x-ncp-region_code": "KR",
            "x-ncp-iam-access-key": "ncp_iam_BPASKRX9k5Z9dX3VryI4",
            "x-ncp-apigw-timestamp": 1770471614859,
            "x-ncp-apigw-signature-v2": "ow6caa/GO5/39BVtec1cnh3px0PFUX1OJWHi8D+/nNA=",
            "x-drm-token": "eyJzaXRlSWQiOiJkcm0tMjAyNDA4MjYxMzE1MjgtVmpWeXIiLCJjb250ZW50SWQiOiJ2cGUtc2FtcGxlLXZvZC1kcm0iLCJkcm1UeXBlIjoiUExBWVJFQURZIiwicmVzcG9uc2VGb3JtYXQiOiJvcmlnaW5hbCIsInVzZXJJZCI6InRlc3QtdXNlciJ9"
          }
        },
        "com.apple.fps": {
          "src": "https://8kmgeiox5271.edge.naverncp.com/hls/~Mm2B8LV1K~dMoZUnpjc4g__/endpoint/sample/221027_NAVER_Cloud_intro_Long_ver_AVC_FHD_2Pass_30fps.mp4/index.m3u8",
          "certificateUri": "https://multi-drm.apigw.ntruss.com/api/v1/license/fairPlay",
          "certificateRequestHeader": {
            "x-ncp-region_code": "KR",
            "x-ncp-iam-access-key": "ncp_iam_BPASKRX9k5Z9dX3VryI4",
            "x-ncp-apigw-timestamp": 1770471614859,
            "x-ncp-apigw-signature-v2": "PT8KABJiB0YAzIwfbVyDmJYloQfeCCQ8l51MkmB+9t0=",
            "x-drm-token": "eyJzaXRlSWQiOiJkcm0tMjAyNDA4MjYxMzE1MjgtVmpWeXIiLCJjb250ZW50SWQiOiJ2cGUtc2FtcGxlLXZvZC1kcm0iLCJkcm1UeXBlIjoiRkFJUlBMQVkiLCJyZXNwb25zZUZvcm1hdCI6Im9yaWdpbmFsIiwidXNlcklkIjoidGVzdC11c2VyIn0=",
            "accept": "application/json"
          },
          "licenseUri": "https://multi-drm.apigw.ntruss.com/api/v1/license",
          "licenseRequestHeader": {
            "x-ncp-region_code": "KR",
            "x-ncp-iam-access-key": "ncp_iam_BPASKRX9k5Z9dX3VryI4",
            "x-ncp-apigw-timestamp": 1770471614859,
            "x-ncp-apigw-signature-v2": "ow6caa/GO5/39BVtec1cnh3px0PFUX1OJWHi8D+/nNA=",
            "x-drm-token": "eyJzaXRlSWQiOiJkcm0tMjAyNDA4MjYxMzE1MjgtVmpWeXIiLCJjb250ZW50SWQiOiJ2cGUtc2FtcGxlLXZvZC1kcm0iLCJkcm1UeXBlIjoiRkFJUlBMQVkiLCJyZXNwb25zZUZvcm1hdCI6Im9yaWdpbmFsIiwidXNlcklkIjoidGVzdC11c2VyIn0="
          }
        }
      },
      "poster": "https://2ardrvaj2252.edge.naverncp.com/endpoint/sample/221027_NAVER_Cloud_intro_Long_ver_01.jpg",
      "description": {
        "title": "네이버클라우드 테스트 영상",
        "created_at": "2024.07.13",
        "profile_name": "네이버클라우드",
        "profile_image": "https://player.vpe.naverncp.com/images/d127c8db642716d84b3201f1d152e52a.png"
      }
    }
  ],
  "aspectRatio": "16/9",
  "autostart": true,
  "muted": true
}
React