Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "vidxp",
"interface": {
"displayName": "VidXP"
},
"plugins": [
{
"name": "vidxp",
"source": {
"source": "local",
"path": "./plugins/vidxp"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,11 @@ jobs:
if: >-
needs.scope.outputs.run_suite == 'true' &&
matrix.python-version == '3.14' &&
inputs.package_artifact_name != ''
(needs.scope.outputs.run_desktop == 'true' ||
inputs.package_artifact_name != '')
uses: actions/upload-artifact@v7
with:
name: ${{ inputs.package_artifact_name }}
name: ${{ inputs.package_artifact_name || 'vidxp-python-dist' }}
path: dist/
if-no-files-found: error
retention-days: 30
Expand Down Expand Up @@ -268,10 +269,13 @@ jobs:
if: >-
github.event_name == 'pull_request' &&
needs.scope.outputs.run_desktop == 'true'
needs: scope
needs:
- scope
- validate
uses: ./.github/workflows/desktop.yml
with:
checkout_ref: ${{ github.sha }}
package_artifact_name: ${{ inputs.package_artifact_name || 'vidxp-python-dist' }}

required:
if: always() && github.event_name == 'pull_request'
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ on:
required: false
default: false
type: boolean
package_artifact_name:
description: Validated Python distribution to embed in every installer.
required: false
default: ""
type: string
plugin_marketplace_ref:
description: Git ref for release builds; empty keeps a local marketplace.
required: false
default: ""
type: string
workflow_dispatch:
inputs:
checkout_ref:
Expand All @@ -34,6 +44,16 @@ on:
required: false
default: false
type: boolean
package_artifact_name:
description: Existing Python distribution artifact; otherwise build from checkout.
required: false
default: ""
type: string
plugin_marketplace_ref:
description: Git ref for release builds; empty keeps a local marketplace.
required: false
default: ""
type: string
permissions:
contents: read

Expand All @@ -55,6 +75,30 @@ jobs:
with:
ref: ${{ inputs.checkout_ref || github.event.inputs.checkout_ref || github.sha }}

- uses: actions/download-artifact@v8
if: inputs.package_artifact_name != ''
with:
name: ${{ inputs.package_artifact_name }}
path: dist/

- uses: actions/setup-python@v7
if: inputs.package_artifact_name == ''
with:
python-version: "3.14"

- name: Build the Python distribution for a standalone Desktop build
if: inputs.package_artifact_name == ''
shell: bash
run: |
python -m pip install -r utils/build-requirements.txt
bash utils/build_package.sh

- name: Verify the embedded Python package input
shell: bash
run: |
[[ "$(find dist -maxdepth 1 -name '*.whl' | wc -l | tr -d ' ')" == "1" ]]
[[ "$(find dist -maxdepth 1 -name '*.tar.gz' | wc -l | tr -d ' ')" == "1" ]]

- name: Install Linux desktop build dependencies
if: runner.os == 'Linux'
run: |
Expand Down Expand Up @@ -145,6 +189,7 @@ jobs:
working-directory: desktop
env:
VIDXP_DESKTOP_SIGN: ${{ (runner.os == 'macOS' && inputs.sign) && '1' || '' }}
VIDXP_PLUGIN_MARKETPLACE_REF: ${{ inputs.plugin_marketplace_ref }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/release-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,15 @@ jobs:
run_containers: false

desktop:
needs: contract
needs:
- contract
- core
uses: ./.github/workflows/desktop.yml
with:
artifact_retention_days: 30
checkout_ref: ${{ inputs.head_sha }}
package_artifact_name: vidxp-python-dist
plugin_marketplace_ref: ${{ inputs.target_branch }}
sign: true
secrets: inherit

Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FROM python:3.14-slim-trixie AS runtime-base
LABEL org.opencontainers.image.title="VidXP" \
org.opencontainers.image.description="Video indexing and search" \
org.opencontainers.image.source="https://github.com/grayhatdevelopers/vidxp" \
org.opencontainers.image.vendor="Grayhat Developers PVT Ltd" \
org.opencontainers.image.licenses="MIT"

RUN apt-get update && apt-get install -y --no-install-recommends \
Expand Down
5 changes: 3 additions & 2 deletions INSTALLATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ shape needs.
| Desktop app | Install the native package | Adopt a compatible local installation or create a private Desktop-managed runtime |
| Browser UI in Docker | Published `vidxp` image | One CPU worker/UI container |
| Public/self-hosted service | `compose.coolify.yaml` | API/MCP control plane, CPU worker, PostgreSQL, Chroma, tusd |
| Embed one capability | `dialogue`, `scene`, or `actor` extra | Python indexing/retrieval code |
| Embed one capability | `dialogue`, `scene`, `actor`, or `videoprism` extra | Python indexing/retrieval code |

Do not install the bare package and expect it to index video. Base `vidxp`
provides the lightweight command shell, configuration, and typed contracts.
Expand Down Expand Up @@ -227,7 +227,8 @@ Extras are composable:
| `dialogue` | Storage, transcription, dialogue embeddings | Scene/actor providers |
| `scene` | Storage, PyTorch, Transformers, OpenCV, Pillow | Dialogue/actor providers |
| `actor` | Storage, OpenCV, YuNet/SFace support | Dialogue/scene providers |
| `all` | Dialogue, scene, and actor | Grounded-query model client and UI |
| `videoprism` | Storage, VideoPrism, PyTorch, Transformers, Torchvision | Other model providers |
| `all` | Every built-in search capability | Grounded-query model client and UI |
| `local-worker` | `all` plus grounded-query client | Browser UI, MCP SDK, HTTP server |
| `frontend` | Streamlit | Worker providers |
| `mcp` | MCP SDK | Worker providers |
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 Grayhat Developers
Copyright (c) 2026 Grayhat Developers PVT Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ include LICENSE
include docs/images/logo.png
recursive-include src/vidxp/assets/upload_page *
recursive-include src/vidxp/assets/artifact_download *
recursive-include src/vidxp/assets/mcp_app *
recursive-include plugins/vidxp *
include web/upload-page/package.json
include web/upload-page/package-lock.json
include web/upload-page/scripts/build.mjs
Expand Down
47 changes: 35 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</p>

<p align="center">
<strong>Dialogue search · Scene search · Actor grouping</strong>
<strong>Dialogue search · Scene search · Temporal video search · Actor grouping</strong>
</p>

<p align="center">
Expand Down Expand Up @@ -43,9 +43,13 @@ VidXP makes one video—or an entire collection—searchable by meaning:
matching moments.
- **Scene search:** describe what appeared on screen and find the closest
visual matches.
- **VideoPrism search:** describe an action or event spanning a short clip.
- **Actor matching:** find recurring faces within a video and export a
highlighted video for a selected group.

Existing indexes remain compatible. Index media with the `videoprism`
capability selected before using temporal video search.

Use it to search years of family videos, add video search to an editing
workflow, or let an AI agent answer questions using evidence from your own
video library. Your videos can stay on your machine.
Expand Down Expand Up @@ -138,6 +142,9 @@ vidxp index create <media-id>
# Find a visual moment
vidxp search scene "a yellow taxi on a city street"

# Find an action spanning several frames
vidxp search videoprism "a person opens a door and walks outside"

# Find something that was said
vidxp search dialogue "the bread just came out of the oven"
```
Expand All @@ -159,18 +166,29 @@ questions about a library, and return inspectable evidence such as boards,
frames, and clips. Clients can connect locally over stdio or to a self-hosted
VidXP server.

### ChatGPT and Codex skills
### Codex plugin and skills

VidXP includes reusable skill source folders for the two common agent workflows:
VidXP is distributed as a Codex plugin through a Git marketplace hosted in
this GitHub repository. It includes three reusable agent workflows:

- [Ingest and index videos](skills/vidxp-ingest-video/SKILL.md)
- [Find moments and return inspectable evidence](skills/vidxp-find-video-evidence/SKILL.md)
- [Install Desktop or CLI and connect Codex](plugins/vidxp/skills/vidxp-install/SKILL.md)
- [Ingest and index videos](plugins/vidxp/skills/vidxp-ingest-video/SKILL.md)
- [Find moments and return inspectable evidence](plugins/vidxp/skills/vidxp-find-video-evidence/SKILL.md)

Download a skill folder and add it through a supported ChatGPT desktop or Codex
Skills surface. The skills require a connected VidXP MCP server; installable
plugin packaging for additional ChatGPT surfaces will follow separately.
Paste this into Codex:

```text
Add https://github.com/grayhatdevelopers/vidxp as a Git plugin marketplace, install the VidXP plugin, then use its $vidxp-install skill to set up VidXP on this computer.
```

VidXP Desktop can perform the same setup from its **Set up in Codex** button.

The MCP App resource gives compatible hosts an interactive upload and
evidence-review view; every workflow continues to work through ordinary MCP
tool results when a host has no UI.

- [Python, HTTP, and MCP installation](INSTALLATION_GUIDE.md)
- [ChatGPT and Codex plugin integration](docs/integrations/openai-plugin.md)
- [Optional capability packages](INSTALLATION_GUIDE.md#optional-dependency-extras)
- [Coolify server setup](docs/deployment/coolify.md)

Expand All @@ -179,14 +197,19 @@ plugin packaging for additional ChatGPT surfaces will follow separately.
First setup downloads only the models needed for the capabilities you select.
VidXP shows the download size and destination before it starts.

The Desktop-managed Python runtime and its selected dependencies can use
approximately 3 GiB.

| Capability | Approximate model download |
|---|---:|
| Dialogue search | 2.64 GiB |
| Scene search | 1.43 GiB |
| VideoPrism temporal search | 0.93 GiB |
| Actor matching | 37 MiB |

Leave additional space for the VidXP runtime, indexes, source videos, and
exported results.
A full local Desktop setup with every search capability uses approximately
8.1 GiB. Leave additional temporary space during installation and for indexes,
source videos, and exported results.

By default, the CLI and desktop app share the same VidXP data directory:

Expand Down Expand Up @@ -231,14 +254,14 @@ Contributions are welcome. Read the

## Credits

Built by Grayhat Developers PVT Ltd. and maintained by the community.
Built by [Grayhat](https://grayhat.studio/) and maintained by the community.
Originally researched by students:
- [Abdullah Mansoor](https://github.com/abdullahmansoor321)
- [Muhammad Haroon](https://github.com/haroon10725)
- [Sarah Jawaid](https://github.com/sarr266)
- [Talha Ahmed](https://github.com/talhaahmed1234)

Working with [Dr Shahab Tahzeeb](https://scholar.google.com/citations?user=cryeRB0AAAAJ&hl=en) ([NED University of Engineering and Technology](https://www.neduet.edu.pk/)) and [Saad Bazaz](https://scholar.google.com/citations?user=mrJo09oAAAAJ&hl=en) ([Grayhat](https://grayhat.studio)).
Working with [Dr Shahab Tahzeeb](https://scholar.google.com/citations?user=cryeRB0AAAAJ&hl=en) ([NED University of Engineering and Technology](https://www.neduet.edu.pk/)) and [Saad Bazaz](https://scholar.google.com/citations?user=mrJo09oAAAAJ&hl=en) ([Grayhat](https://grayhat.studio/)).

Email: info@grayhat.studio

Expand Down
2 changes: 1 addition & 1 deletion desktop/THIRD_PARTY_NOTICES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ VidXP Desktop and VidXP | MIT | https://github.com/grayhatdevelopers/vidxp

MIT License

Copyright (c) 2026 Grayhat Developers
Copyright (c) 2026 Grayhat Developers PVT Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 5 additions & 0 deletions desktop/model-cache-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"label": "google/siglip2-base-patch16-224",
"relative_artifact": "models--google--siglip2-base-patch16-224/snapshots/75de2d55ec2d0b4efc50b3e9ad70dba96a7b2fa2/model.safetensors"
},
{
"id": "google/videoprism-lvt-base-f16r288",
"label": "google/videoprism-lvt-base-f16r288",
"relative_artifact": "models--google--videoprism-lvt-base-f16r288/snapshots/fb6de9f0eb7bc285be86bdca1cf7daa3e3ef51ff/model.safetensors"
},
{
"id": "Qwen/Qwen3-Embedding-0.6B",
"label": "Qwen/Qwen3-Embedding-0.6B",
Expand Down
2 changes: 1 addition & 1 deletion desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"model-catalog:check": "uv run --frozen python scripts/model-catalog.py --check",
"tauri": "tauri",
"sync:branding": "node scripts/sync-branding.mjs",
"icons": "npm run sync:branding && tauri icon ../docs/images/logo.png --output src-tauri/icons",
"icons": "tauri icon ../docs/images/logo.png --output src-tauri/icons && npm run sync:branding",
"predesktop:dev": "npm run sync:branding",
"desktop:dev": "tauri dev",
"predesktop:build": "npm run icons",
Expand Down
5 changes: 5 additions & 0 deletions desktop/runtime-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
"extra": "actor",
"modality": "actor",
"label": "Actor recognition"
},
"videoprism": {
"extra": "videoprism",
"modality": "videoprism",
"label": "Temporal video search"
}
},
"media_runtime": {
Expand Down
10 changes: 9 additions & 1 deletion desktop/scripts/sync-branding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ const desktopRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const source = resolve(desktopRoot, "../docs/images/logo.png");
const publicDirectory = resolve(desktopRoot, "public");
const favicon = resolve(publicDirectory, "icon.png");
const pluginLogo = resolve(desktopRoot, "../plugins/vidxp/assets/logo.png");
const artifactLogo = resolve(
desktopRoot,
"../src/vidxp/assets/artifact_download/vidxp-logo.png",
);
const generatedIcon = resolve(desktopRoot, "src-tauri/icons/128x128.png");

mkdirSync(publicDirectory, { recursive: true });
copyFileSync(source, favicon);
console.log("Synced the VidXP desktop favicon from the shared icon.");
copyFileSync(source, pluginLogo);
copyFileSync(generatedIcon, artifactLogo);
console.log("Synced VidXP branding from docs/images/logo.png.");
Loading
Loading