Разбираю, как устроен рынок корпоративного мониторинга, что уже умеют большие системы, и где в этой картине живёт простая идея «скриншот каждые 5 минут + анализ активности». Материал — черновик, потом можно доработать.
Идея «следить за сотрудниками через скриншоты» кажется новой только на первый взгляд. На самом деле это огромный рынок, который последние 5 лет переживает бум из-за удалёнки и генеративного ИИ.
Ключевой сдвиг: раньше мониторинг = «поймать вора». Сейчас мониторинг = «понять поведение, оптимизировать процессы и защититься от утечек через ИИ-инструменты».
Условно всё делится на три этажа. Чем выше — тем больше денег, сложнее архитектура и серьёзнее юридические риски.
Один скрипт на Python. Скриншоты, активное окно, отправка на сервер. Без ML, без OCR. Анализ — глазами или простыми эвристиками.
Локальная нейросеть (Ollama + vision-модель), SQLite, дашборд. Анализ активности: «работает / ютуб / переписка». Всё локально.
Агенты, DLP, OCR, поведенческая аналитика, графы коммуникаций, детект аномалий, интеграция с SIEM. Сертификации, юристы, отдел внедрения.
Это не «скриншот каждые 5 минут». Это полноценные платформы, где картинка с экрана — лишь один из сотни сигналов.
Общий паттерн: большие системы не полагаются на один сигнал. Они комбинируют активное окно, OCR, сетевые события, DLP-правила и ML-модели аномалий.
Если не хочешь корпоративную махину, но и «скрипт на коленке» уже мало — вот сюда стоит смотреть.
qwen2.5vl, llava, moondream — все умеют «опиши, что на экране».Скрипт под именем host.exe, скриншот каждые 5 минут, отправка на внутренний сервер, потом анализ нейросетью. Давай разложим честно.
host.exe — красная тряпка. Любой антивирус и любой админ насторожатся. Это маскировка под системный процесс, а не «нейтральное имя».activity-logger, chrono.Минимальный, но осмысленный прототип. Делает скриншот, определяет активное окно, спрашивает локальную модель «чем занят пользователь», пишет в SQLite. Всё локально.
pip install mss pywin32 pillow requests
import time
import json
import base64
import sqlite3
import io
from datetime import datetime
import mss
import requests
from PIL import Image
import win32gui
import win32process
# --- Настройки ---
INTERVAL_SEC = 300 # раз в 5 минут
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL = "qwen2.5vl:3b" # лёгкая vision-модель
DB_PATH = "activity.db"
def get_active_window_title():
"""Возвращает заголовок активного окна и имя процесса."""
try:
hwnd = win32gui.GetForegroundWindow()
title = win32gui.GetWindowText(hwnd)
_, pid = win32process.GetWindowThreadProcessId(hwnd)
# имя процесса без psutil — через tasklist было бы медленно,
# поэтому просто оставим pid, а имя добавим опционально
return title, pid
except Exception:
return "", 0
def take_screenshot_base64():
"""Скриншот всего экрана → base64 PNG (сжатый)."""
with mss.mss() as sct:
monitor = sct.monitors[1]
shot = sct.grab(monitor)
img = Image.frombytes("RGB", shot.size, shot.rgb)
# уменьшаем, чтобы модель работала быстрее
img.thumbnail((1280, 720))
buf = io.BytesIO()
img.save(buf, format="PNG", optimize=True)
return base64.b64encode(buf.getvalue()).decode("utf-8")
def ask_model(image_b64, window_title):
"""Спрашиваем локальную модель: чем занят пользователь."""
prompt = (
"Ты анализируешь скриншот рабочего стола сотрудника. "
"Ответь строго в JSON без пояснений:\n"
"{\n"
' "category": "work|social|video|messaging|games|other",\n'
' "app": "название приложения или сайта",\n'
' "activity": "краткое описание, чем занят (до 15 слов)",\n'
' "is_work_related": true/false\n'
"}\n"
f"Заголовок активного окна: {window_title}"
)
payload = {
"model": MODEL,
"prompt": prompt,
"images": [image_b64],
"stream": False,
"options": {"temperature": 0.1}
}
try:
r = requests.post(OLLAMA_URL, json=payload, timeout=120)
r.raise_for_status()
raw = r.json().get("response", "").strip()
# вытаскиваем JSON из ответа
start = raw.find("{")
end = raw.rfind("}") + 1
return json.loads(raw[start:end])
except Exception as e:
return {"category": "error", "app": "", "activity": str(e), "is_work_related": False}
def init_db():
con = sqlite3.connect(DB_PATH)
con.execute("""
CREATE TABLE IF NOT EXISTS activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts TEXT,
window_title TEXT,
pid INTEGER,
category TEXT,
app TEXT,
activity TEXT,
is_work_related INTEGER
)
""")
con.commit()
return con
def save(con, window_title, pid, result):
con.execute(
"INSERT INTO activity (ts, window_title, pid, category, app, activity, is_work_related) "
"VALUES (?, ?, ?, ?, ?, ?, ?)",
(
datetime.now().isoformat(timespec="seconds"),
window_title,
pid,
result.get("category", ""),
result.get("app", ""),
result.get("activity", ""),
1 if result.get("is_work_related") else 0,
),
)
con.commit()
def main():
con = init_db()
print(f"[activity-logger] старт, интервал {INTERVAL_SEC} сек, модель {MODEL}")
while True:
try:
title, pid = get_active_window_title()
img_b64 = take_screenshot_base64()
result = ask_model(img_b64, title)
save(con, title, pid, result)
print(f"[{datetime.now():%H:%M:%S}] {result.get('category')} | "
f"{result.get('app')} | {result.get('activity')}")
except Exception as e:
print(f"[!] ошибка: {e}")
time.sleep(INTERVAL_SEC)
if __name__ == "__main__":
main()
SELECT ts, category, app, activity FROM activity ORDER BY ts DESC LIMIT 10;
games или video в рабочее время.Ты придумал скриншот каждые 5 минут и локальную нейронку для анализа. Microsoft сделала то же самое, но назвала это Recall, встроила в Windows и добавила кучу железа. Разбираем архитектуру.
Recall — это фича Windows 11 для Copilot+ PC, анонсированная в мае 2024 года. Она каждые несколько секунд делает скриншот экрана (или когда содержимое активного окна меняется), прогоняет его через OCR и строит семантический индекс — локальную векторную базу, по которой можно искать всё, что ты когда-либо видел на экране[citation:1][citation:8].
Идея ровно твоя: «запомнить всё, что делает пользователь, и потом анализировать». Только вместо отправки на сервер — всё локально, и вместо «ваньку валяет или работает» — «найди мне ту таблицу с синим графиком, которую я видел на прошлой неделе».
Phi Silica — это маленькая языковая модель (SLM) от Microsoft, оптимизированная для запуска прямо на NPU (нейропроцессоре) Copilot+ PC[citation:3][citation:9]. Это не Llama на 8B, а компактная модель, которая:
Изначальный релиз Recall был катастрофой. Скриншоты хранились в открытом виде в обычной папке. Исследователи показали, что любой малварный процесс или другой пользователь на той же машине может вытащить всё, что ты когда-либо видел[citation:18].
После волны критики Microsoft полностью переделала архитектуру:
Твоя идея — это Recall без бюджета Microsoft. Ты хочешь:
host.exe → Microsoft: явный opt-in с иконкой в трее.Разница в том, что у Microsoft есть юристы, инженеры и репутация, которую они чуть не потеряли на первом релизе. У тебя есть Python-скрипт и блог. Это не значит, что идея плохая — это значит, что ты нащупал реальный тренд, который корпорация пытается монетизировать.
«Recall — это не фича. Это ответ Microsoft на вопрос: что если бы у компьютера была фотографическая память? И да, они сделали это ровно так, как ты придумал. Просто у них NPU на 45 TOPS, а у тебя — mss и Ollama».
Если система нужна для безопасности — она должна быть прозрачной и согласованной. Если для «поймать» — она будет врать и вредить.