SIRINVIDEO Документация администратора и интегратора На сайт 2026.08

Запись архива (DVR)

Как включить непрерывную запись потока на диск, задать глубину архива и убедиться, что запись действительно идёт.

Архив (DVR) — непрерывная запись живого потока на диск с возможностью потом отмотать назад, посмотреть любой момент и выгрузить фрагмент файлом. Запись ведётся из того же кольцевого буфера, из которого идёт раздача: поток разбирается один раз, отдельного разбора «для архива» нет.

Запись — это факт конфигурации, а не команда#

Начать и остановить запись через API нельзя, и такого эндпоинта нет. Поток пишется, потому что в его блоке есть строка dvr, и перестаёт писаться, когда эту строку убирают, когда поток помечен disabled;, либо когда служба останавливается.

Следствия, которые стоит принять сразу:

  • Чтобы включить или выключить запись — правьте конфигурацию (файл, панель управления или PATCH /api/v1/streams/{id}) и применяйте изменения.
  • Изменение строки dvr перезапускает только этот поток; остальные потоки продолжают работать и не теряют зрителей. Подробнее — Применение изменений.
  • Директива on_demand на пишущем потоке игнорируется. Запись означает «тянуть источник всегда»: «писать только когда смотрят» дало бы архив с дырами.

Как включить запись одному потоку#

Шаг 1. Объявите хранилище#

Хранилище — это именованный каталог на диске, куда складываются записи. Один раз на весь сервер:

storage archive /var/lib/hastreamer/dvr;

Каталог должен существовать и быть доступен на запись пользователю, от имени которого запущена служба hastreamer.service. Полный набор параметров хранилища, вытеснение по заполнению диска и холодный ярус S3 — на странице Хранилища и S3.

Шаг 2. Добавьте строку dvr в поток#

stream cam1 {
  input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101;
  dvr archive 14d 500G;
}

Читается так: «писать в хранилище archive, хранить 14 дней или 500 ГиБ — что наступит раньше».

Шаг 3. Примените изменения#

# разобрать файл, ничего не запуская: при ошибке печатается строка с её номером
hastreamer --validate /etc/hastreamer/hastreamer.conf
# применить: перезапустится только изменённый поток
systemctl reload hastreamer

Запись начинается сразу после перезапуска потока — ждать чего-либо не нужно.

Синтаксис директивы dvr#

dvr <хранилище> [<глубина>] [<объём>] [copy=<ссылка-s3> [<глубина-s3>] [<объём-s3>]];

Аргументы позиционные, но распознаются по форме, а не по месту: сервер смотрит на вид слова и понимает, что это. Поэтому dvr archive 500G 14d; и dvr archive 14d 500G; — одно и то же.

Параметр Тип и допустимые значения По умолчанию Применение
<хранилище> имя объявленного локального дискового хранилища — (обязателен) горячее
<глубина> число + s · m · h · d · w · mo · y без ограничения горячее
<объём> число + K · M · G · T (двоичные, только заглавные) без ограничения горячее
copy= s3://<бакет>@<аккаунт> либо s3s://<бакет>@<аккаунт> (TLS) нет копии горячее
mode= async · cross — режим репликации кластера горячее
<узел>/<том> цель репликации в кластере горячее

Хранилище обязательно всегда, когда запись включена. Без него конфигурация не примется:

stream "cam1": record needs a known local DISK storage (got "archiv"); use copy= for an s3 cold tier

Аргументы mode= и <узел>/<том> относятся к работе нескольких серверов; на одиночном сервере они не действуют.

Два имени подряд — побеждает последнее, молча

dvr archive fast 14d; — это не «пиши в оба хранилища». Второе имя просто перетирает первое, и запись пойдёт в fast без единого предупреждения. Один поток пишется ровно в одно локальное хранилище (плюс, при желании, одна копия в S3 через copy=).

Единственное место, где порядок значим, — copy=: глубина и объём до него относятся к диску, после — к архиву в S3.

dvr fast 2h 3G copy=s3s://cam-archive@coldtier 30d 100G;

Здесь на диске держатся последние 2 часа (не более 3 ГиБ), а в S3 — 30 дней (не более 100 ГиБ). Настройка холодного яруса разобрана на странице Хранилища и S3.

Единицы глубины#

Суффикс Значение
s секунды
m минуты
h часы
d сутки
w недели
mo месяцы — фиксированные 30 суток, не календарный месяц
y годы — фиксированные 365 суток
m — это минуты, а не месяцы

dvr archive 30m; хранит тридцать минут видео, а не тридцать месяцев. Ошибка не даёт ни предупреждения при разборе, ни сообщения в журнале: конфигурация полностью корректна, просто архив оказывается короче ожидаемого в десятки тысяч раз — и это выясняется в тот день, когда запись понадобилась. Месяцы пишутся mo: dvr archive 30mo;.

Объём задаётся суффиксами K, M, G, Tдвоичные (×1024) и только заглавные. 500g, 500GB и 500Gi — ошибки разбора:

stream "cam1": bad retention_size "500GB" (K/M/G/T)
stream "cam1": bad retention_time "14days" (s/m/h/d/w/mo/y)

Пропущенное значение (или 0) означает «без ограничения по этому измерению». Оставлять без ограничений оба измерения можно, но тогда за место на диске отвечает только вытеснение по заполнению — см. ниже.

Как глубина и объём работают вместе#

Ограничения не выбирают между собой — они применяются подряд, в фиксированном порядке:

  1. Удаляются все записи, чей конец старше <глубина>.
  2. Из того, что осталось, удаляются самые старые, пока суммарный размер превышает <объём>.

