Inserting SEI into H.264 (AVC) Streams | v0.18.0+

OvenMediaEngine은 라이브 스트림에 SEI(Supplemental Enhancement Information)를 삽입하여 프레임 단위의 정확도로 사용자 정의 데이터를 비디오 콘텐츠와 함께 전달할 수 있습니다.

개요

  • OvenMediaEngine의 Send Event API를 통해 동적으로, XML 설정을 통해 지속적으로 SEI를 삽입할 수 있습니다.

  • SEI 삽입 시 사용자 정의 데이터를 추가할 수 있으며 삽입된 SEI에는 UUID와 Timestamp가 자동으로 포함됩니다.

    • 삽입된 SEI는 UUID, Timestamp, 사용자 데이터를 포함한 OvenMediaEngine 전용 포맷으로 생성됩니다.

  • OvenPlayer는 OvenMediaEngine이 삽입한 SEI를 수신할 수 있으며 OvenMediaEngine이 정의한 SEI 규격을 자동으로 파싱하는 기능을 제공합니다.

Send Event API를 통한 SEI 삽입

API 인터페이스

OvenMediaEngine의 SendEvent REST API를 사용하면 동적으로 스트림에 SEI를 삽입하는 이벤트를 발생시킬 수 있습니다.

요청

POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvent

Header

Authorization: Basic {credentials}

# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>

Body

{
    "eventFormat": "sei",
    "eventType": "video",
    "events": [
        {
            "seiType": "UserDataUnregistered",
            "data": "OvenMediaEngine"
        }
    ]
}
POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvents

Header

Authorization: Basic {credentials}

# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>

Body

[
  {
      "eventFormat": "sei",
      "eventType": "video",
      "events": [
          {
              "seiType": "UserDataUnregistered",
              "data": "OvenMediaEngine"
          }
      ]
  }
]
Parameter
Required
Description

eventFormat

Y

이벤트 형식을 지정합니다. (sei 형식 사용)

eventType

N

이벤트 타입을 지정합니다. (video형식 사용)

events

Y

이벤트 데이터 값을 포함합니다.

event.seiType

N

SEI 타입을 지정합니다 (UserDataUnregistered 형식 사용)

event.data

Y

실제 전송할 데이터를 입력합니다.

응답

200 Ok

Header

Content-Type: application/json

Body

{
    "message": "OK",
    "statusCode": 200
}
400 Bad Request

Header

Content-Type: application/json

Body

{
    "message": "eventFormat(string) and events(array) are required",
    "statusCode": 400
}
{
    "message": "eventFormat is not supported: [XXX]",
    "statusCode": 400
}
{
    "message": "Could not make events data",
    "statusCode": 400
}
{
    "message": "eventType must be string",
    "statusCode": 400
}
{
    "message": "eventType is not supported: [XXX]",
    "statusCode": 400
}
500 Internal Server Error

Header

Content-Type: application/json

Body

{
    "message": "Could not inject event: [XXX]",
    "statusCode": 500
}

XML설정을 통한 SEI 삽입

지속적인 SEI 삽입이 필요한 시나리오의 경우, XML 설정을 통해 이 동작을 구성할 수 있습니다. SEI삽입 이벤트를 정의한 XML파일을 생성하고 Server.xml에서 EventGenerator를 활성화 합니다.

설정 예제

Server.xml: <Application><EventGenerator>를 추가하여 SEI삽입을 위한 EventGenerator기능을 활성화 할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<Server version="8">
  ...
  <VirtualHosts>
    <VirtualHost>
      <Applications>
        <Application>
          ...
          <EventGenerator>
            <Enable>true</Enable>
            <Path>events/send_event_info.xml</Path>
          </EventGenerator>
        </Application>
      </Applications>
    </VirtualHost>
  </VirtualHosts>
</Server>
Element
Required
Description

<Enable>

Y

true 도는 false로 활성화 여부를 설정합니다.

<Path>

Y

SEI삽입 상세를 정의한 XML 파일의 경로를 설정합니다. 상대 경로를 지정하면 Server.xml파일이 있는 디렉토리가 기준이 됩니다.

SEI삽입 이벤트를 정의한 XML: Server.xml에서 정의한 경로에 SEI삽입 이벤트를 정의한 XML파일을 생성합니다. 예제의 경우 send_event_info.xml입니다.

<?xml version="1.0" encoding="UTF-8"?>
<EventInfo>
  <Event>
    <Enable>true</Enable>
    <SourceStreamName>stream*</SourceStreamName>
    <Interval>2000</Interval>
    <EventFormat>sei</EventFormat>
    <EventType>video</EventType>
    <Values>
      <SeiType>UserDataUnregistered</SeiType>
      <Data>OvenMediaEngine</Data>
    </Values>
  </Event>
</EventInfo>
매개변수
Required
설명

<Enable>

Y

true 도는 false로 활성화 여부를 설정합니다.

<SourceStreamName>

Y

대상 스트림 이름을 지정합니다. 패턴 매칭을 위한 와일드카드(*)를 지원합니다.

<Interval>

Y

이벤트 발생 주기를 밀리초(ms) 단위로 설정합니다.

<EventFormat>

Y

이벤트 형식을 지정합니다. (sei 형식 사용)

<EventType>

N

이벤트 타입을 지정합니다. (video형식 사용)

<Values><SeiType>

N

SEI 타입을 지정합니다. (UserDataUnregistered 형식 사용)

