---
title: "频道与上游"
description: "配置频道与上游，了解各字段的作用，并完成启停、导入导出和播放前检查。"
---

> Documentation Index
> Fetch the complete documentation index at: https://kiln.wbxdocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 频道与上游

频道是 Kiln 的核心对象。每个频道由上游地址、输入格式和运行策略组成，对外提供一个播放地址，并在播放列表中占一行。下面按配置顺序介绍各个字段。

## 频道模型

### 标识与展示

- `id`：频道的唯一标识，出现在播放地址、播放列表的 `tvg-id` 属性和访问日志里。改动它等于换一条频道，播放器侧的收藏与记录都会失效。
- `title`：显示名称，留空时回退为 `id`。
- `group`：分组名，写进播放列表的 `group-title` 属性。
- `logo_url`：台标地址。留空且内置台标候选源命中时，播放列表会改指向 `/v1/logo/{id}`，由 Kiln 代取。
- `epg_id`、`epg_name`、`epg_source`：节目单匹配用的字段，`epg_name` 留空时取 `title`。详见 [节目单 EPG](/guide/epg/)。

### 节目源

节目源有两种写法，二选一：

- `upstream` + `path`：`upstream` 引用 `[[upstreams]]` 里的 `id`，`path` 拼接在该上游的 `base_url` 之后。`path` 以 `http://` 或 `https://` 开头时按绝对地址处理，不再拼接。
- `source_url`：直接写完整地址。填了它就不需要 `upstream` 与 `path`，并且该频道不会继承任何上游级请求头。

`ingress` 决定这条源怎么被处理，取值 `hls` 或 `dash`，留空按 `hls` 处理：

- `hls`：同源分片代理，播放列表在返回前被改写，分片按需回源。
- `dash`：按全局 `kid:key` 本地解密后重封装为 HLS。启用状态下的 DASH 频道要求 `[packager].keys_file` 已配置，否则保存时报错。

### 运行方式

- `on_demand`：无人观看时回收上游连接。打开后频道受空闲回收管辖。
- `autostart`：进程启动时主动拉起，不等第一个观众。
- `idle_timeout_sec`：空闲多久算无人观看，小于等于 0 时归一为 `90` 秒。只对 `on_demand` 频道生效。
- `max_viewers`：同时在看的观众上限。大于 0 时启用观众租约，超额的新观众收到 429；留空或 0 表示不限制。
- `restart_on_failure`：上游断流后自动重启。DASH 频道保存时会被强制打开。

两个开关组合出管理控制台里的三种运行方式：

| `autostart` | `on_demand` | 控制台标签 | 行为 |
| --- | --- | --- | --- |
| 关 | 开 | 有观众时启动 | 首个观众触发启动，空闲后回收 |
| 开 | 开 | 启动时预热 | 进程启动即拉起，空闲后仍会回收 |
| 开 | 关 | 始终运行 | 进程启动即拉起，不参与空闲回收 |

两个开关都关闭时，`on_demand` 会被自动打开，不存在既不预热也不按需的频道。

> **启动时的自动拉起**
>
> Kiln 启动时会检查数据库里的所有可用频道。因此，即使频道只在管理控制台中创建，只要打开了 `autostart`，重启后也会自动拉起。

### 媒体选择

以下字段只作用于 DASH 频道的重封装路径，HLS 频道走同源代理，不做轨道计划：

- `prefer_height`：目标分辨率高度。为 0 或留空时采用 `[ffmpeg].prefer_height`。
- `preferred_audio_languages`：按优先级排列的音轨语言代码数组，例如 `["zh", "en"]`。
- `selection`：更精确的轨道选择，可分别对视频、音频与字幕指定模式和具体轨道。
- `packager`：为当前频道指定封装引擎，取值与 `[packager].engine` 相同。留空时使用全局设置；填写其他值会导致配置校验失败。

#### 精确选择轨道

视频可设为自动选择、限制最高分辨率，或精确指定一条轨道；音频可按语言偏好选择，也可以只接受指定轨道；字幕还可以完全关闭。轨道可以按 `key`、语言、角色、编码、分辨率，或 DASH 中的 AdaptationSet 和 Representation ID 匹配。`exact` 与 `only` 要求填写轨道条件，否则配置校验会失败。

