Skip to main content

hugpy-video

The video arm of Hugpy (import name hugpy_video). The source tree is at 0.3.5; the installed deb and running service on this host are 0.3.4. It covers execution and artifacts for video work:

  • the media library jail and the sqlite media job bus, with its local runners (ffmpeg crop, frames and audio);
  • engine-backed generation (image, scene and movie), the studio spine (t2v/i2v clips, segmented movies, the model battery) and the GPU reservation engine;
  • the identity-profile library with relays to the identity render service;
  • LLM prompt assist;
  • the /video Video Intelligence console (SPA) and its toolset API (/api/video/*, /api/movie/*), served by its own service on 127.0.0.1:7341. Hugpy Core proxies both.

The arm contract (toolset → Blueprint → standalone server → arms.d → core proxy) is in docs/arms.md. How engine-backed routes choose and fall back between models is in docs/execute_prompt.md.

Dependency on hugpy-oracle

hugpy-oracle is a hard dependency (hugpy-oracle>=0.3.11,<0.4 in 0.3.5; >=0.3.10 in 0.3.4; operator ruling 2026-10-15). The dependency graph runs video → oracle. The oracle's use of video is lazy and optional: its video extra pulls in hugpy-video, and it reaches video's studio registry, runners and media bus only inside the functions that need them. Video imports the oracle lazily, inside the toolset callables that need it (studio/plan, producer/plan, performance/probe, script/runs, script/sources), so import hugpy_video loads no planner. The oracle's planners install into video's hooks (hugpy_video.bus.hooks) through hugpy_oracle.install_hooks(). That call is made idempotently by the planner routes, and by the hugpy.video.hooks entry point when hugpy_video.web.api loads.

Layout

src/hugpy_video/
  imports/        the shared layer: imports no optional or heavy backend
    constants.py  ARM_NAME="video", UI_PREFIX="/video/", every env-var NAME and default
    functions.py  env_value()/env_bool(), parse_env_file(), lazy()/first_lazy()
    classes.py    VideoError, ToolError (the toolset error, which becomes {"error": ...}),
                  JobError (the job error-as-data, lifted from hugpy_control in 0.3.5)
    store.py      stdlib cross-process sqlite helpers, lifted from hugpy_control in 0.3.5
                  (used by the studio-assist log and the reservation ledger; same env
                  names and paths, so existing stores keep working)
    init_imports.py, __init__.py
  toolset.py      get_toolset() -> {"video": {...}, "movie": {...}}, get_manifest()
  routes.py       video_bp = register_categories(get_bp("video"), get_toolset())
                  plus the native SSE escape hatches
  serve/          the standalone service: `hugpy-video serve` (app.py: create_app, serve)
  ui.py           dist_dir() -> ui_dist/ (built @hugpy/video-intelligence-ui)
  web/            the Flask view implementation the toolset adapts: api (read surface,
                  presets, identity library, media/clip bytes), generate, identity_write,
                  movie_routes, assist, studio_planning, render_catalog, jobstream (SSE),
                  studio_assist_log, video_intent
  bus/            the job-bus control plane: jobs (public API, register_job), job_events
                  (worker -> core transitions), hooks (PromptCoordinator and planner seams)
  intel/          media_store (refs and jail), media_bus (sqlite bus), job_bridge,
                  job_schema, presets, reservation/, runners/ (ffmpeg, diffusers plane,
                  studio, identity relays, MLT), studio/ (the studio spine), plane.py
                  (the one seam onto hugpy_engine.execute_prompt)
  chat_video/     chat-side frame analysis over a hugpy_media vision runner
  video_gen/      StudioVideoRunner / VideoGenRequest (engine runner for t2v/i2v)
  plugin.py       hugpy_engine.tasks entry point: text-to-video, image-to-video
  state.py        injectable state roots;  config.py  HUGPY_API_KEY / HUGPY_BASE loader
  cli.py          `hugpy-video`;  selftest.py;  sql/001_video_jobs_notify.sql
  _lifted/        helpers lifted from the retired monolith

The old top-level module paths (hugpy_video.api, .jobstream, .jobs, .hooks, .render_catalog, .studio_assist_log, ...) still import. They are transparent sys.modules aliases to the new locations. Wildcard imports are forbidden (tests/test_import_policy.py).

The toolset (video/* 56 routes, movie/* 2 routes)

Each route is GET+POST at /api/<category>/<route>, with a trailing-slash variant. Ids are kwargs (?job_id=, ?slug=, ?preset_id=, ?movie_id=), not path segments. The return value comes back as {"result": ...} and an error as 500 {"error": "<real message>"}. Byte routes return the file Response directly (status 200, 206 or 404 preserved). Source: toolset.get_toolset(), verified against the live GET /api/video/manifest.

Works standalone (no core, no GPU)

Route Notes
health, manifest identity; the manifest includes escape_hatches
jobs job bus listing; reads ?all, ?stale, ?limit, ?owner
job, job/cancel, job/private job_id; job/private reads private from the body
media handle: raw bytes for a jailed MediaRef (Range supported)
projects, presets catalog reads
studio/clips, studio/clip, studio/clip/detail, studio/clip/archive, studio/clip/unarchive job_id; studio/clip streams the mp4. Archive never deletes.
studio/presets, studio/presets/apply preset_id
identity-profiles, identity-profile, identity-profile/delete, identity-profile/private slug; delete archives, never hard-deletes
ingest turns a path under the video storage root into a MediaRef
jobs/crop, jobs/frame_extract, jobs/audio_extract ffmpeg runners on the local bus (needs ffmpeg; the deb depends on it)
prompt/assist/log, prompt/assist/ticket (ticket), studio/movies local reads
performance/probe the oracle's (oracle, performance) readiness, reported as data: ready, bound, unbound with the operator step for each gap
script/sources, script/runs the oracle's script-first run store. GET script/runs lists runs; POST starts one.
movie/presets, movie/presets/apply preset_id

Needs a reachable core and GPU fleet

Each of these first checks HUGPY_CORE_URL (default http://127.0.0.1:7020, 1.5 s). If nothing answers, the route raises ToolError naming the variable and /etc/hugpy/video.env, and does not enqueue anything. The check proves only that something answers HTTP at that URL; the fleet itself is reached later, through execute_prompt.

jobs/generate_image, jobs/generate_scene, jobs/generate_movie, studio/i2v, studio/tester, studio/movie, studio/movie/pause (movie_id), studio/movie/resume (movie_id), studio/plan and producer/plan (oracle-backed planners), prompt/assist, prompt/intent, prompt/assist/models, render/presets.

Needs the identity render service

These require IDENTITY_RENDER_URL (and IDENTITY_RENDER_TOKEN). Without it they raise a ToolError that names the variables:

identity-profiles/create, identity-profiles/from-video, identity-profiles/from-images, identity-profiles/video-extract, identity-profile/reconstruction (slug), identity-profile/canonical (slug), identity-profile/generate (slug). The identity extra installs the abstract-identity client. It does not start a GPU service.

Stubs: reachable, not implemented in this build

These always answer 500 {"error": "<route> is not implemented in this hugpy-video build: <what it needs>"}. They never return 404:

Route Missing piece
identity-render/probe the identity render service probe
studio/clip/to-editor the Filmora editor handoff (ffprobe/remux)
identity-profile/settings the identity gen_settings write (not ported)
identity-profile/update the identity profile name/notes write (not ported)
identity-profile/versions identity version management (not ported)

Escape hatches (native Blueprint routes)

Route Kind
GET /api/video/jobs/stream SSE. Sends a stream.ready marker, then one row per job transition, filtered to what the caller may see. Capped at one hour; the client re-seeds from video/jobs.
GET /api/video/prompt/assist/log/stream SSE: the studio assist log
POST /api/video/jobs/event internal ingest: a worker reports {job_id, status}. Returns 202. Not listed in escape_hatches.

The job stream is single-process by default. With HUGPY_VIDEO_JOBS_PG_DSN unset, a reported transition goes straight into this process's in-memory event ring and no Postgres listener starts. Set it (for example dbname=hugpy_video) only when several processes share one bus and need Postgres LISTEN/NOTIFY to fan events out. That needs sql/001_video_jobs_notify.sql and psycopg. If Postgres is then unreachable, the listener retries and the stream degrades to the initial seed.

Not served (pending)

  • POST /video/jobs/performance. The Oracle station's performance submit is not in the toolset, and the standalone service returns 404. The legacy web/api.py registers it only as a "501 not available" placeholder. Use performance/probe to see which seams are unbound.
  • Video UI uploads. The SPA's file stations (image crop, audio crop, frame extract, identity upload, studio generate) upload to /api/uploads. Neither this service nor core 0.4.40 serves that route (404).

Standalone service

hugpy-video serve [--host H] [--port P] [--env-file /etc/hugpy/video.env]

create_app() does the following:

  • loads the env file without overriding the environment;
  • creates the state directories and initialises the sqlite job bus;
  • builds abstract_flask.get_Flask_app(name="hugpy-video", routes=hugpy_video.routes, url_prefix="api");
  • serves the SPA at /video/ with history fallback. / and /video redirect to /video/. A build without ui_dist serves only the API.
  • forwards /v1/* (streamed) to HUGPY_CORE_URL. This exists because the UI's model pickers read core's /v1/models and /v1/task-bindings. With core unreachable it answers 503 {"error": "hugpy core unreachable at ..."}.

Then it runs Flask threaded, so SSE does not block other requests.

Demo media. The served index.html marker window.__HUGPY_MEDIA_BASE__ = window.__HUGPY_MEDIA_BASE__ ?? null; is rewritten from the environment. HUGPY_DEMO_MEDIA_DIR (served by this process at /demo-media/) takes precedence over HUGPY_DEMO_MEDIA_BASE (a URL).

curl -s 127.0.0.1:7341/api/video/health      # {"result":{"arm":"video","ok":true,"version":"0.3.4"}}
curl -s '127.0.0.1:7341/api/video/jobs?limit=5'
curl -s 127.0.0.1:7341/api/video/performance/probe
curl -sN 127.0.0.1:7341/api/video/jobs/stream

CLI

Command What it does
hugpy-video serve [...] the standalone service
hugpy-video jobs list [--all] [--limit N] [--json] the media job bus
hugpy-video jobs registry registered job names, runner keys, queues and timeouts
hugpy-video selftest in-process checks (no GPU, no service); exits 1 on failure
hugpy-video state prints the resolved state roots
hugpy-video models audit [--json] declared studio models: runner gaps, weight pin, VRAM by precision. Loads no weights.
hugpy-video --version

Environment

The names are defined in imports/constants.py.

Variable Default Effect
HUGPY_VIDEO_HOST / HUGPY_VIDEO_PORT 127.0.0.1 / 7341 bind address of serve
HUGPY_VIDEO_STATE_DIR <DEFAULT_ROOT>/video_intel (the deb uses /var/lib/hugpy-video) job bus and studio sessions
HUGPY_MEDIA_JOBS_DB <state>/media_jobs.db sqlite job bus
HUGPY_RESERVATIONS_DB <PROJECTS_HOME>/reservations.db GPU reservation ledger
STUDIO_OUTPUT_ROOT <state>/studio studio sessions and renders
DEFAULT_ROOT, UPLOADS_HOME, IDENTITIES_HOME, PROJECTS_HOME hugpy_platform (the deb sets DEFAULT_ROOT=/var/lib/hugpy-video/root) platform storage roots; the media jail is UPLOADS_HOME plus DEFAULT_ROOT
HUGPY_CORE_URL http://127.0.0.1:7020 engine preflight, /v1 forwarder, engine relays
HUGPY_VIDEO_JOBS_PG_DSN unset (single-process) multi-process job-stream fan-out
IDENTITY_RENDER_URL, IDENTITY_RENDER_TOKEN unset identity render service
HUGPY_DEMO_MEDIA_DIR, HUGPY_DEMO_MEDIA_BASE unset demo-media marker rewrite
HUGPY_WORKER_NAME unset worker identity on reported job events
HUGPY_API_KEY, HUGPY_BASE "", https://dev.hugpy.ai/api config.load_config() credentials. The legacy aliases CONSOLE_API, HUGPY_API_TOKEN, HUGPY_AGENT_API, HUGPY_API_KEY_NEWVM / HUGPY_BASE_URL, HUGPY_URL, HUGPY_CENTRAL are accepted and recorded in Config.deprecations.

Tuning knobs read by the runners include HUGPY_MEDIA_BUS_* (runners, lookahead, stale and reap timing), HUGPY_RESERVATION*, STUDIO_WEIGHTS_ROOT, STUDIO_MAX_VRAM_GB, STUDIO_ALLOW_UNPINNED and HUGPY_SCENE_CONCURRENCY. Their defaults live next to the code that reads them.

Debian package

BUILD_PYTHON=/usr/bin/python3 packaging/debian/build.sh     # -> build/debian/hugpy-video_<ver>_amd64.deb (Python 3.12)
sudo apt install ./build/debian/hugpy-video_<ver>_amd64.deb      # 0.3.4 is the newest deb built so far

build.sh bundles offline wheels for hugpy-video and its local siblings (hugpy-oracle, hugpy-platform, hugpy-media, hugpy-engine) and their public dependencies. The 0.3.4 deb also bundled hugpy-control and hugpy-storage. Neither is needed since video 0.3.5, oracle 0.3.11 and media 0.3.4. build.sh asserts that the wheel contains ui_dist/index.html and sql/001_video_jobs_notify.sql. The control file declares Depends: python3 (>= 3.12), python3 (<< 3.13), python3-venv, systemd, ffmpeg.

postinst:

  • builds /opt/hugpy-video/venv offline and force-reinstalls the bundled siblings;
  • creates the hugpy-video system user, a member of the hugpy group;
  • creates /var/lib/hugpy-video (mode 0750) with root/ inside it;
  • writes /etc/hugpy/video.env if it is absent;
  • writes hugpy-video.service (WorkingDirectory=/var/lib/hugpy-video, ProtectSystem=strict, ReadWritePaths set to the state directory);
  • writes /usr/share/hugpy/arms.d/video.json (categories video and movie, UI /video/; the upstream port follows video.env);
  • restarts the service.

Core then proxies /api/video/*, /api/movie/* and /video/*. postrm removes the unit and the arms.d file. On purge it also removes the venv, the state, video.env and the user. Host-level steps are in docs/install.md.

Dependencies

Runtime (pyproject.toml, 0.3.5): flask>=2, pydantic>=2, abstract-essentials, requests>=2.28, abstract-flask>=0.0.0.1052, hugpy-platform>=0.3.0, hugpy-media>=0.2.8, hugpy-engine>=0.3.2, hugpy-oracle>=0.3.11,<0.4.

hugpy-control is no longer a dependency as of 0.3.5. Its sqlite store helpers and JobError now live in hugpy_video.imports (store.py, classes.py). Version 0.3.4 depended on hugpy-control>=0.3.0.

Extras: render (numpy, Pillow, requests), studio (torch, diffusers, transformers and the rest of the GPU set), identity (abstract-identity), test. GPU and runtime pieces are never imported at module scope.

Entry points

Group Name → target
console_scripts hugpy-video → hugpy_video.cli:main
hugpy.arms video → hugpy_video.routes:video_bp
hugpy.toolsets video → hugpy_video.toolset:get_toolset
hugpy_engine.tasks video → hugpy_video.plugin:register (text-to-video, image-to-video)

Rules

  • Heavy imports are lazy. The package must import on a CPU-only box.
  • The version is single-sourced from pyproject.toml through importlib.metadata.
  • Credentials come only through hugpy_video.config.load_config.

UI

The SPA source is ui/video_intelligence_ui. Its build is copied into src/hugpy_video/ui_dist/, and the provenance is in ui_dist/PROVENANCE.md.

Get the Debian packages, architecture details, SHA-256 checksums and installation commands from Hugpy Downloads. The feature gallery shows the console, Agent, Station, Media and Video interfaces. Screenshots reflect the versions captured; the current interface may differ.

Video studio

A clip viewer, shot staging, model settings and generation controls.

Video studio

Metadata

Release files for hugpy-video 0.3.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hugpy-video 0.3.7
File Size Uploaded Provenance
hugpy_video-0.3.7.tar.gz 1.3 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hugpy-video 0.3.7
File Interpreter ABI Platform
hugpy_video-0.3.7-py3-none-any.whl Python 3 none any Details

Total release size: 2.6 MB

Release files / hugpy_video-0.3.7.tar.gz

Download URL hugpy_video-0.3.7.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
494702cd5c9765db2fe1a95fde453067dea6fd6f23d78a267675692c41404398
BLAKE2b-256 checksum
How to use checksums
5bc3754d50b174c5920516439d1c261f537b5606aa947ebb951311256fb6f47b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / hugpy_video-0.3.7-py3-none-any.whl

Download URL hugpy_video-0.3.7-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
f0bc140c96e6354ad666f31de594208624c7d6b040c5e1d3b87a78ccae627f32
BLAKE2b-256 checksum
How to use checksums
ef0697f491482cf1f93839de524bd7a11f9dd78c5ff7d1dfa7e66c6bd0e501ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for hugpy-video 0.3.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.7 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page