# Scheduled Channel

Scheduled Channel은 사전 녹화된 파일을 스케줄링하여 라이브 채널을 생성할 수 있는 기능입니다. 다른 서비스나 소프트웨어에서는 이를 Pre-recorded Live 또는 File Live라고 부르기도 하지만, OvenMediaEngine은 라이브 채널을 하나의 소스로 구성하는 기능으로 확장할 계획이기 때문에 Scheduled Channel이라는 이름을 사용합니다.

## Getting Started

이 기능을 사용하려면 다음과 같이 Schedule Provider를 활성화해야 합니다.

```xml
<!-- /Server/VirtualHosts/VirtualHost/Applications/Application -->
<Providers>
    ...
    <Schedule>
        <MediaRootDir>/opt/ovenmediaengine/media</MediaRootDir>
        <ScheduleFilesDir>/opt/ovenmediaengine/media</ScheduleFilesDir>
    </Schedule>
    ...
</Providers>
```

* `<MediaRootDir>`: 미디어 파일이 위치한 루트 경로입니다. 상대 경로를 지정할 경우 설정 파일이 위치한 디렉토리를 기준으로 합니다.
* `<ScheduleFileDir>`: 스케줄 파일이 위치한 루트 경로입니다. 상대 경로를 지정할 경우 설정 파일이 위치한 디렉토리를 기준으로 합니다.

## Schedule Files

Scheduled Channel은 `ScheduleFileDir` 경로에 `.sch` 확장자를 가진 파일을 생성/수정/삭제함으로써 스트림을 생성/업데이트/삭제합니다. `.sch` 파일은 다음과 같은 XML 형식을 사용합니다. `{Stream Name}.sch` 파일이 생성되면 OvenMediaEngine은 이를 분석하여 `{Stream Name}`이라는 Scheduled Channel을 생성합니다. 파일 내용이 변경되면 채널이 업데이트되며, 파일이 삭제되면 스트림도 삭제됩니다.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Schedule>
    <Stream>
        <Name>tv1</Name> <!-- optional, using filename without ext -->
        <BypassTranscoder>false</BypassTranscoder>
        <VideoTrack>true</VideoTrack>
        <AudioTrack>true</AudioTrack>
        <AudioMap> <!-- optional, only needed if you want to enable multilingual audio -->
            <Item>
                <Name>English</Name>
                <Language>en</Language>
            </Item>
            <Item>
                <Name>Korean</Name>
                <Language>ko</Language>
            </Item>
            <Item>
                <Name>Japanese</Name>
                <Language>ja</Language>
            </Item>
        </AudioMap>
    </Stream>

    <FallbackProgram> <!-- Not yet supported -->
        <Item url="file://sample.mp4" start="0" duration="60000" />
    </FallbackProgram>

    <Program name="1" scheduled="2023-09-27T13:21:15.123+09:00" repeat="true">
        <Item url="stream://default/app/stream1" duration="60000" />
    </Program>
    <Program name="2" scheduled="2022-03-14T15:10:0.0+09:00" repeat="true">
        <Item url="file://sample.mp4" start="0" duration="60000" />
        <Item url="stream://default/app/stream1" duration="60000" /> <!-- Not yet supported -->
        <Item url="file://sample.mp4" start="60000" duration="120000" />
    </Program>
</Schedule>
```

* `<Stream>` (필수): 채널 생성에 필요한 스트림 정보를 정의합니다.
* `<Stream>/<Name>` (선택): 스트림 이름입니다. 파일 이름에서 추출된 참조 값이며, 일관성을 위해 동일하게 설정하는 것이 권장됩니다.
* `<Stream>/<BypassTranscoder>` (선택, 기본값: false): 트랜스코딩을 수행하지 않으려면 true로 설정합니다.
* `<Stream>/<VideoTrack>` (선택, 기본값: true): 비디오 트랙 사용 여부를 설정합니다. true인데 Item에 비디오 트랙이 없으면 오류가 발생합니다.
* `<Stream>/<AudioTrack>` (선택, 기본값: true): 오디오 트랙 사용 여부를 설정합니다. true인데 Item에 오디오 트랙이 없으면 오류가 발생합니다.
* `<Stream>/<AudioMap>` (선택): 다국어 오디오를 사용하려면 설정합니다. 정의된 오디오 트랙 수보다 적은 트랙을 제공하면 오류가 발생하며, 더 많은 트랙이 제공되면 순서대로 매핑되고 나머지는 무시됩니다.
* `<FallbackProgram>` (선택): 현재 시점에 스케줄된 프로그램이 없거나 오류가 발생할 경우 자동으로 전환되는 프로그램입니다. 정상 상태로 돌아오면 원래 프로그램으로 복귀합니다. 파일과 라이브 모두 사용할 수 있지만 안정적인 파일 사용이 권장됩니다.
* `<Program>` (선택): 프로그램을 스케줄링합니다. `name`은 선택 값이며, 지정하지 않으면 자동 생성됩니다. `scheduled`에는 ISO8601 형식으로 시작 시간을 설정합니다. 재생 종료 후 반복 여부는 `repeat`로 설정합니다.
* `<Program>/<Item>` (선택): 방송할 미디어 소스를 정의합니다.
  * `url`은 미디어 소스의 위치를 의미합니다. `file://`로 시작하면 `<MediaRootDir>` 내부 파일을 의미하며, `stream://`로 시작하면 동일 OvenMediaEngine 내부 스트림을 의미합니다. 형식은 `stream://{VHost Name}/{App Name}/{Stream Name}`입니다.
  * `file`의 경우, `start` 속성은 파일 재생을 시작할 위치를 밀리초 단위로 설정할 수 있습니다.
    * `duration`은 해당 항목의 재생 시간을 밀리초 단위로 나타냅니다. duration이 끝나면 다음 항목으로 넘어갑니다.
    * `start`와 `duration`은 모두 선택 사항입니다. 설정하지 않으면 `start`는 기본값인 0이 되고, `duration`은 기본값인 파일의 전체 재생 시간이 사용됩니다. 지정하지 않으면 미디어 파일은 전체 재생 시간 동안 재생됩니다.