На практике это значит «сработает то ограничение, которое наступит раньше». Полезный приём: задайте глубину по требованиям регламента, а объём — как страховку от неожиданно выросшего битрейта.

Последняя запись не удаляется никогда

Самая свежая завершённая запись потока не удаляется ни по возрасту, ни по размеру. Поток нельзя вычистить до полной пустоты — даже если глубина 1s, а объём 1K.

Длительность записи и что лежит на диске#

Записи режутся на файлы фиксированной целевой длительности, которая задаётся на хранилище, а не на потоке, — параметром segment_secs. Допустимы только три значения: 900 (по умолчанию), 1800 и 3600 секунд.

Рез всегда происходит по ключевому кадру, поэтому реальный файл получается чуть длиннее целевой величины: при segment_secs 900; фактическая длина обычно около 900–905 с. Досрочный рез происходит при смене параметров кодирования и при разрыве непрерывности потока.

Раскладка на диске:

<путь-хранилища>/<поток>/ГГГГ/ММ/ДД/ЧЧ-ММ-СС-мкс_d<мс>.mp4
<путь-хранилища>/<поток>/ГГГГ/ММ/ДД/ЧЧ-ММ-СС-мкс_d<мс>.mp4.idx

Время в имени — UTC, с точностью до микросекунды. Рядом с каждым файлом лежит .idx — индекс, благодаря которому перемотка по архиву мгновенна. Файл, в который прямо сейчас идёт запись, не имеет суффикса _d: суффикс появляется в момент, когда запись закрыта, проверена и внесена в каталог. Поэтому незавершённая запись физически не может попасть ни в выдачу, ни под удаление.

Не удаляйте файлы архива вручную

Каталог архива — не просто набор .mp4. Удаление файла без его .idx (или наоборот) оставляет запись, которую сервер не сможет ни отдать, ни корректно вычистить. Для очистки архива потока используйте DELETE /api/v1/dvr-archive/{поток} или уменьшите глубину и дождитесь прохода обслуживания.

Что происходит при исчерпании места#

Защита эшелонирована — на потоке и на хранилище:

  1. Ретенция потока. Записи cam1 вытесняются по его собственным <глубина>/<объём>. Один разросшийся поток не трогает соседей.
  2. Вытеснение по заполнению хранилища. Если файловая система пересекла порог evict_at_percent (по умолчанию 90 %), проход обслуживания удаляет самые старые записи по всем потокам этого хранилища, пока заполнение не опустится на 2 процентных пункта ниже порога. Подробнее — Хранилища и S3.
  3. Реакция на «диск полон». Если запись упёрлась в ENOSPC, проход обслуживания просыпается досрочно (в пределах ~2 с) и первым делом освобождает место.

Запись никогда не тормозит приём потока: медленный или полный диск не создаёт обратного давления на источник. Если запись не поспевает, в архиве возникает видимый разрыв непрерывности — при просмотре он выглядит как стык между записями, а не как порча файла.

Задержка очистки#

Удаление устаревших записей выполняет фоновый проход обслуживания. Его период задаётся глобально:

Параметр Тип и допустимые значения По умолчанию Применение
dvr_cleanup_secs целое, секунды 600 рестарт
dvr_cleanup_secs 600;

Отсюда практическое следствие: архив может отставать от заданной глубины на один такт. При значениях по умолчанию поток с dvr archive 6h; какое-то время держит 6 часов и ещё до 10 минут сверху. Это нормально и не считается ошибкой. Уменьшать период ради «точности» не нужно — проход сканирует каталоги всех хранилищ, и частые проходы стоят дороже, чем несколько лишних минут видео.

Проход выполняется на отдельном системном потоке, вне ядер, обслуживающих зрителей, поэтому на раздачу он не влияет.

Проверка: запись действительно идёт#

Три команды — достаточно любой из них

Сводка по хранилищу — в поле streams тройки [поток, число записей, байт]:

curl -sS "http://media.example.com:8080/api/v1/storages" \
  -H "Authorization: Bearer $TOKEN"
[{"name":"archive","path":"/var/lib/hastreamer/dvr","identity":"","identity_healthy":true,
  "maintenance_healthy":true,"total_bytes":84444717056,"used_bytes":31178297344,
  "avail_bytes":53266419712,"evict_at_percent":90,
  "streams":[["cam1",21,21012998324]],
  "write_bps":1441369,"tier_backlog_bytes":0,"s3_healthy":true}]

Календарь записанных суток (UTC):

curl -sS "http://media.example.com:8080/cam1/dvr/api/days"
{"days":["2026-08-19"]}

Покрытие за последний час — если запись идёт, end_ms растёт от вызова к вызову:

curl -sS "http://media.example.com:8080/cam1/dvr/api/timeline"
{"from":1787139386390,"to":1787142986390,
 "ranges":[{"start_ms":1787139151495,"end_ms":1787142986427,
            "segment_count":5,"bytes":4348353497,"tier":"local"}]}

Если запись не включена, тот же запрос отвечает 404 с телом stream is not recorded — это однозначный ответ «в конфигурации потока нет строки dvr», а не «архив пуст».

Если включена авторизация просмотра

Примеры выше показаны без токена — так они работают на сервере без auth_backend { }. Когда авторизация просмотра настроена, запросам к /<поток>/dvr/… нужен токен с правом dvr; API /api/v1/… всегда требует Authorization: Bearer $TOKEN. См. Авторизация просмотра.

В панели управления те же факты видны без командной строки: страница Storage показывает заполнение и крупнейшие записи, а на карточке потока вкладка DVR — покрытие, число записей и календарь. Вкладка появляется только у пишущих потоков.

Куда двигаться дальше#