# WebRTC / WHIP

사용자는 별도의 플러그인 없이 웹 브라우저를 통해 WebRTC를 사용하여 OvenMediaEngine으로 비디오 및 오디오를 전송할 수 있습니다. 또한 브라우저뿐만 아니라 WebRTC 전송을 지원하는 모든 인코더를 미디어 소스로 사용할 수 있습니다.

<table><thead><tr><th width="216.6666259765625">Item</th><th>Description</th></tr></thead><tbody><tr><td>Container</td><td>RTP / RTCP</td></tr><tr><td>Security</td><td>DTLS, SRTP</td></tr><tr><td>Transport</td><td>ICE</td></tr><tr><td>Error Correction</td><td>ULPFEC (VP8, H.264), In-band FEC (Opus)</td></tr><tr><td>Codec</td><td>VP8, H.264, H.265, Opus</td></tr><tr><td>Signaling</td><td>Self-Defined Signaling Protocol, Embedded WebSocket-based Server / WHIP</td></tr><tr><td>Additional Features</td><td>Simulcast</td></tr></tbody></table>

## Configuration

### Bind

OvenMediaEngine는 WebRTC 입력을 위해 자체 정의된 시그널링 프로토콜과 [WHIP](https://datatracker.ietf.org/doc/draft-ietf-wish-whip/)을 지원합니다.

```xml
<!-- /Server/Bind -->
<Providers>
    ...
    <WebRTC>
        ...
        <Signalling>
            <Port>3333</Port>
            <TLSPort>3334</TLSPort>
        </Signalling>
        <IceCandidates>
            <TcpRelay>*:3478</TcpRelay>
            <TcpForce>false</TcpForce>
            <IceCandidate>*:10000-10005/udp</IceCandidate>
        </IceCandidates>
        ...
    </WebRTC>
    ...
</Providers>
```

`/<Server>/<Bind>/<Provider>/<WebRTC>/<Signalling>/<Port>`에서 시그널링에 사용할 포트를 설정할 수 있습니다. `<Port>`는 암호화되지 않은 HTTP 포트이며, `<TLSPort>`는 TLS로 암호화된 HTTPS 포트를 설정하는 데 사용됩니다.

WebRTC 입력을 위해서는 `<IceCandidates>`에 OvenMediaEngine 서버의 ICE 후보를 설정해야 합니다. `<IceCandidate>`에 설정된 값은 WebRTC 피어에게 전달되며, 피어는 해당 후보를 통해 통신을 시도합니다. 따라서 피어가 접근 가능한 IP를 설정해야 합니다. IP를 `*`로 지정하면 서버의 모든 IP를 수집하여 피어에게 전달합니다.

`<TcpRelay>`는 OvenMediaEngine에 내장된 TURN 서버를 의미합니다. 이 기능이 활성화되면 해당 TURN 서버 주소가 자체 시그널링 프로토콜 또는 WHIP를 통해 피어에게 전달되며, 피어는 TCP를 통해 이 TURN 서버와 통신합니다. 이를 통해 OvenMediaEngine은 WebRTC/TCP를 자체적으로 지원할 수 있습니다. URL 설정에 대한 자세한 내용은 [WebRTC over TCP](/guide/ko-kr/features/live-source/webrtc-whip.md#webrtc-over-tcp)를 참조하세요.

### Application

WebRTC 입력은 각 애플리케이션 단위로 활성화하거나 비활성화할 수 있습니다. 아래 설정은 해당 애플리케이션에서 WebRTC 입력 기능을 활성화합니다. `<CrossDomains>` 설정은 WebRTC 시그널링에서 사용됩니다.

```xml
<!-- /Server/VirtualHosts/VirtualHost/Applications/Application -->
<Providers>
    ...
    <WebRTC>
        <Timeout>30000</Timeout>
        <FIRInterval>3000</FIRInterval>
        <RtcpBasedTimestamp>false</RtcpBasedTimestamp>
        <CrossDomains>
            <Url>*</Url>
        </CrossDomains>
    </WebRTC>
    ...
</Providers>
```

<table><thead><tr><th width="217">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Timeout</code></td><td>연결 끊김으로 인해 세션이 종료되기 전에 ICE 바인딩 요청/응답을 기다리는 최대 시간(밀리초)입니다.</td></tr><tr><td><code>FIRInterval</code></td><td>송신자에게 IDR 프레임 생성을 강제하기 위해 전체 인트라 요청(FIR)을 전송하는 간격(밀리초)입니다(이 값을 0으로 설정하면 요청이 비활성화됩니다).</td></tr><tr><td><code>RtcpBasedTimestamp</code></td><td><code>false</code> (기본값)로 설정하면 각 트랙의 RTP 타임스탬프는 RTCP 송신자 보고서를 기다리지 않고 0부터 독립적으로 계산됩니다. <code>true</code>로 설정하면 RTCP 송신자 보고서를 사용하여 오디오/비디오 타임스탬프를 공통 클럭으로 동기화합니다. 송신자가 RTCP 송신자 보고서를 안정적으로 전송하는 것으로 확인된 경우에만 <code>true</code>로 설정하십시오. 그렇지 않으면 첫 번째 송신자 보고서를 기다리는 동안 스트림 시작이 최대 5초까지 지연될 수 있습니다.</td></tr><tr><td><code>CrossDomain</code></td><td>CORS (Cross-Origin Resource Sharing) 정책을 준수하여 시그널링 요청에 허용되는 도메인을 지정합니다.</td></tr></tbody></table>

## URL Pattern

OvenMediaEngine는 WebRTC 입력을 위해 자체 시그널링 프로토콜과 WHIP를 지원합니다.

### Self-defined Signaling URL

WebRTC 입력을 위한 시그널링 URL은 재생용 URL과 구분하기 위해 다음과 같이 `?direction=send` 쿼리 문자열을 사용합니다. 자체 정의 WebRTC 시그널링 프로토콜은 WebSocket 기반이므로 `ws` 또는 `wss` 스킴을 사용해야 합니다.

> `ws[s]://<OME Host>[:Signaling Port]/<App Name>/<Stream Name>`**`?direction=send`**

### WHIP URL

WHIP 클라이언트를 통해 입력할 경우, 아래와 같이 시그널링 URL의 쿼리 문자열에 `?direction=whip`를 추가해야 합니다. WHIP는 HTTP 기반이므로 `http` 또는 `https` 스킴을 사용해야 합니다.

> `http[s]://<OME Host>[:Signaling Port]/<App Name>/<Stream Name>`**`?direction=whip`**

### WebRTC over TCP

WebRTC 전송은 패킷 손실에 매우 민감하며, 이는 해당 스트림을 시청하는 모든 플레이어에 영향을 줍니다. 따라서 WebRTC 전송을 TCP 기반으로 제공하는 것이 권장됩니다.

OvenMediaEngine은 WebRTC/TCP를 위한 내장 TURN 서버를 제공하며, 플레이어의 TURN 클라이언트가 TURN 서버에 연결한 TCP 세션을 그대로 사용하여 스트림을 송수신합니다. WebRTC/TCP를 사용하려면 다음과 같이 URL에 `transport=tcp` 쿼리를 추가합니다. 자세한 내용은 [WebRTC/tcp playback](/guide/ko-kr/features/streaming-and-distribution/webrtc-streaming.md)을 참조하세요.

> `ws[s]://{OME Host}[:{Signaling Port}]/{App Name}/{Stream Name}`**`?direction=send&transport=tcp`**
>
> `http[s]://{OME Host}[:{Signaling Port}]/{App Name}/{Stream Name}`**`?direction=whip&transport=tcp`**

{% hint style="warning" %}
WebRTC/TCP를 사용하려면 `<Bind>` 설정에서 `<TcpRelay>`가 활성화되어 있어야 합니다.

`<TcpForce>`를 `true`로 설정하면 URL에 `?transport=tcp`를 명시하지 않아도 TCP로 동작합니다.
{% endhint %}

## Simulcast

Simulcast는 송신자가 서버 인코더에 의존하지 않고 여러 품질 레이어를 동시에 전송할 수 있는 기능입니다. 이 기능을 통해 제한된 서버 리소스 환경에서도 비용을 줄이면서 고품질 스트리밍을 제공할 수 있습니다.

OvenMediaEngine은 v0.18.0부터 WebRTC Simulcast를 지원합니다. 다만 Simulcast는 WHIP 시그널링에서만 지원되며, OvenMediaEngine 자체 시그널링에서는 지원되지 않습니다.

WHIP와 Simulcast를 지원하는 인코더(예: OvenLiveKit, OBS)를 사용하여 테스트할 수 있으며, 일반적으로 레이어 수를 설정할 수 있습니다. 또한 OvenLiveKit API를 직접 사용할 경우 레이어별 해상도 및 비트레이트를 설정할 수 있습니다.

<figure><img src="/files/ecjBLS0cHj7s0PGKBGzg" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/bFekEWmPuOXgHJdjIQZH" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/iGCliC8EsCcDIKSZvT2k" alt=""><figcaption></figcaption></figure>

### Playlist Template for Simulcast

여러 개의 입력 비디오 트랙이 존재하는 경우, 동일한 Variant Name을 가진 여러 트랙이 생성됩니다. 예를 들어 아래와 같은 기본 `<OutputProfile>`에서 입력 비디오 트랙이 3개라면 `video_bypass`라는 Variant Name을 가진 트랙이 3개 생성됩니다.

```xml
<!-- /Server/VirtualHosts/VirtualHost/Applications/Application -->
<OutputProfiles>
    ...
    <OutputProfile>
        <Name>stream</Name>
        <OutputStreamName>${OriginStreamName}</OutputStreamName>
        <Encodes>
            <Video>
                <Name>video_bypass</Name>
                <Bypass>true</Bypass>
            </Video>
        </Encodes>
    </OutputProfile>
    ...
</OutputProfiles>
```

여러 트랙을 가진 플레이리스트를 구성하기 위해 `Index` 개념을 사용할 수 있습니다.

<pre class="language-xml"><code class="lang-xml">&#x3C;!-- /Server/VirtualHosts/VirtualHost/Applications/Application/OutputProfiles -->
<strong>&#x3C;OutputProfile>
</strong><strong>    ...
</strong>    &#x3C;Playlist>
        &#x3C;Name>simulcast&#x3C;/Name>
        &#x3C;FileName>template&#x3C;/FileName>
        &#x3C;Options>
            &#x3C;WebRtcAutoAbr>true&#x3C;/WebRtcAutoAbr>
            &#x3C;HLSChunklistPathDepth>0&#x3C;/HLSChunklistPathDepth>
            &#x3C;EnableTsPackaging>true&#x3C;/EnableTsPackaging>
        &#x3C;/Options>
        &#x3C;Rendition>
            &#x3C;Name>first&#x3C;/Name>
            &#x3C;Video>video_bypass&#x3C;/Video>
            &#x3C;VideoIndexHint>0&#x3C;/VideoIndexHint> &#x3C;!-- Optional, default : 0 -->
            &#x3C;Audio>aac_audio&#x3C;/Audio>
        &#x3C;/Rendition>
        &#x3C;Rendition>
            &#x3C;Name>second&#x3C;/Name>
            &#x3C;Video>video_bypass&#x3C;/Video>
            &#x3C;VideoIndexHint>1&#x3C;/VideoIndexHint> &#x3C;!-- Optional, default : 0 -->
            &#x3C;Audio>aac_audio&#x3C;/Audio>
            &#x3C;AudioIndexHint>0&#x3C;/AudioIndexHint> &#x3C;!-- Optional, default : 0 -->
        &#x3C;/Rendition>
    &#x3C;/Playlist>
    ...
&#x3C;/OutputProfile>
</code></pre>

`<VideoIndexHint>`와 `<AudioIndexHint>`는 각각 입력 비디오 및 오디오 트랙의 인덱스를 지정합니다.

그러나 위와 같은 방식은 Simulcast로 3개의 비디오 트랙을 송출하는 경우, HLS/WebRTC 스트리밍을 위해 서버를 재시작하고 설정을 변경해야 하는 불편함이 있습니다. 이를 해결하기 위해 동적 Rendition 생성 기능인 RenditionTemplate가 제공됩니다.

### RenditionTemplate

`<RenditionTemplate>` 기능은 지정된 조건에 따라 Rendition을 자동으로 생성하여, 각각을 수동으로 정의할 필요를 제거합니다.

```xml
<!-- /Server/VirtualHosts/VirtualHost/Applications/Application/OutputProfiles -->
<OutputProfile>
    ...
    <Playlist>
        <Name>template</Name>
        <FileName>template</FileName>
        <Options>
            <WebRtcAutoAbr>true</WebRtcAutoAbr>
            <HLSChunklistPathDepth>0</HLSChunklistPathDepth>
            <EnableTsPackaging>true</EnableTsPackaging>
        </Options>
        <RenditionTemplate>
            <Name>hls_${Height}p</Name>
            <VideoTemplate>
                <EncodingType>bypassed</EncodingType>
            </VideoTemplate>
            <AudioTemplate>
                <VariantName>aac_audio</VariantName>
            </AudioTemplate>
        </RenditionTemplate>
    </Playlist>
    ...
</OutputProfile>
```

이 설정은 모든 bypass 비디오에 대해 Rendition을 생성하고, `aac_audio` Variant Name을 가진 오디오 트랙을 사용합니다.\
`RenditionTemplate`의 Name에는 다음과 같은 매크로를 사용할 수 있습니다:\
`${Width}`, `${Height}`, `${Bitrate}`, `${Framerate}`, `${Samplerate}`, `${Channel}`

조건을 지정하여 Rendition 생성 대상을 제어할 수 있습니다. 예를 들어 최소 해상도 280p 이상, 비트레이트 500kbps 이상만 포함하거나, 1080p 또는 2Mbps를 초과하는 비디오를 제외하도록 설정할 수 있습니다.

```xml
<!-- /Server/VirtualHosts/VirtualHost/Applications/Application/OutputProfiles/OutputProfile/Playlist -->
<RenditionTemplate>
    <VideoTemplate>
        <EncodingType>bypassed</EncodingType> <!-- all, bypassed, encoded -->
        <VariantName>bypass_video</VariantName>
        <VideoIndexHint>0</VideoIndexHint>
        <MaxWidth>1080</MaxWidth>
        <MinWidth>240</MinWidth>
        <MaxHeight>720</MaxHeight>
        <MinHeight>240</MinHeight>
        <MaxFPS>30</MaxFPS>
        <MinFPS>30</MinFPS>
        <MaxBitrate>2000000</MaxBitrate>
        <MinBitrate>500000</MinBitrate>
    </VideoTemplate>
    <AudioTemplate>
        <EncodingType>encoded</EncodingType> <!-- all, bypassed, encoded -->
        <VariantName>aac_audio</VariantName>
        <MaxBitrate>128000</MaxBitrate>
        <MinBitrate>128000</MinBitrate>
        <MaxSamplerate>48000</MaxSamplerate>
        <MinSamplerate>48000</MinSamplerate>
        <MaxChannel>2</MaxChannel>
        <MinChannel>2</MinChannel>
        <AudioIndexHint>0</AudioIndexHint>
    </AudioTemplate>
    ...
</RenditionTemplate>
```

## WebRTC Producer

WebRTC 입력을 쉽게 테스트할 수 있도록 데모 페이지가 제공됩니다. 아래 URL에서 접근할 수 있습니다.

{% embed url="<https://demo.ovenplayer.com/demo_input.html>" %}

<figure><img src="/files/cHV1ow2b7vSTQursrZ8b" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
getUserMedia API는 보안 컨텍스트에서만 동작하므로, WebRTC 입력 데모 페이지는 HTTPS 환경에서만 정상 동작합니다. 따라서 OvenMediaEngine에 인증서를 설치하고 `wss` 시그널링 URL을 사용해야 합니다.

만약 인증서를 설치할 수 없는 경우, 브라우저에서 demo.ovenplayer.com의 비보안 콘텐츠를 허용하여 임시로 테스트할 수 있습니다.
{% endhint %}

### Self-defined WebRTC Ingest Signaling Protocol

사용자 정의 WebRTC Producer를 구현하려면 OvenMediaEngine의 자체 정의 시그널링 프로토콜 또는 WHIP를 구현해야 합니다. 자체 정의 프로토콜은 간단한 구조를 가지며 [WebRTC 스트리밍과 동일한 방식](/guide/ko-kr/features/streaming-and-distribution/webrtc-streaming.md#signalling-protocol)으로 동작합니다.

<figure><img src="/files/QT0uNGunWul0OvEF1CFU" alt=""><figcaption></figcaption></figure>

플레이어가 WebSocket을 통해 ws\[s]://host:port/app/stream?**direction=send**에 연결하고 request offer 명령을 전송하면, 서버는 offer SDP로 응답합니다. URL의 쿼리 스트링에 `transport=tcp`가 존재할 경우 offer SDP에 [iceServers](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) 정보가 포함되는데, 여기에는 OvenMediaEngine에 내장된 TURN 서버 정보가 들어있으므로 WebRTC/TCP를 사용하려면 `RTCPeerConnection`에 이를 설정해야 합니다. 그런 다음 플레이어는 offer SDP에 대해 `setRemoteDescription` 및 `addIceCandidate`를 수행하고, answer SDP를 생성하여 서버에 응답합니다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ovenmediaengine-enterprise.gitbook.io/guide/ko-kr/features/live-source/webrtc-whip.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
