Skip to content

Архитектура подсистемы записи и сериализации fMP4 ​

Подсистема записи (internal/recorder/) предназначена для непрерывного круглосуточного архивирования видео. Она преобразует сырые видеокадры из Ring Buffer в фрагментированные файлы MP4 (.mp4), соответствующие стандарту ISO BMFF.


1. Структура боксов фрагментированного MP4 (fMP4) ​

Традиционные MP4-файлы записывают индекс (moov) в самом конце файла. При внезапном отключении питания незакрытый файл невозможно открыть.

RUSEON Core формирует файлы fMP4 из независимых фрагментов:

text
┌────────────────────────────────────────────────────────────────────────┐
│ Инициализирующий сегмент                                               │
│   [ ftyp: isom/iso6/mp41 ] [ moov: trak / mdia / minf / avcC|hvcC ]    │
├────────────────────────────────────────────────────────────────────────┤
│ Фрагмент фильма #1 (GOP 1)                                             │
│   [ moof: mfhd / traf / tfhd / tfdt / trun ] [ mdat: Видео NALU ]      │
├────────────────────────────────────────────────────────────────────────┤
│ Фрагмент фильма #2 (GOP 2)                                             │
│   [ moof: mfhd / traf / tfhd / tfdt / trun ] [ mdat: Видео NALU ]      │
└────────────────────────────────────────────────────────────────────────┘
  1. ftyp + moov: Записываются в начале файла и содержат параметры кодека SPS/PPS (avcC для H.264, hvcC для H.265).
  2. moof + mdat: Записываются на каждой границе ключевого кадра (GOP). Бокс trun содержит длительности и размеры семплов, а mdat — сжатые видеоданные.

2. Вытеснение страниц из Page Cache ядра Linux (POSIX_FADV_DONTNEED) ​

Круглосуточная запись сотен камер генерирует постоянный поток десятков мегабайт в секунду. В стандартных Linux-серверах ядро кеширует все записанные данные в RAM, что приводит к Page Cache Thrashing и авариям OOM Killer.

RUSEON Core решает эту проблему через интерфейс CacheDropper:

go
// 1. Запись части fMP4 на диск
_ = part.Marshal(file)

// 2. Указание ядру Linux вытеснить записанные страницы из памяти
if dropper, ok := file.(registry.CacheDropper); ok {
    _ = dropper.DropCache()
}
  • Память фиксирована: Расход RSS остается плоским (~471 МБ при 600 камерах).
  • Отсутствие задержек I/O: Фоновый сброс предотвращает зависания дисковых контроллеров.

3. Структура каталогов и восстановление после сбоев ​

Файлы сохраняются в каталоге архива (по умолчанию recordings/):

  • Текущая запись: recordings/{camera_id}/2026-08-23_15-04-05_ongoing.mp4
  • Завершенная запись: recordings/{camera_id}/2026-08-23_15-04-05_to_16-04-05.mp4
  • Восстановление при старте: При запуске cmd/server/main.go автоматически восстанавливает незавершенные файлы .crashed и .ongoing.

Связанная документация ​

Released under the MIT License.