- Python 95.4%
- Shell 3%
- Makefile 0.8%
- Dockerfile 0.8%
| agents | ||
| common | ||
| config | ||
| deploy/ubuntu | ||
| secrets | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| docker-compose.gpu.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Makefile | ||
| MIGRATION_NOTES.md | ||
| README.md | ||
| requirements.txt | ||
| run.py | ||
| SHA256SUMS | ||
| summary.py | ||
Автоматическая обработка записей из Nextcloud — Linux/Docker
Комплект переносит конвейер с Windows на Linux, устраняет вызовы .bat и не требует локального зеркала больших каталогов Nextcloud.
Архитектура хранения
Данные разделены на две категории.
Большие каталоги записей
Аудио, видео, Zoom VTT, расшифровки и резюме встреч обрабатываются через WebDAV:
scheduler_agentрекурсивно выполняетPROPFINDтолько для каталогов изnextcloud.rootsи записывает в SQLite метаданные файлов.transcriber_agentскачивает поGETодну выбранную запись во временный каталогworkdir/whisperx/<meeting_id>.- WhisperX создаёт локальные временные артефакты.
- Готовые
*-parsed.txtи*-whisperx.srtзагружаются обратно в исходную папку черезPUT. SRT содержит временные интервалы и технические метки говорящих; он нужен, если Zoom VTT появится позднее. - Если рядом есть Zoom VTT,
enricher_agentскачивает*-parsed.txt, Zoom VTT и*-whisperx.srt, создаёт*-enriched.txtи загружает его черезPUT. analyzer_agentчитает parsed/enriched-текст через WebDAV, вызывает локальную LLM и загружает*-resume.txtв ту же удалённую папку.- Временные локальные копии медиа и промежуточных файлов удаляются после успешного шага; долговечное состояние обработки остаётся в Nextcloud.
На диске сервера постоянно не хранится архив записей. Требуемое место определяется размером одновременно обрабатываемой записи, кэшем моделей и техническими артефактами.
Небольшая папка Automation
nextcloudcmd используется только для папки, например /Automation:
Automation/
├── config.yaml
├── prompts/
│ ├── *.txt
│ └── clients/*.txt
└── summaries/
Она содержит общую конфигурацию, промпты, клиентские контексты и сводные отчёты. Код запрещает запуск nextcloudcmd без явного списка заданий и отказывается синхронизировать корень /.
Что заменено
| Windows-реализация | Linux-реализация |
|---|---|
run.bat |
run.py / agents.pipeline_agent |
summary.bat |
summary.py |
WhisperX.bat |
common/whisperx_runner.py |
summarize_transcript.bat и AskGPT.py |
common/llm.py, OpenAI-совместимый API llama.cpp |
| полный локальный доступ к каталогам записей | выборочные PROPFIND, GET и PUT через WebDAV |
| секреты в общем YAML | Docker secrets или root-owned файлы |
Состав конвейера
nextcloudcmd: синхронизация /Automation
↓
WebDAV scheduler: метаданные выбранных remote roots
↓
classifier_agent
↓
GET одной записи → WhisperX → PUT parsed + whisperx.srt
↓
GET parsed + VTT + whisperx.srt → обогащение → PUT enriched
↓
GET текста → llama.cpp → PUT resume
↓
повторный WebDAV scan
Правило определения состояния
SQLite является локальным индексом и журналом, но не источником истины. Каждый цикл начинается со сканирования Nextcloud, а стадии определяют работу по наличию удалённых артефактов:
| Стадия | Обязательные входы | Выход | Условие запуска |
|---|---|---|---|
| Транскрибация | медиа | *-parsed.txt, *-whisperx.srt |
parsed отсутствует; либо VTT появился позднее, enriched отсутствует и нет whisperx SRT |
| Обогащение | parsed, Zoom VTT, whisperx SRT | *-enriched.txt |
все входы есть, enriched отсутствует |
| Анализ встречи | enriched; либо parsed при отсутствии VTT | *-resume.txt/*.md |
вход готов, resume отсутствует |
| Сводный анализ | remote resume-файлы | файл в /Automation/summaries |
ожидаемый сводный файл отсутствует после синхронизации |
Если выходной файл удалён в Nextcloud, следующий полный scan очистит соответствующее поле SQLite и стадия создаст файл снова. Существующие выходы не перезаписываются: загрузка выполняется условным PUT с If-None-Match: *. Исключение — явно заданные параметры --force/--force-analysis.
classifier_agent не создаёт файл в Nextcloud: он детерминированно восстанавливает служебные атрибуты встречи из удалённого пути и общей конфигурации, поэтому его безопасно запускать при каждом цикле.
Конфигурация
Общая конфигурация команды
Шаблон: config/shared.example.yaml.
Общий файл находится в /Automation/config.yaml и содержит:
- удалённые корни записей
nextcloud.roots; - тип и клиента для каждого корня;
- правила классификации;
- порядок предпочтения форматов медиа;
- маршруты промптов;
- параметры сканирования, не содержащие секретов.
Пути к промптам разрешаются относительно каталога общего config.yaml.
Локальная конфигурация сервера
Создайте config/server.yaml из config/server.example.yaml. Файл не должен попадать в Git или общую папку Nextcloud.
Ключевые параметры:
shared_config_path: /data/automation/config.yaml
runtime:
nextcloud:
webdav_url: https://cloud.example.org/remote.php/dav/files/{username}
username_file: /run/secrets/nextcloud_username
password_file: /run/secrets/nextcloud_password
nextcloud_sync:
server_url: https://cloud.example.org
jobs:
- remote_path: /Automation
local_path: /data/automation
webdav_url — полный DAV-корень пользователя. {username} заменяется значением из защищённого secret-файла.
nextcloud_sync.server_url — обычный адрес сервера Nextcloud без /remote.php/dav/....
Секреты
Создайте файлы:
secrets/nextcloud_username
secrets/nextcloud_password
secrets/huggingface_token
secrets/llama_api_key
Пример:
mkdir -p secrets
printf '%s' 'nextcloud-user' > secrets/nextcloud_username
printf '%s' 'NEXTCLOUD-APP-PASSWORD' > secrets/nextcloud_password
printf '%s' 'hf_...' > secrets/huggingface_token
printf '%s' 'no-key' > secrets/llama_api_key
chmod 700 secrets
chmod 600 secrets/*
Для незащищённого llama-server можно использовать значение no-key.
Для диаризации токен Hugging Face должен иметь доступ к используемой модели pyannote; принятие условий модели выполняется в учётной записи Hugging Face заранее.
Требования к серверу
- Linux x86-64;
- Docker Engine и Docker Compose plugin;
- драйвер NVIDIA на Docker-хосте;
- NVIDIA Container Toolkit на Docker-хосте, если WhisperX использует локальный GPU;
- доступ из контейнера к Nextcloud и серверу llama.cpp;
- свободное место минимум для крупнейшей одновременно обрабатываемой записи, кэша моделей и временных артефактов.
Подготовка Docker-хоста для локального WhisperX на NVIDIA
CUDA-библиотеки внутри образа не устанавливают host-side NVIDIA Container Toolkit.
Команда nvidia-ctk и настройка Docker runtime должны находиться на самом Ubuntu-сервере.
После клонирования репозитория выполните один раз:
make bootstrap-gpu
Скрипт deploy/ubuntu/install-nvidia-container-toolkit.sh идемпотентен: он проверяет
работу драйвера через nvidia-smi, подключает официальный репозиторий NVIDIA,
устанавливает Toolkit, запускает nvidia-ctk runtime configure --runtime=docker,
перезапускает Docker и обновляет CDI-описания, если соответствующий systemd-сервис
доступен. Скрипт намеренно не устанавливает драйвер NVIDIA.
Базовый docker-compose.yml не требует GPU. Локальный GPU подключается только через
docker-compose.gpu.yml, поэтому синхронизация и административные команды работают
даже на CPU-only сервере.
Развёртывание
sudo mkdir -p /opt/nextcloud_processing
sudo chown "$USER":"$USER" /opt/nextcloud_processing
git clone https://git.greesha.ru/modeus_tools/nextcloud_processing \
/opt/nextcloud_processing
cd /opt/nextcloud_processing
cp config/server.example.yaml config/server.yaml
cp .env.example .env
mkdir -p data/{automation,work,database,models} secrets
Запишите UID/GID владельца файлов в .env:
id -u
id -g
До первого запуска создайте в Nextcloud /Automation и разместите там:
config/shared.example.yamlпод именемconfig.yaml;- файлы промптов в
prompts/; - клиентские контексты в
prompts/clients/.
Затем отредактируйте config/server.yaml и создайте secret-файлы.
Первичная проверка
Сначала проверьте только синхронизацию небольшой папки:
make build
make sync
В data/automation должен появиться config.yaml и папка prompts.
Проверьте WebDAV-сканирование без WhisperX:
make scan
Сканирование читает только метаданные и не скачивает содержимое медиа.
Запуск
Однократный полный проход:
make run-once-gpu
Фоновый режим:
make up-gpu
make logs
Фильтр по клиенту и дате:
docker compose -f docker-compose.yml -f docker-compose.gpu.yml \
run --rm processor --config /config/server.yaml --once \
--client 'УрФУ' --from_date 2026-07-01
Сводное резюме нескольких встреч:
docker compose run --rm --entrypoint python3 processor \
summary.py --config /config/server.yaml \
--client 'УрФУ' --from_date 2026-07-01
Сводный файл записывается в /data/automation/summaries, после чего summary.py синхронизирует /Automation.
Настройка llama.cpp
runtime:
llm:
base_url: http://llama-server.internal:8080/v1
model: local-model
api_key_file: /run/secrets/llama_api_key
timeout: 900
temperature: 0.1
max_tokens: 8192
Клиент вызывает POST /v1/chat/completions. localhost внутри контейнера означает сам контейнер, поэтому для отдельного сервера LLM укажите адрес, доступный из Docker-сети.
Диагностика
CUDA:
docker compose -f docker-compose.yml -f docker-compose.gpu.yml \
run --rm --entrypoint python3 processor -c \
"import torch; print(torch.cuda.is_available(), torch.version.cuda)"
WhisperX:
docker compose -f docker-compose.yml -f docker-compose.gpu.yml \
run --rm --entrypoint python3 processor -c \
"import whisperx; print('WhisperX imported')"
Тесты без GPU и реального Nextcloud:
python3 -m unittest discover -s tests -v
Журнал операций хранится в SQLite data/database/nextcloud_media.sqlite3, таблица operations.
Персистентные данные
data/automation— только небольшая синхронизируемая папка Automation;data/database— SQLite и история операций;data/work— временные загрузки, локальные копии артефактов, полные промпты и технические результаты;data/models— кэш Hugging Face и Torch.
Каталога с локальным зеркалом записей нет.
Очистка временных файлов
При успешной обработке:
- исходное медиа удаляется после загрузки недостающих remote-артефактов;
- локальные JSON, parsed и SRT WhisperX удаляются;
- долговечный
*-whisperx.srtостаётся рядом с записью в Nextcloud; - после обогащения локально скачанные VTT/parsed/SRT удаляются.
Для диагностики можно задать:
runtime:
transcribe:
keep_source_copy: true
keep_artifacts: true
enrich:
keep_artifacts: true
Эти параметры существенно увеличивают использование диска.
CPU-режим
Для диагностического запуска без NVIDIA не требуется редактировать Compose-файлы:
- запускайте команды через базовый
docker-compose.yml(make run-onceилиmake up); - задайте
device: cpuиcompute_type: int8; - уменьшите
batch_size.
Для локальной NVIDIA используйте make run-once-gpu или make up-gpu.
Для регулярной обработки длинных записей CPU-режим обычно непрактичен.