使用 `ffmpeg` 引擎时，字幕仅支持 `auto` 和 `off`。全部字段与取值见 [频道配置参考](/reference/config/#channelsselection)。

### 请求头

- `user_agent`：该频道回源时使用的 User-Agent。
- `headers`：该频道回源时附加的请求头。与上游级 `headers` 合并，同名键以频道级为准。

固定请求头只会发送到源地址的同源请求。跨域重定向与播放列表中的外部资源不会收到这些请求头；HTTPS 的 FFmpeg 兼容路径如果无法保证同源，会直接拒绝请求，避免凭据泄漏。

### 停用

`disabled` 为真的频道不会出现在频道列表与播放列表里，播放请求按找不到处理。停用状态下的 DASH 频道即使还没配置全局密钥文件也允许保存，方便先落盘再补密钥。

## 上游定义

上游只在配置文件里定义，用来让多条频道共享同一个源站的地址与凭据：

```toml
[[upstreams]]
id = "origin"
base_url = "http://127.0.0.1:5050"

[upstreams.headers]
X-Custom = "value"
```

- `id`：频道通过 `upstream` 字段引用它。
- `base_url`：源站基础地址，频道的 `path` 拼接在它后面。
- `headers`：注入到该上游所有频道回源请求里的请求头，频道级 `headers` 可以逐键覆盖。

对应的频道写法：

```toml
[[channels]]
id = "hls-demo"
title = "Demo HLS"
group = "Demo"
upstream = "origin"
path = "/live/demo-hls"
ingress = "hls"
on_demand = true
autostart = false
```

## 配置文件与管理控制台

两者不是同一份数据，边界值得记清楚：

- **频道**：只有在首次启动且频道表为空时，Kiln 才会把配置文件里的 `[[channels]]` 写入数据库。此后以数据库为准，改配置文件不会同步过去，也不会覆盖控制台里的改动。批量调整已有频道时，请使用控制台或管理接口。
- **上游**：`[[upstreams]]` 始终只从配置文件读取，控制台不能新增或修改上游。频道保存时会校验引用的 `upstream` 是否存在于配置里，不存在直接拒绝。
- **对外基础地址**：`server.public_base_url` 首次启动时写入设置表，之后以设置表为准，可以在控制台里改。
- **出站线路与 EPG 源**：同样只在首次启动时写入，之后以数据库为准。

`lite` 变体不创建数据库，频道完全来自配置文件且只读，管理接口不可用。

## 启用与停用

- 单条频道通过 `disabled` 字段启停，控制台的开关和管理接口都是改这个字段。
- 批量操作对应 `POST /v1/admin/channels/enable-all` 与 `POST /v1/admin/channels/disable-all`，需要 `write` 权限。
- 停用不会删除频道定义，也不会改变它在列表中的位置，但会立即停止当前播放会话，并让频道从对外列表中消失。

## M3U 导入导出

### 导入

导入分预览与应用两步，都走 `POST /v1/admin/import/m3u`，由请求里的 `apply` 决定。预览返回每一条的动作与原因，确认后再应用。

解析与生成规则：

- 读取 `#EXTINF` 行上的 `group-title`、`tvg-logo`、`tvg-id` 与 `tvg-name` 属性，以及行尾的标题。
- 频道 `id` 由 `tvg-id` 生成 slug，没有就用标题，再没有就用地址里的路径；重名依次追加 `-2`、`-3`，最长 48 个字符。
- 地址以 `.mpd` 结尾推断为 `dash`，其余为 `hls`。
- 导入的频道一律写 `source_url`，并清空 `upstream` 与 `path`。
- 新建的频道默认打开 `on_demand`，空闲超时 90 秒。
- 已存在同 `id` 的频道视为更新，只有非空字段才覆盖原值。
- 地址非法或校验不通过的条目会被跳过，并在预览结果里标注原因。
- 导入不会删除列表里没有出现的频道。
- 应用时会带上预览时读到的修订号，期间被别处改过的频道会让整批返回 409，避免覆盖他人改动。

### 导出

`POST /v1/admin/exports/m3u` 返回一份可直接给播放器的 M3U 文件。它会自动创建一枚不限频道范围的播放密钥，播放列表里所有地址都落在 `/p/{token}/play/` 前缀下，绝不嵌入管理员凭据。不再需要这份导出时，在控制台的「播放访问控制」里撤销对应密钥即可让它整体失效。

## 自检：warmup、probe 与 preview

三个接口经常被混用，但用途完全不同，都需要 `refresh` 权限。

1. **probe：只测源，不建会话**

   `POST /v1/admin/channels/{id}/probe` 对上游做一次探测，全程不创建会话、不产生媒体。HLS 频道拉取一次源地址、读取开头一小段，返回状态码、内容类型、最终地址与耗时；DASH 频道解析 manifest，按 `prefer_height` 与 `selection` 做一次轨道计划，并校验全局密钥是否配齐。控制台的新建页还能用 `POST /v1/admin/source-probes` 探测尚未保存的草稿。适合排查地址、请求头与线路是否通。
2. **warmup：提前拉起会话**

   `POST /v1/admin/channels/{id}/warmup` 在后台启动会话；频道已在运行时只刷新一次活跃时间。接口立刻返回 202，不等第一份播放列表就绪，所以它的成功只代表启动流程已经开始。用途是消掉按需频道的冷启动延迟。
3. **preview：拿一枚临时播放凭据**

   `POST /v1/admin/channels/{id}/preview` 签发一枚 5 分钟有效的预览凭据，返回带 `?token=` 的完整播放地址，供控制台内置播放器直接打开。预览凭据只能播放，调用任何管理接口都会被拒绝，因此可以安全地临时分享给同事验证画面。

排查顺序通常是 probe 先确认源可达，再 warmup 确认能起会话，最后 preview 确认画面正常。三步都过还有问题，转到 [故障排查](/guide/troubleshooting/)。

Source: https://kiln.wbxdocs.com/guide/channels/index.mdx