<Values><Data>

Y

실제 전송할 데이터를 입력합니다.

이벤트 정의 XML 파일의 내용을 변경하면 OvenMediaEngine을 재시작하지 않아도 변경 사항이 바로 적용됩니다.

OvenMediaEngine-Specific SEI Payload Data 규격

OvenMediaEngine이 생성한 SEI의 페이로드는 다음과 같은 구조로 UUID, Timestamp 값이 항상 포함되어 있습니다.

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| uuid_iso_iec_11578(128)                                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timestamp (64)                                                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data (Payload Size - UUID(128) - Timestamp(64))               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ...                                                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Field
Size (bits)
Description

UUID

128

SEI Payload가 OvenMediaEngine이 정의한 규격임을 나타내는 값입니다. 항상 464d4c47-5241-494e-434f-4c4f554201입니다.

Timestamp

64

Epoch time in milliseconds

Data

사용자 정의 데이터에 따라 다름

사용자 정의 데이터

SEI 데이터 수신

OvenPlayer는 OvenMediaEngine이 삽입한 SEI를 파싱해서 포함되어있는 UUID, TimeStamp, 사용자 정의 데이터를 어플리케이션에 전달할 수 있습니다.

코드 예제

var player = OvenPlayer.create('player', {
  sources: [
    {
      type: 'webrtc', // WebRTC 스트림 재생
      file: 'wss://[YOUR_OvenMediaEngine]:3333/app/stream'
    }
  ],
  parseStream: {
    enabled: true // H.264 NAL 파싱 활성화
  }
});

function toAsciiString(byteArray) {
  return String.fromCharCode.apply(null, byteArray);
}

player.on('metaData', function (metadata) {
  console.log('MetaData:', metadata);
  /* 출력:
    {
      type: 'sei',
      nalu: Unit8Array(33),
      sei: {
        type: 5,
        size: 39,
        payload: Unit8Array(39)
      },
      registered: true,
      uuid: '464d4c47-5241-494e-434f-4c4f-55524201',
      timecode: 1739851602778,
      userdata: Unit8Array(15)
    }
  */

  console.log(`사용자 데이터 문자열 변환: ${toAsciiString(metadata.userdata)}`);
  /* 출력:
    사용자 데이터 문자열 변환: OvenMediaEngine
  */
});

플레이어 초기화:

  • OvenPlayer.create() 함수를 호출하여 지정된 div에 플레이어를 생성합니다.

  • sources 배열에서 재생할 스트림의 유형과 URL을 지정합니다. SEI는 WebRTC 스트림에서만 지원됩니다.

  • parseStream.enabled: true 설정을 통해 H.264의 NAL(Network Abstraction Layer)파싱을 활성화합니다. 이는 SEI 메타데이터 처리를 위한 필수 설정입니다.

SEI 데이터 처리:

  • player.on('metaData', callback) 이벤트 리스너를 등록하여 SEI가 수신될 때마다 처리합니다.

  • 이벤트 콜백에 전달되는 파라메터에서 OvenMediaEngine이 삽입한 UUID, Timestamp, 사용자 정의데이터를 얻어올 수 있습니다.

metaData 이벤트 콜백 파라메터

필드
설명

type

항상 sei로 설정되며, 이것이 SEI 메타데이터임을 나타냅니다.

nalu

SEI의 원시 NALU(Network Abstraction Layer Unit) 데이터를 포함하는 Uint8Array입니다.

sei

SEI파싱 결과로, 다음 하위 필드들을 포함합니다: - type: SEI 타입 - size: 페이로드 크기 - payload: 원시 SEI 페이로드 데이터 (Uint8Array)

registered

OvenMediaEngine에서 정의한 형식으로 SEI가 생성되었는지 여부를 나타냅니다. true인 경우 아래의 추가 필드들이 포함됩니다.

uuid

(registered=true인 경우) OvenMediaEngine이 SEI에 삽입한 고유 식별자입니다.

timecode

(registered=true인 경우) SEI가 삽입된 시점의 Timestamp(밀리초)입니다.

userdata

(registered=true인 경우) 사용자 정의 데이터가 포함된 Uint8Array입니다. 이 데이터는 애플리케이션의 요구에 맞게 파싱해야 합니다.

부록: OvenPlayer 설치하기

OvenPlayer 0.10.39 버전부터 WebRTC 스트림 재생 시 비디오에 포함된 SEI 데이터를 수신할 수 있습니다.

  1. OvenPlayer는 GitHub 릴리스 페이지에서 다운로드할 수 있습니다.

  2. 다운로드한 파일의 압축을 푼 후, dist 디렉토리 내의 모든 파일을 프로젝트의 라이브러리 폴더로 복사합니다:

├─.github
├─demo
├─dist
│      ovenplayer.js
│      ovenplayer.js.map
│      RTCTransformWorker.worker.worker.js
│      RTCTransformWorker.worker.worker.js.map
├─docs
├─packages
└─src

복사할 주요 파일:

  • ovenplayer.js: OvenPlayer 코어 라이브러리

  • RTCTransformWorker.worker.worker.js: WebRTC 처리를 위한 워커 스크립트

Web Worker의 CORS정책으로 인해 ovenplayer.js는 자체 호스팅이 되어야 하며, RTCTransformWorker.worker.worker.js 파일은 반드시 ovenplayer.js와 같은 경로에 존재해야 합니다.

Last updated