Потоки
Полный жизненный цикл потока через API — список, снимок, создание, правка, удаление, старт, стоп, рестарт, клонирование, сессии и метрики.
Операции над потоками делятся на две группы, и путать их дорого.
- Чтения рантайма (
GET /streams,GET /streams/{id},/timeseries,/sessions) видят только работающие потоки. Остановленного потока для них не существует — будет 404. - Операции над конфигурацией (создание, правка, удаление, старт, стоп, клонирование,
GET /streams/{id}/config) работают с файломhastreamer.conf: они дописывают, меняют или убирают блокstream, после чего конфигурация применяется целиком.
Единственное исключение — POST /streams/{id}/restart: он пересоздаёт поток в рантайме и
конфигурацию не трогает.
Общие правила для всех примеров (BASE, TOKEN, кодирование идентификатора, форма ошибок) — на
странице Введение и аутентификация.
Чтение#
GET /api/v1/streams#
Чтение — подходят сессия администратора, токен записи или токен чтения.
Пагинированный список работающих потоков. Фильтрация и сортировка выполняются на сервере одним
проходом по готовому снимку. Выключенных потоков здесь нет — их даёт
GET /config/streams.
Параметры запроса
| Параметр | Тип и допустимые значения | По умолчанию | Смысл |
|---|---|---|---|
limit |
целое 1 … 50000 |
100 |
размер страницы |
page |
целое ≥ 1 | — | номер страницы |
cursor |
значение next_cursor |
— | keyset-курсор |
fields |
имена полей через запятую | все | проекция элементов |
sort |
до 4 ключей колонка[:asc|desc] |
id |
сортировка |
dir |
asc | desc |
asc |
направление по умолчанию |
ids |
идентификаторы через запятую | — | точечная выборка |
q |
подстрока без учёта регистра | — | поиск по id и меткам |
label |
строка | — | точное совпадение метки |
health |
ok | degraded | failing | absent |
— | фильтр по здоровью |
status |
live | idle | down |
— | фильтр по состоянию |
min_viewers |
целое ≥ 0 | — | не меньше указанного числа зрителей |
Сортируемые колонки: id, viewers, bytes_in, packets_in, started_ms, core, dvr_viewers,
health (порядок ok < degraded < failing < absent), alive, bitrate, fps, packets_in_per_s.
curl -sS "$BASE/api/v1/streams?fields=id,health,viewers,bitrate,fps&sort=viewers:desc&limit=2" \ -H "Authorization: Bearer $TOKEN"
{"items":[{"bitrate":2920000.0,"fps":25.0,"health":"ok","id":"cam1","viewers":1}, {"bitrate":3455232.76,"fps":15.0,"health":"ok","id":"cam2","viewers":0}], "limit":2,"next_cursor":"18446744073709551615\u001fcam2","page":null, "raw_total":10,"total":10,"total_pages":5}
Ошибки
| Код | Когда |
|---|---|
304 |
тело не изменилось с момента, зафиксированного в If-None-Match |
401 |
нет действительных учётных данных |
GET /api/v1/streams/counts#
Чтение
Счётчики для вкладок и виджетов: сколько потоков в каждом состоянии и каждой категории здоровья.
Учитываются фильтры q и label, но не status и health — иначе каждая вкладка показывала бы
собственную же выборку.
curl -sS "$BASE/api/v1/streams/counts" -H "Authorization: Bearer $TOKEN"
{"total":10, "health":{"ok":9,"degraded":0,"failing":1,"absent":0}, "status":{"live":10,"idle":0,"down":0}, "cameras":{"total":0,"live":0,"degraded":0,"failing":0}}
GET /api/v1/streams/{id}#
Чтение
Полный снимок одного работающего потока: источник, дорожки, счётчики приёма, здоровье, аудитория.
Дополнительно к полям списка приходят caps — протоколы, которые узел реально отдаёт для этого
потока, — и default_proto.
Параметры пути
| Параметр | Смысл |
|---|---|
id |
идентификатор потока одним percent-encoded сегментом (live%2Fcam1); литеральный / отвергается |
curl -sS "$BASE/api/v1/streams/cam1" -H "Authorization: Bearer $TOKEN"
{"id":"cam1","alive":true,"health":"ok","health_reasons":[],"core":0, "started_ms":1787139151213,"source_connected_ms":1787139151213, "viewers":1,"dvr_viewers":0,"bitrate":2920000.0,"fps":25.0, "bytes_in":4648839146,"fragments":18488,"samples":102712, "no_data_secs":0,"ingest_latency_ms":0,"reconnects":0, "input_loss":0,"input_errors":0,"input_discontinuities":0, "dts_jumps":0,"dts_backwards":0,"dts_stuck":0, "on_demand":false,"flow":"continuous","source_error":null, "audio_codec":"mp4a.40.2","meta":{"codec":"avc1.64001F","width":1280,"height":720}, "caps":["hls","hls-ll","mse-ws","dash","webrtc","dvr","timeshift","preview"], "default_proto":"hls", "tracks":[{"kind":"video","codec":"H.264","codec_string":"avc1.64001F", "width":1280,"height":720,"profile":"High","level":"3.1", "bitrate_kbps":2894.08,"num_ref_frames":2}]}
Ошибки
| Код | Когда |
|---|---|
401 |
нет действительных учётных данных |
404 |
потока нет или он остановлен |
Рантайм-снимок знает только запущенные потоки. Чтобы увидеть сконфигурированный, но не работающий
поток, читайте GET /streams/{id}/config (один поток) или
GET /config/streams (весь список).
GET /api/v1/streams/{id}/config#
Чтение
Конфигурация одного потока: сырое тело блока stream и его разобранная модель. Читает движок
конфигурации, а не рантайм, поэтому работает и для остановленного или выключенного потока. Именно
поэтому маршрут существует рядом с GET /streams/{id}. Чтение никогда не попадает в журнал аудита.
curl -sS "$BASE/api/v1/streams/cam1/config" -H "Authorization: Bearer $TOKEN"
{"path":"cam1","disabled":false, "directives":"input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101;\n dvr local 6h 20G;", "config":{"path":"cam1","disabled":false, "source":"rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101", "storage":"local","record":true, "retention_time":"6h","retention_size":"20G", "labels":[],"on_demand":false,"allowed_referers":[],"restream":[]}}
Примечания. Поле directives — то, что вы отправите обратно в
PATCH /streams/{id}. Поле config — удобная для чтения модель; отправлять
обратно её нельзя.
GET /api/v1/streams/{id}/timeseries#
Чтение
Серверное кольцо метрик потока в нескольких разрешениях, наполняемое раз в секунду.
Параметры запроса
| Параметр | Тип и допустимые значения | По умолчанию | Смысл |
|---|---|---|---|
range |
1m | 5m | 1h | 24h |
1m |
ярус разрешения; неизвестное значение молча читается как 1m |
curl -sS "$BASE/api/v1/streams/cam1/timeseries?range=5m" -H "Authorization: Bearer $TOKEN"
{"id":"cam1","core":0,"started_ms":1787139151213, "range":"5m","cadence_s":5,"cap":60, "samples":[{"ts":4050548,"bitrate":2920000,"fps":25.0,"viewers":1,"packets_in_per_s":0}, {"ts":4055550,"bitrate":2918000,"fps":25.0,"viewers":1,"packets_in_per_s":0}]}
ts — это не настенное времяПоле ts каждого отсчёта — миллисекунды от старта потока, а не Unix-время. Абсолютный момент
получается как started_ms + ts.
Ошибки
| Код | Когда |
|---|---|
401 |
нет действительных учётных данных |
404 |
поток не запущен |
GET /api/v1/streams/{id}/sessions#
Чтение
Зрительские сессии одного потока — то же, что общий список сессий, но поток зафиксирован путём.
Если передать ещё и параметр stream, победит путь.
Параметры запроса
| Параметр | Тип и допустимые значения | По умолчанию | Смысл |
|---|---|---|---|
limit, page, cursor, fields, sort, dir |
как у списка потоков | — | пагинация и сортировка |
proto |
строка | — | точное совпадение протокола |
q |
подстрока без учёта регистра | — | поиск по протоколу, User-Agent, адресу клиента и субъекту авторизации |
min_bytes |
целое | — | сессии, отдавшие не меньше указанного числа байт |
Сортируемые колонки: id, bytes_out, connected_ms, last_access_ms, fragments_out,
packets_out, rr_fraction_lost, lag_events, protocol, stream.
curl -sS "$BASE/api/v1/streams/cam1/sessions?sort=bytes_out:desc&limit=1" \ -H "Authorization: Bearer $TOKEN"
{"items":[{"id":13,"stream":"cam1","core":0,"protocol":"hls-fmp4", "connected_ms":1787143172091,"last_access_ms":1787143231071, "client_ip":"10.0.0.55","user_agent":"Mozilla/5.0 …", "fragments_out":41,"bytes_out":7364410,"packets_out":0, "rr_fraction_lost":0,"rr_jitter_us":0,"rr_rtt_us":0,"lag_events":0}], "limit":1,"next_cursor":null,"page":null, "raw_total":1,"total":1,"total_pages":1}
Жизненный цикл#
Все операции этой группы правят конфигурацию: перед записью весь файл разбирается заново, и правка, которая ломает конфигурацию, отвергается кодом 422, не попав на диск.
POST /api/v1/streams#
Запись — сессия администратора или api_write_token.
Дописывает в конфигурацию новый блок stream и применяет её. Успех — 201.
Тело запроса
| Поле | Тип | Обязательно | Смысл |
|---|---|---|---|
path |
строка | да | идентификатор потока; он же путь в URL зрителя |
directives |
строка | нет | тело блока stream целиком, директивы через ; и перевод строки |
curl -sS -X POST "$BASE/api/v1/streams" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"path":"live/cam1", "directives":"input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101;\n dvr local 6h 20G;"}'
{"epoch":12,"hash":"4a186afe976f6ef3","path":"live/cam1","changed":true}
Ошибки
| Код | Тело | Когда |
|---|---|---|
400 |
{"title":"bad request","detail":"need \"path\""} |
в теле нет ключа path |
403 |
{"error":"forbidden","reason":"read_token_cannot_write"} |
предъявлен токен чтения |
409 |
{"title":"conflict","detail":"stream \"live/cam1\" already exists"} |
идентификатор занят |
413 |
— | тело больше 1 МиБ |
422 |
{"title":"invalid config","detail":"unknown directive \"sourse\" in stream \"live/cam1\""} |
директива не разобралась |
423 |
{"title":"config locked"} |
рядом с конфигурацией лежит <config>.locked |
501 |
{"title":"config mutation unavailable (no config file)"} |
сервер запущен без файла конфигурации |
Директивы внутри directives — та же грамматика, что в hastreamer.conf. Полный список —
Справочник конфигурации. Сомнительный кандидат целиком можно прогнать
через POST /config/validate, ничего не записывая.
PATCH /api/v1/streams/{id}#
Запись
Заменяет тело блока stream целиком.
Всё, чего нет в переданной строке directives, из конфигурации исчезнет. Чтобы поменять один
параметр, сначала прочитайте текущее тело
GET /streams/{id}/config, измените его и отправьте целиком.
Тело запроса
| Поле | Тип | Обязательно | Смысл |
|---|---|---|---|
directives |
строка | да | новое тело блока целиком |
curl -sS -X PATCH "$BASE/api/v1/streams/live%2Fcam1" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"directives":"input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101;\n dvr local 24h 100G;\n on_demand;"}'
{"epoch":13,"hash":"9f2c11a70bd4e650","path":"live/cam1","changed":true}
Ошибки
| Код | Когда |
|---|---|
400 |
в теле нет ключа directives |
403 |
предъявлен токен чтения |
404 |
потока нет в конфигурации |
413 |
тело больше 1 МиБ |
422 |
итоговая конфигурация не разбирается |
423 |
конфигурация заморожена |
501 |
сервер запущен без файла конфигурации |
DELETE /api/v1/streams/{id}#
Запись
Убирает блок stream из конфигурации и применяет её.
curl -sS -X DELETE "$BASE/api/v1/streams/live%2Fcam1" \ -H "Authorization: Bearer $TOKEN"
{"epoch":14,"hash":"62b8ff41c07d935a","path":"live/cam1","changed":true}
Удаление потока не трогает его записи DVR. Освобождать место нужно отдельно — см. Просмотр и экспорт.
Ошибки
| Код | Когда |
|---|---|
403 |
предъявлен токен чтения |
404 |
потока нет в конфигурации |
422 |
итоговая конфигурация не разбирается |
423 |
конфигурация заморожена |
501 |
сервер запущен без файла конфигурации |
POST /api/v1/streams/{id}/stop#
Запись
Ставит в блоке потока флаг disabled и применяет конфигурацию. После этого поток исчезает из
GET /streams, но остаётся в GET /config/streams — оттуда его
можно запустить снова.
curl -sS -X POST "$BASE/api/v1/streams/live%2Fcam1/stop" \ -H "Authorization: Bearer $TOKEN"
{"epoch":15,"hash":"7c3e15b09ad2f846","path":"live/cam1","changed":true}
POST /api/v1/streams/{id}/start#
Запись
Снимает флаг disabled и применяет конфигурацию.
curl -sS -X POST "$BASE/api/v1/streams/live%2Fcam1/start" \ -H "Authorization: Bearer $TOKEN"
{"epoch":16,"hash":"3d90aa27e6c418bb","path":"live/cam1","changed":true}
Оба маршрута переписывают файл, поднимают версию (epoch) и попадают в журнал аудита. Поэтому они
блокируются файлом <config>.locked (423) и недоступны на сервере, запущенном без файла
конфигурации (501).
Ошибки для start и stop
| Код | Когда |
|---|---|
403 |
предъявлен токен чтения |
404 |
потока нет в конфигурации |
422 |
итоговая конфигурация не разбирается |
423 |
конфигурация заморожена |
501 |
сервер запущен без файла конфигурации |
POST /api/v1/streams/{id}/restart#
Запись
Пересоздаёт поток в рантайме без правки конфигурации: переподключение к источнику с теми же настройками. Основной инструмент, когда камера «залипла», а конфигурация верна.
curl -sS -X POST "$BASE/api/v1/streams/live%2Fcam1/restart" \ -H "Authorization: Bearer $TOKEN"
{"path":"live/cam1","restarted":true}
Примечания. Ответ не содержит ни epoch, ни hash — версия конфигурации не менялась. Маршрут
не блокируется файлом <config>.locked: замороженная конфигурация запрещает правки, а рестарт
правкой не является. Зрители текущих сессий этого потока будут отключены.
Ошибки
| Код | Когда |
|---|---|
403 |
предъявлен токен чтения |
501 |
сервер запущен без файла конфигурации |
POST /api/v1/streams/{id}/clone#
Запись
Создаёт новый поток с телом блока, скопированным из указанного без изменений. Успех — 201.
Тело запроса
| Поле | Тип | Обязательно | Смысл |
|---|---|---|---|
path |
строка | да | идентификатор нового потока |
curl -sS -X POST "$BASE/api/v1/streams/live%2Fcam1/clone" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"path":"live/cam2"}'
{"epoch":17,"hash":"d9b4d2d2a819ff24","path":"live/cam2","changed":true}
Тело блока переносится дословно, включая директиву input. Сразу после клонирования два потока
будут забирать видео с одной камеры. Отредактируйте новый поток
PATCH /streams/{id} прежде, чем оставлять его работать.
Ошибки
| Код | Когда |
|---|---|
400 |
в теле нет целевого path |
403 |
предъявлен токен чтения |
404 |
исходного потока нет в конфигурации |
409 |
целевой идентификатор занят |
422 |
итоговая конфигурация не разбирается |
423 |
конфигурация заморожена |
501 |
сервер запущен без файла конфигурации |
Сводная таблица#
| Действие | Метод и путь | Правит конфигурацию | Есть у остановленного потока |
|---|---|---|---|
| Список работающих | GET /streams |
нет | нет |
| Счётчики | GET /streams/counts |
нет | нет |
| Снимок | GET /streams/{id} |
нет | нет |
| Конфигурация потока | GET /streams/{id}/config |
нет | да |
| Ряд метрик | GET /streams/{id}/timeseries |
нет | нет |
| Сессии потока | GET /streams/{id}/sessions |
нет | нет |
| Создать | POST /streams |
да | — |
| Заменить блок | PATCH /streams/{id} |
да | да |
| Удалить | DELETE /streams/{id} |
да | да |
| Остановить | POST /streams/{id}/stop |
да | — |
| Запустить | POST /streams/{id}/start |
да | да |
| Перезапустить | POST /streams/{id}/restart |
нет | нет |
| Клонировать | POST /streams/{id}/clone |
да | да |
Все изменяющие операции попадают в журнал аудита; чтения — никогда.