#### Supported Formats for File Live

<table><thead><tr><th width="216.6666259765625">Title</th><th>Description</th></tr></thead><tbody><tr><td>Formats</td><td><p>MP4, TS, MP3 등 다양한 포맷을 지원합니다.</p><ul><li>FFmpeg에서 지원하는 모든 포맷을 사용할 수 있습니다.</li></ul></td></tr></tbody></table>

## Multiple Audio Track

Scheduled Channel은 여러 개의 오디오 트랙을 지원하며, 이는 LLHLS Publisher에 자동 적용됩니다. `<AudioMap>` 설정을 통해 다중 오디오 트랙을 구성할 수 있습니다.

```xml
<?xml version="1.0"?>
<Schedule>
    <Stream>
        <Name>today</Name>
        <BypassTranscoder>false</BypassTranscoder>
        <VideoTrack>true</VideoTrack>
        <AudioTrack>true</AudioTrack>
        <AudioMap>
            <Item>
                <Name>English</Name>
                <Language>en</Language> <!-- Optioanl, RFC 5646 -->
                <Characteristics>public.accessibility.describes-video</Characteristics> <!-- Optional -->
            </Item>
            <Item>
                <Name>Korean</Name>
                <Language>ko</Language> <!-- Optioanl, RFC 5646 -->
                <Characteristics>public.alternate</Characteristics> <!-- Optional -->
            </Item>
            <Item>
                <Name>Japanese</Name>
                <Language>ja</Language> <!-- Optioanl, RFC 5646 -->
                <Characteristics>public.alternate</Characteristics> <!-- Optional -->
            </Item>
        </AudioMap>
    </Stream>
</Schedule>
```

{% hint style="warning" %}
Scheduled Channel은 파일 또는 다른 스트림의 트랙을 복사하여 스트림을 생성하므로, 다중 오디오를 사용하는 경우 모든 소스는 정의된 오디오 트랙 수 이상을 제공해야 합니다. 그렇지 않으면 스케줄링이 실패합니다.
{% endhint %}

## Application: Persistent Live Channel

이 기능은 스케줄링 채널이지만, 다음과 같이 항상 유지되는 스트림을 구성하는 데 사용할 수 있습니다.

```xml
<?xml version="1.0"?>
<Schedule>
    <Stream>
        <Name>stream</Name>
        <BypassTranscoder>false</BypassTranscoder>
        <VideoTrack>true</VideoTrack>
        <AudioTrack>true</AudioTrack>
    </Stream>
    <FallbackProgram>
        <Item url="file://hevc.mov" />
        <Item url="file://avc.mov" />
    </FallbackProgram>

    <Program name="origin" scheduled="2000-01-01T20:57:00.000+09" repeat="true">
        <Item url="stream://default/app/input" duration="-1" />
    </Program>
</Schedule>
```

이 채널은 기본적으로 `default/app/input`을 재생하지만, 라이브 입력이 중단되면 `<FallbackProgram>`의 파일을 재생합니다. `.sch` 파일이 삭제되기 전까지 계속 유지됩니다. 항상 재생되도록 하기 위해 시작 시간을 과거(예: 2000년)로 설정하는 방법을 사용할 수 있습니다.

{% hint style="warning" %}
파일에서 라이브로 전환될 때 일부 버퍼링이 발생할 수 있습니다. 이는 기능 특성과 저지연 구조로 인해 불가피합니다. 이를 완화하려면 LLHLS의 `PartHoldBack` 값을 5 이상으로 설정하여 약간의 지연을 추가하면 버퍼링을 줄일 수 있습니다. 이는 지연과 버퍼링 간의 트레이드오프입니다.
{% endhint %}

## REST API

ScheduledChannel은 API를 통해서도 제어할 수 있습니다. 자세한 내용은 아래 페이지를 참고하시기 바랍니다.

{% content-ref url="/pages/5vrBx3uYobAuALazI6FI" %}
[Scheduled Channel](/guide/ko-kr/features/rest-api/v1/virtual-host/application/scheduled-channel.md)
{% endcontent-ref %}


---

# 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/scheduled-channel.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.
