Files

285 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ImageFind
ImageFind 是面向 fnOS/NAS 的私有 AI 媒体库。它提供类似视频网站的浏览、在线播放、上传、
下载和资料管理体验,可索引本地目录、通用 WebDAV、AList 直连库与 AList 加密库,并通过
中英文关键词、番号/演员/标签、OCR/字幕/音频语音、查询图片和已命名人物定位到视频中的具体时间片段。
> 当前版本为可侧载验证的 `0.5.45`。应用声明 fnOS Python 3.12 和 PostgreSQL 依赖,核心运行环境离线安装,
> PyTorch、OpenVINO 和各类 AI 依赖在安装对应模型时按需下载;AI 模型权重可在“设置”中
> 按组件下载、通过离线脚本准备或上传完整模型包。
> 上传、移动和回收站操作只会对明确启用写入的资料库生效。
## 本地开发
要求 Python 3.113.13、Node.js 20+、FFmpeg/FFprobe,以及启用 `vector``pg_trgm` 扩展的
PostgreSQL 17。业务数据、全文索引和语义向量均由 PostgreSQL 保存,不再使用 SQLite 或 Qdrant
作为运行数据库。启动前通过 `IMAGEFIND_POSTGRES_CONF` 指向 PostgreSQL 客户端配置文件。
```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
npm install --prefix frontend
npm run build --prefix frontend
IMAGEFIND_DATA_DIR="$PWD/.data" imagefind
```
打开 `http://127.0.0.1:8765`。本地开发时首次访问需创建不少于 10 个字符的管理员密码;
fnOS 安装包会在安装向导中完成这一步。
UI 回归使用 Playwright。Linux 截图机必须安装 `fonts-noto-cjk`,缺少中文字体时测试会直接失败,
避免把方框字保存为视觉基线:
```bash
cd frontend
npm run test:ui
```
飞牛真机测试使用独立配置,不在仓库保存 NAS 密码或浏览器会话。先把已登录管理员浏览器的
Playwright `storageState` 保存到仓库外,并准备一个只放测试文件的可写资料库:
```bash
IMAGEFIND_FNOS_BASE_URL="https://NAS地址/app/imagefind/" \
IMAGEFIND_FNOS_STORAGE_STATE="/安全目录/fnos-storage-state.json" \
IMAGEFIND_E2E_SOURCE_NAME="ImageFind E2E" \
npm run test:ui:fnos
```
写入测试只清理本次创建且以 `E2E-` 开头的文件,不会操作其他媒体。
常用配置:
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `IMAGEFIND_DATA_DIR` | `./data` | 数据库、缩略图、模型和缓存目录 |
| `IMAGEFIND_HOST` / `IMAGEFIND_PORT` | `127.0.0.1` / `8765` | 监听地址与端口 |
| `IMAGEFIND_POSTGRES_CONF` | 数据目录上级的 `postgres-client.conf` | PostgreSQL 客户端配置文件 |
| `IMAGEFIND_DB_POOL_MIN` / `IMAGEFIND_DB_POOL_MAX` | `1` / `8` | PostgreSQL 进程内连接池上下限 |
| `IMAGEFIND_DB_POOL_TIMEOUT` | `5` | 等待可用数据库连接的最长秒数 |
| `IMAGEFIND_EMBEDDING_BACKEND` | `auto` | `auto``openvino``torch` 或测试用 `hash` |
| `IMAGEFIND_MODEL_BUNDLE_URL` | 空 | 可选:用自建模型包代替默认官方仓库 |
| `IMAGEFIND_MODEL_BUNDLE_SHA256` | 空 | 自建模型包的 SHA-256 |
| `IMAGEFIND_MODEL_HF_ENDPOINT` | `https://huggingface.co` | Hugging Face 地址,可改为可信镜像 |
| `IMAGEFIND_PIP_INDEX_URL` | `https://pypi.tuna.tsinghua.edu.cn/simple` | AI 运行依赖使用的 PyPI 主镜像 |
| `IMAGEFIND_PYTORCH_INDEX_URL` | `https://download.pytorch.org/whl/cpu` | PyTorch CPU 专用轮子源,可在设置页留空或修改 |
| `IMAGEFIND_MODEL_UPLOAD_GB` | `10` | 手动上传模型包上限(GiB) |
| `IMAGEFIND_FFMPEG_PATH` | `ffmpeg` | FFmpeg 可执行文件 |
| `IMAGEFIND_REMOTE_MAX_CONNECTIONS` | `3` | WebDAV 扫描、索引和播放的全局并发上限 |
| `IMAGEFIND_PREVIEW_CACHE_GB` | `5` | HLS 兼容预览缓存上限(GiB) |
| `IMAGEFIND_UPLOAD_CHUNK_MB` | `16` | 浏览器上传分块大小(MiB) |
| `IMAGEFIND_UPLOAD_STAGING_GB` | `100` | 未完成上传的暂存配额(GiB) |
| `IMAGEFIND_UPLOAD_RESERVE_GB` | `5` | 创建上传任务后仍需保留的磁盘空间(GiB) |
| `IMAGEFIND_TRASH_RETENTION_DAYS` | `30` | 回收站记录的默认保留天数 |
## 远程媒体库与加密
通用 WebDAV 和 AList 均在“资料库 → 添加资料库”中配置。扫描器使用递归 `Depth: 1
PROPFIND`,以 ETag、大小和修改时间识别变更。服务端不支持 Range 时,索引或播放可能退化为
完整文件传输,建议先在小目录验证带宽占用。
AList 有两种互斥模式:
- **AList 直连**:文件和文件名以明文保存在远端。播放接口向浏览器返回 AList 提供的 302
临时直链,视频流量通常不经过 NAS;直链解析失败时自动回退到认证代理。
- **AList 加密**:使用 `rclone crypt` 加密文件内容、文件名和目录名。应用优先使用 fnOS/系统
已安装的兼容 rclone,缺失时再下载经过版本与 SHA-256 固定的私有副本。上传、
播放、下载、抽帧和 AI 索引均由 NAS 即时解密,因此不能再使用 302 直链,带宽会经过 NAS。
ImageFind 每 60 秒安全核验上次异常退出遗留的 rclone 实例。只有进程身份和应用目录匹配、连续
3 次没有活动连接或 I/O 且观察满 2 分钟时才会自动回收;身份不一致的进程只标记为“待处理”,
不会强制终止。也可以在“设置 → 任务与偏好 → 资源保护”中执行一次立即安全核验。
创建加密库时浏览器会自动下载一次 `imagefind-vault-recovery-*.json`。必须把它存放在密码管理器
或离线介质中;它含有解密所需密钥,但不包含 AList 登录密码。重装后选择“AList 加密 → 从恢复
文件导入”,再输入当前 AList 密码,即可重新挂载原有密文。丢失恢复文件和应用内部数据后,
远端密文无法恢复。
AI 对加密库仍完整可用:NAS 读取并解密所需片段后执行抽帧、OCR、人物与向量分析,远端不会
得到明文索引。代价是首次扫描和播放都需要 NAS 与网盘之间的传输。
也可以先在 fnOS 中挂载 WebDAV,再作为本地目录添加。这种模式通常拥有更好的断线重连和
系统级缓存能力。
## 上传、下载与文件管理
浏览器上传采用 16 MiB 分块,每块带 SHA-256 校验,单文件 API 上限为 200 GiB,前端按当前
产品约束提示 100 GiB。文件会先完整暂存在应用私有数据目录,再由独立后台通道传输到目标库;
上传过程中断后,服务端会保留已接收分块用于续传;上传中心分别显示“上传至 ImageFind”、
“转存 WebDAV/AList”和“校验加入媒体库”三个阶段,失败的目标传输可直接重试。创建任务
时若无法满足暂存配额或 5 GiB 安全余量,接口会拒绝任务而不是写满系统盘。
开启飞牛“直接 Web/API 访问”后,可在“设置 → 账户与 API”启用 WebDAV 后台上传。标准
WebDAV 客户端必须连接 `http://NAS_IP:8765/webdav/`(端口以应用配置为准),用户名固定为
`imagefind`,密码使用页面创建且只显示一次的专用 REST API Token。飞牛 5666 统一网页网关
不转发标准 DAV 认证和方法,不能作为 WebDAV 服务器地址。上传路径的第一层目录会自动映射为
同名合集,后续目录映射为可任意嵌套的章节或小节;已入库视频可浏览和读取。服务端兼容普通
`PUT`、临时文件加 `MOVE``Content-Range``Upload-Offset` 续传。完整上传会在接收时增量
校验且不再二次扫描暂存文件;客户端因响应丢失重传相同路径和内容时会幂等返回,不会再生成
`(2)``(3)` 副本。文件接收完成到媒体入库之间,`HEAD`/`PROPFIND` 仍会返回已接收状态,
避免客户端因短暂 404 重新上传。
本地目录默认只读,必须在资料库卡片上主动启用写入;AList 资料库默认可写。文件面板支持浏览、
新建目录、移动/重命名和移入回收站。回收站内可恢复或永久删除;卸载应用不会删除共享目录、
已授权目录或远端库中的源视频。播放接口支持 HTTP Range;AList 直连下载/播放可使用 302,
其余来源经 ImageFind 认证代理读取,下载会保留原文件名。
后台任务按 AI 识别、上传转存、后台下载和来源扫描分为四条独立通道,各自保持单并发。这样
大文件上云不会阻塞索引,同时避免低功耗 NAS 因多个 AI 或磁盘任务并发而耗尽内存。
## 自定义分类与 AI 标签
“分类与标签”支持创建任意分类组,例如类型、场景、服装、片商或自定义收藏维度。每个组可设置为
单选或多选;影片资料编辑和批量赋值都会遵守该约束。标签可以移动、合并和删除,旧版字符串标签
在升级时会自动迁移到“未分组”。
每个标签都可以独立启用一种 AI 建议方式:
- **画面语义**:使用已生成的 CLIP 画面向量与自定义描述做零样本匹配,适合能从画面判断的场景、
服装和视觉类型。
- **文本规则**:匹配文件名、路径、影片资料、OCR 和文本字幕,适合番号、片商、系列或明确关键词。
AI 结果只会进入“待确认建议”,不会直接覆盖人工标签。索引新视频完成后会自动排队分析已启用
AI 的标签,也可从影片资料或分类页手动重跑。服务启动、状态检查和仅浏览页面都不会加载模型;
模型仍然只在实际索引、图片/语义检索或手动分析需要时延迟初始化。自定义标签的准确度取决于描述、
阈值和素材,不能可靠由画面判断的抽象标签应使用文本规则或保持手动。
## 系统备份与恢复
“设置 → 系统备份与恢复”可下载单一 `.ifbackup` 加密文件。每个备份都包含本地、WebDAV 与
AList 来源配置、登录凭据和 rclone crypt 密钥;完整范围还包含影片身份、手工资料、分类与标签、
演员、收藏、喜欢、播放进度、偏好和模型/运行依赖镜像配置。备份密码独立于管理员密码,长度为 10–256 个
字符,不会持久化;忘记密码后无法解密。
恢复前需在新系统创建管理员并登录。只有没有来源、影片、AI 人物、演员或用户标签的空系统可以
恢复。当前管理员、会话和 API Token 不会被导入或覆盖;媒体文件、模型、缩略图、OCR、人物聚类、
向量与其他可重建索引也不进入备份。恢复后影片先处于不可播放的待扫描状态,启用的来源会自动排队
扫描,并按来源 ID 与源文件键重新关联原影片 ID。
## fnOS 视频目录
安装或升级后,fnOS 会创建共享目录 `imagefind/videos`,应用运行用户会自动获得访问权限。
可以把待索引视频放入该目录,再在 ImageFind 中将它添加为本地资料库。
如果视频已经位于其他 NAS 目录,无需搬动文件:在 fnOS 的 ImageFind 应用设置中授权这些
目录,再在 ImageFind 中添加对应路径。`imagefind/videos` 是便于直接导入文件的应用共享目录,
授权目录可用于只读索引已有媒体库;只有在 ImageFind 内明确启用写入后,文件管理和上传操作
才允许修改该目录。AI 索引过程本身不会修改源视频。
fnOS 全新安装时必须输入两次 ImageFind 管理员密码。升级向导中的密码可以留空以保留
现有密码,也可以填写两次来初始化或重置密码。卸载向导默认保留应用数据;勾选清除后会
删除数据库、索引、缓存、模型、凭据和日志,但不会删除 `imagefind/videos`、用户授权目录
或 WebDAV 上的任何源视频。
## 播放与 HLS 兼容预览
搜索结果优先通过认证后的 Range 接口直接播放,并跳转到命中时间。浏览器不支持源视频的
封装格式或编码时,前端会自动请求命中点附近的 HLS 兼容预览。预览默认最长 180 秒,优先
使用 Intel VAAPI,随后尝试 OpenH264 或 libx264;缓存达到上限后按最久未使用顺序清理。
生成兼容预览会消耗额外 CPU/GPU 和临时空间。远程源还会读取对应时间段;WebDAV 服务端若
忽略 Range,可能退化为完整文件传输。
## 模型包约定
fnOS 安装包包含 Web 服务与 PostgreSQL 客户端运行依赖,数据库和 pgvector 由声明的
`nxsir.postgresql` fnOS 依赖应用提供;OpenVINO、PyTorch 等**推理运行时**
与体积更大的**模型权重**不随包发布,而是在首次安装对应 AI 组件时按需下载。设置页的在线安装
会从 Hugging Face 下载画面/多语言模型及 Whisper small,从 Open Model Zoo 下载人物模型。Whisper
会导出为 OpenVINO FP16;安装后以单任务串行方式自动补齐旧影片的带时间轴语音索引。应用启动
和状态检查都不会加载模型到内存,只有搜索或索引实际需要时才延迟初始化。
语音识别默认采用“中文优先 + 准确率优先”:先读取音轨语言,再从最多 3 个高语音占比片段检测,
无法判断时使用中文,并以 5-beam 解码。每个时间片段会经过字符损坏、异常文字脚本、重复输出、
无语音幻觉和文本密度校验,低质量片段不会进入搜索。设置页可切换智能检测、固定中文和三档质量,
也可扫描存量旧转写;明显低质量的视频会自动排队重新识别。
“设置 → AI 与网络”可分别配置 Hugging Face、PyPI 和 PyTorch CPU 下载源。PyPI 默认使用已直连
验证的清华镜像;HTTP/HTTPS 代理有独立开关,关闭后保留加密凭据但所有 AI 下载直接连接,启用后
才用于模型与运行依赖下载。pip 安装期间每隔约 5 秒更新阶段和等待时间,任务重启排队时会重置为
0%,避免把等待中的组件误显示为卡住。
无法直接访问官方仓库时,可以在其他电脑准备下述 ImageFind 模型包,再通过设置页“上传模型包”
手动安装。服务端以流式方式写入应用数据目录,不会先占用 fnOS 的 `/tmp`;安装前会检查压缩包
路径、解压体积和必需目录,并以原子方式替换现有模型。
模型包是 `.tar.gz`,根目录必须包含 `manifest.json` 以及:
```text
visual/image/ # clip-ViT-B-32 SentenceTransformer 模型
visual/text/ # clip-ViT-B-32-multilingual-v1 文本模型
ocr/ # 可选:det.onnx、rec.onnx、cls.onnx
faces/ # 可选:detector.xml/.bin、reidentification.xml/.bin
audio/ # 可选:Whisper small OpenVINO FP16 模型和处理器配置
```
视觉模型变化后需要重建画面向量;应用不会静默切换向量空间。
生成模型包不会修改源模型目录:
```bash
python3 scripts/build-model-bundle.py /path/to/models dist/imagefind-models.tar.gz --version 1
```
## 构建 fnOS 安装包
发布构建只面向 x86_64 fnOS,需要官方 `fnpack`、Node.js、带 Hatchling/Pillow 的构建环境,
以及 `.fnos-wheel-cache/python312` 中完整的 Python 3.12 核心 wheelhouse。fnOS 端声明依赖
`python312`;AI 推理依赖不会进入 FPK,而是在安装对应模型时按锁文件下载。发布包只内置:
```text
vendor/libOpenCL.so.1
```
安装依赖并构建:
```bash
python3 -m venv .release-venv
.release-venv/bin/pip install -e '.[dev]'
./scripts/build-fnos.sh
```
默认输出为 `dist/imagefind-0.5.45-x86_64.fpk`。FFmpeg/FFprobe 与 rclone 在运行时优先使用
兼容的系统版本,缺失时按固定版本和 SHA-256 动态下载。0.5.45 不读取或迁移旧 SQLite 数据库;
安装时直接初始化 PostgreSQL schema,升级脚本不会擅自删除用户数据或旧 runtime 目录。
当前仓库中的 manifest、权限和资源声明是
侧载模板;正式发布前必须用目标 fnOS 版本配套的官方 `fnpack` 校验,并在真实 N100 设备上
验证安装/升级向导、启停、GPU 权限、端口跳转和两种卸载数据行为。
解出安装包内的 `app.tgz` 后,可以在 x86_64 Linux 构建机上运行制品级冒烟:
```bash
./scripts/smoke-fnos-package.sh /path/to/extracted/app /tmp/imagefind-smoke 18765
```
## API
登录后在“设置”创建独立 API Token。请求使用 `Authorization: Bearer <token>`
OpenAPI 文档位于 `/api/docs`,主要入口是:
- `POST /api/v1/query-images`
- `POST /api/v1/search`
- `POST /api/v1/uploads``/api/v1/uploads/{id}/chunks/{index}`
- `POST /api/v1/models/install``POST /api/v1/models/upload`
- `PATCH /api/v1/models/config``POST /api/v1/models/proxy/test``DELETE /api/v1/models/{component}`
- `/api/v1/sources``/api/v1/files``/api/v1/trash`
- `POST /api/v1/sources/alist/restore`
- `GET/POST /api/v1/backups``GET /api/v1/backups/{id}/download``POST /api/v1/backups/restore`
- `/api/v1/tag-groups``/api/v1/tags``POST /api/v1/videos/tags/bulk`
- `/api/v1/tag-suggestions``POST /api/v1/tag-suggestions/analyze``POST /api/v1/tag-suggestions/decide`
- `PATCH /api/v1/videos/{video_id}/state`
- `GET/PATCH /api/v1/speech/config``POST /api/v1/speech/reconcile`
- `GET /api/v1/videos/{video_id}/transcript``POST /api/v1/videos/{video_id}/transcript/reindex`
- `/api/v1/profile``/api/v1/series``POST /api/v1/videos/series/bulk`
- `GET /api/v1/storage/usage`
- `/api/v1/preferences``/api/v1/activity``GET /api/v1/events`
- `/api/v1/jobs``/api/v1/people``/api/v1/actors`
- `GET /api/v1/system/diagnostics`
- `POST /api/v1/system/resources/rclone/reconcile`
## 隐私与范围
- 视频可位于本机或用户配置的远端;关键帧、人脸特征、文字、向量和密钥只保存在本机。
- WebDAV 凭据通过应用主密钥加密;主密钥文件权限为 `0600`
- 首版只支持管理员;fnOS 提供稳定的用户身份 API 后再接入系统多用户 ACL。
- 支持文本字幕、烧录在画面内的文字和带时间轴的 Whisper 语音转写;不包含 PGS/VobSub 图片字幕。