Commit graph

17 commits

Author SHA1 Message Date
7a2710dc9a docs: design spec for YouTube importer
Adds a paste-URL ingest path under Ingest → YouTube. Worker hosts
yt-dlp, downloads to S3, then hands off to the existing proxy +
thumbnail pipeline so imported assets share one lifecycle with uploads.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:04:28 -04:00
6a1d271576 feat(ui): polish round 2 — live refresh, schedule calendar, jobs times, real sidebar user
- recorders: dispatch df:recorders-changed on create/start/stop/delete so the
  list updates immediately instead of waiting for the 10s poll tick
- library: poll every 4s while any asset is live/processing (15s otherwise) and
  listen for df:assets-changed so a stopped recorder's LIVE badge drops and
  the thumbnail appears without a manual refresh
- auth: synthetic /auth/me (AUTH_ENABLED=false) now uses LOCAL_OPERATOR / USER /
  USERNAME instead of hardcoding "Admin", and flags synthetic:true
- shell: Sidebar takes `me` as a prop, drops the misleading "Admin" fallback,
  and surfaces an "auth off" hint when the response is synthetic
- jobs: replace the always-empty ETA column with a Time column that shows
  queued/started/done/failed N ago (full timestamp on hover); widen column
- schedule: new month-calendar view (default) with events plotted on day cells
  by status; clicking a day pre-fills the new-schedule modal with a 30-min
  window on that day; List view kept behind a toggle

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 14:52:04 -04:00
7e64675aa5 fix: settings S3 surfaces fetch errors; recorder signal dot pulses
- screens-admin.jsx S3SettingsCard: when /settings/s3 fails, log to
  console and surface the message in the existing SettingsMsg banner
  instead of silently returning empty fields. Also logs the response
  payload on success so the next "endpoint blank" report is easier to
  diagnose. (closes part of #15)
- screens-ingest.jsx recorder row: wrap the signal value in a dot+text
  pair; add CSS so the dot pulses green when status=receiving and
  matches the value color otherwise. The pulse is the kind of cue the
  Live signal column was missing per #2.
2026-05-23 13:19:48 -04:00
claude
7170a9945c polish: schedule edit + README refresh
- Schedule: pending rows get an 'Edit' button next to Cancel/Delete;
  opens a modal that PUTs /schedules/:id with new name/times/recurrence
  (recorder reassignment is intentionally locked — delete + recreate
  to swap recorder)
- README rewritten: project renamed to dragonflight, full feature
  catalog (ingest, growing-files, scheduler, library + comments,
  jobs, settings, cluster), accurate ports, refreshed architecture
  diagram, ops scripts inventory
2026-05-23 04:26:03 +00:00
claude
90a9e4361a feat(comments): persistent frame-anchored comments on asset detail
- migration 010: asset_comments table (id, asset_id, user_id, body,
  frame_ms, resolved, timestamps) with index on asset_id+created_at
- new routes mounted at /api/v1/assets/:assetId/comments — GET/POST/
  PATCH/DELETE with author join (display_name + initials), nullable
  user_id so comments still attach when AUTH_ENABLED is off
- Asset detail loads comments from the API on mount instead of the
  empty ZAMPP_DATA.COMMENTS seed; addComment POSTs and merges the
  returned row; resolved-toggle and delete are wired
- CommentsList: new trash-icon delete action per comment, helpful
  empty-state copy ('Add one below to mark a frame'), tooltips on
  the timestamp and resolved buttons

Now editor comments survive page reload, are visible to other users
via the same API, and pin reliably to frame_ms (integer) instead of
a parsed HH:MM:SS:FF string.
2026-05-23 04:21:11 +00:00
claude
7da171cf1f polish: defensive hydration defaults on ZAMPP_DATA accessors
Guards against the brief window between app mount and the first
data load completing — empty arrays render gracefully instead
of throwing on .filter / .map.
2026-05-23 04:17:36 +00:00
claude
24820e921e polish: schedule past-time confirm, recorder name sanitization, asset detail player controls
- Schedule: if start_at is more than a minute in the past, confirm()
  before submitting (operator may want to fire immediately, but
  shouldn't do it accidentally)
- Recorders: generateClipName now sanitizes the recorder name so the
  S3 key / SMB path / ffmpeg arg stays clean — spaces become
  underscores, anything outside [A-Za-z0-9._-] is dropped, capped at 40
- Asset detail: audio mute + fullscreen buttons now key off streamUrl
  state (rather than videoRef.current which is null on first render)
  so they reliably appear when a stream is available
2026-05-23 04:12:42 +00:00
claude
9877ed351f fix(recorders): queue proxy on finalize + custom clip names
- POST /api/v1/assets: when transitioning from 'live' to 'processing'
  with a hi-res key but no proxy, queue a proxy job instead of just
  flipping status='ready'. Recorder-captured clips now get a proxy
  + thumbnail like upload-path assets do
- POST /api/v1/recorders/:id/start now accepts { clipName } in the body;
  operator-supplied name (sanitized to [A-Za-z0-9 ._-], capped at 80)
  overrides the auto-generated <recorder>_<timestamp> fallback
- RecorderRow gets a 'Clip name (optional)' input visible when stopped;
  Enter triggers Record, value sent on POST start, cleared on stop
- New POST /api/v1/assets/:id/generate-proxy and
  POST /api/v1/assets/backfill-proxies for one-shot cleanup of pre-fix
  clips that have a hi-res master but no proxy
2026-05-23 03:41:03 +00:00
claude
53196d38ce feat(scheduler): recorder scheduling — UI, CRUD, tick loop, recurrence
- New Ingest → Schedule page: upcoming/past/all tabs, status badges
  (pending / recording / completed / cancelled / failed), 10s
  auto-refresh, cancel/delete actions
- New Schedule modal: name, recorder dropdown, datetime-local start/end,
  recurrence (one-shot / daily / weekly), sensible defaults (+5min / +35min)
- Backend: migration 009 (recorder_schedules), routes/schedules.js
  (list/create/edit/cancel/delete), scheduler.js tick loop polling every
  15s; transitions trigger /recorders/:id/start and /stop via in-process
  HTTP so we reuse the full container orchestration path
- Recurring schedules: tick loop auto-queues the next occurrence on
  completion (daily = +24h, weekly = +7d)
- Sidebar + app.jsx route wired in, schedule-row table style added
2026-05-23 03:19:24 +00:00
328f7b4f31 feat: live HLS preview, proxy worker fixes, Settings tabs, growing-files + Premier panel
- worker/proxy: scale-to-even filter, analyzeduration 100M, skip images, hasAudio
- worker/promotion: SMB landing zone -> S3 on idle, queues proxy job, status='ready'
- web-ui screens-ingest: HlsPreview component replaces fake LiveStrip/FauxFrame
- web-ui screens-admin: functional Settings tabs (S3, GPU, Growing, SDI, AMPP)
- mam-api /settings/growing: GET/PUT growing-files config
- mam-api /assets/:id/live-path: SMB UNC/POSIX path for live growing assets
- capture-manager: GROWING_ENABLED -> write hires to /growing instead of S3 stream
- recorders.js: pass GROWING_ENABLED to capture container, bind /growing mount
- docker-compose: mount /mnt/NVME/MAM/wild-dragon-growing on mam-api + worker
- premiere-plugin: Mount Live button, Relink-to-HiRes, live->ready status poll
2026-05-22 19:12:53 -04:00
d00e1c666e screens-ingest: wire delete button on RecorderRow 2026-05-22 12:24:10 -04:00
665ab5238d feat: live status polling in RecorderRow, immediate refresh on mount 2026-05-22 11:35:13 -04:00
26399f8d0a fix: implement real upload (XHR + S3 multipart) and fix SDI recorder device_index + manual fallback: screens-ingest.jsx 2026-05-22 11:10:00 -04:00
24a1d57165 fix: SDI crash, monitors polling, home RAM fields, editor IN DEV splash, timecode, create recorder API: screens-ingest.jsx 2026-05-22 10:55:19 -04:00
406f28c663 feat(ui): wire ingest screens to real API (recorders, capture devices): screens-ingest.jsx 2026-05-22 10:07:13 -04:00
20dfa504e5 Add Z-AMPP UI: screens-ingest + screens-admin: screens-ingest.jsx 2026-05-22 08:22:37 -04:00
0945f488f6 feat(ui): Dragonflight redesign — ingest, jobs, editor, admin screens: screens-ingest.jsx 2026-05-22 08:20:15 -04:00