-
live.html and dance.html already have independent scheduling pools (architecture.md 2.1), distinguished by clips' channel field, but admin.html rendered everything as one flat table with no way to tell the two apart or scope edits to one room. Add a 视频直播间/跳舞直播间 tab switcher that filters the table by channel, lets manual adds pick which room they land in, and lets existing rows be reclassified via the edit form's new channel select (backed by server.js's existing channel support on POST/PATCH /api/admin/library, committed in e96d689 as part of an unrelated concurrent session's work). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011DUiYs6UjxDMkfvnjtsKFo
-
T20: register now also creates a kind='email_verify' session (24h TTL) and calls sendVerificationEmail() — the one pluggable seam for a real provider once one's chosen (dev-plan-3.md §1 flagged no vendor exists yet). Outside production the register response carries a devVerifyUrl so the whole loop is testable without a real inbox. GET /api/auth/verify?token= flips emailVerified and revokes the token so it can't be replayed. T21: register reads any existing viewer_uid/viewer_nickname cookie (live.html/dance.html's plain client-set identity, unrelated to this session system) and carries it onto the new account as legacyUid/ nickname. Login pushes that legacyUid back onto the browser via Set-Cookie — even from a clean browser with no viewer_uid cookie at all — so logging into an account doesn't let someone dodge per-viewer_uid vote limits by starting a fresh anonymous identity each time. No history is rewritten, per dev-plan-3.md's explicit scope cut. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
POST /api/auth/register, POST /api/auth/login, POST /api/auth/logout, and a debug GET /api/auth/me (T19's own acceptance criteria calls for it explicitly). Passwords hashed with node:crypto's scryptSync (salt stored alongside the hash, verified with timingSafeEqual) — still zero new dependencies. Sessions live in a separate user_session cookie from admin_session (T6) — the two are unrelated systems, confirmed by a test that a user session can't unlock /api/admin/*. Login and "email not registered" return the identical 401 body so the endpoint can't be used to enumerate registered emails. Every test file that spawns server.js in an isolated tmpdir now also copies db.js alongside it (dance-channel/dressup-generate/dressup-crud/ admin-pages-flow/uploads-route .test.js) — server.js requires db.js unconditionally now, so those child processes were crashing silently without it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
New db.js opens data.sqlite (node:sqlite's DatabaseSync — a Node 24 built-in, experimental but functional) and creates the users/sessions tables per dressup-dance-room-mvcp.md M.1/M.10. Zero new npm dependency: no bcrypt/argon2 (node:crypto's scryptSync covers password hashing in T19), no better-sqlite3, no package.json needed. Mirrors store.js's ergonomics (create/get/update, plain JS objects in and out — booleans and the oauthProviders array marshalled to/from SQLite's TEXT/INTEGER columns internally) rather than reaching for an ORM. Exports the openDb/createUsersStore/createSessionsStore factories alongside a default singleton so tests can point at an isolated tmp file instead of the real data.sqlite (same pattern dressup-generate.test.js uses for library.json). data.sqlite is gitignored under the secrets section, not the "runtime state" one — unlike library.json it holds real credential material (password hashes, session tokens), not just regenerable content. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
h3ConsoleFetch blindly JSON.parses the response body regardless of status code; a momentary non-JSON 500 from H3 Console during polling (GET /v1/videos/:id) rejected the promise, which the poll loop let propagate straight to the outer catch — permanently marking the job "failed" even though the job was still fine on H3's side. Hit this for real today: a 20-job batch's concurrent polling briefly 500'd H3 Console's HTTP layer, and all 20 jobs got marked failed locally while every one of them was still queued/running on H3 (confirmed via direct GET /v1/videos/:id against the real console). Now a failed poll attempt is swallowed and retried on the next tick, bounded by the same wall-clock deadline as everything else (12aff60). Only a genuine terminal status (done/error/failed/cancelled) or deleted_at ends the job. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Breaks down dressup-dance-room.md 9节 phase 3 (dressup-dance-room.md 9节第3条: email login, bind anonymous viewer_uid to an account, no credits/payment yet) into T18-T22 with acceptance criteria, work estimates, and a dependency graph, same format as dev-plan.md/ dev-plan-2.md. Key decisions: users/sessions land in SQLite per architecture.md 1.4's own trigger condition (credential storage), using Node 24's built-in node:sqlite + node:crypto scryptSync — zero new npm dependency, no package.json needed. Flags one real gap the requirements doc's 待验证 list missed: no email-delivery vendor has been chosen, so T20 ships a pluggable sendVerificationEmail() with a dev-mode bypass rather than blocking on that decision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Same hue-recolor approach as the first 10 (dev-plan.md's exit bar needs >=30 garments given M.7's per-character-garment dedupe), batch generation for the new 20 already submitted to H3. Also stops tracking uploads/ — binary image/video content, not a good git citizen, and this content is explicitly placeholder ("占位旗袍" / "待替换") the user intends to replace wholesale later. The recipe (characters/garments/dance-refs.json) stays tracked; the files they point at don't. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y -
Spawned server.js with cwd: __dirname (the real repo path, not an isolated copy), so its own test.after() cleanup — rm -rf on "uploads/" — wiped every real uploaded file in the repo on every `node --test` run, not just what the test itself created. Discovered after running the suite several times today silently deleted this session's real character/garment/dance-ref source images (the generated dance videos in library.json were unaffected — those proxy from H3, not served from disk — but admin/dance.html thumbnails broke until the images were re-uploaded). Now spawns from an fs.mkdtempSync isolated copy and cleans up only that tmpdir, matching the pattern already used correctly in dressup-generate.test.js and dance-channel.test.js. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
The rebuild path for non-edited entries only carried `likes` forward from the old record; playCount and lastPlayedAt were dropped, so any clip not yet touched in admin.html had its play stats silently reset to "never played" on every periodic sync (server.js runs this every 5 min). Now carries both forward when present, and leaves them absent for a genuinely never-played clip rather than writing a false 0. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Same category as live-state.json/dance-state.json: rewritten by ingest.js's periodic sync and by every clip play (playCount/ lastPlayedAt), so every commit touching it was just churn from whoever last had the server running locally. File stays on disk, just untracked going forward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Records the 2026-09-02 real-H3 verification of T1-T10 (11 videos / 10 garments, the barefoot reference-video leak finding, the two bugs found and fixed) and cross-references that T11-T17 (dev-plan-2.md) landed the same day from a separate session, so the docs don't read as stale the next time someone opens them. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
…ce refs, 11 generated videos Real (non-test) content for T1-T10's asset libraries, entered through the actual admin CRUD flow (admin-characters/garments/dance-refs.html endpoints) rather than test fixtures: 1 default character, 10 garment variants, 3 reference dance videos. Batch-generated through T9's /api/admin/batch-gen against the real H3 Console — 11 dance videos landed in library.json (one combo generated twice from a dedupe race before the edited:true fix), all with characterId/garmentId/ refDanceVideoId traceability. Quality note found while spot-checking: 3 of the 11 clips show bare feet instead of the character reference's boots, and all three trace back to the same dance-ref ("轻柔手势舞", sourced from the S1-spike's control clip) — the reference video's own footwear leaks through despite the prompt's explicit "weak_reference" instruction. Worth avoiding barefoot reference footage when curating real dance-refs. This doesn't yet hit dev-plan.md's phase-1 exit bar of >=30 videos (that requires 30 garments given the M.7 per-character-garment dedupe cap; this seeds 10) but is enough real content for dance.html's wardrobe to have something to show. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y -
H3's 4 GPUs run one sharded model (H3-CONSOLE.md /v1/status), not 4 independent workers, so a batch of N jobs is served ~serially. The poll loop's old fixed 200-iteration budget (~1000s at the 5s default interval) didn't account for queue depth: submitting a 9-job batch hit this live and 9/11 jobs got marked "generation timed out" locally while still sitting healthy in H3's queue (queue_position confirmed via GET /v1/videos/:id). Also treats H3's "cancelled" status as terminal, matching "error"/"failed". Recovered the wrongly-failed jobs by resetting them to "generating" in generation-jobs.json (their h3JobId was already set, so resumeDressupGenerations() picked them back up without resubmitting to H3) rather than resubmitting and burning the queue further. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
ingest.js's syncLibrary() only carries a library entry forward as-is when edited is true; otherwise its periodic auto-sync (every 5 min) rebuilds the record from the raw H3 job and silently drops channel/characterId/garmentId/refDanceVideoId. That broke the M.7 dedupe cache and would have let dance clips leak into the regular live-channel pool once channel got wiped. Caught while running a real batch generation: the second sync cycle stripped a clip's traceability fields within 5 minutes of it landing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Backend (server.js): - T11: dance.html gets its own schedule/queue state machine, persisted to dance-state.json (gitignored, same as live-state.json). Per MVCP M.8, the schedule stores videoId references rather than inlined clip snapshots like live's does, joining back to library.json at read time. Generalized pickBestIndexByStatus/extracted pickLeastPlayedClip so both channels' schedulers share the same selection logic instead of forking it; live's random-fill pool now excludes channel:"dance" clips (and vice versa) so the two channels' filler picks stay independent, which wasn't true before this (T8's dance clips could have leaked into live.html's filler). - T12: GET /api/dance/wardrobe — public, unauthenticated list of active garments. - T15: POST /api/dance/pick {garmentId, nickname?} — free path, always uses the configured default character, reuses submitGeneration (T8/T9) whole including its M.7 dedupe cache, then hands the result to danceQueue. In-flight generations are reconciled against generationJobs on each schedule tick rather than via a promise chain, so a pick request survives a server restart the same way T8's own jobs do. - T17: separate danceViewers map and POST /api/dance/queue/vote/:id, so viewer counts and votes don't mix with live.html's. - SCHEDULE_TICK_MS env var makes both channels' tick interval configurable so tests don't wait out a real 2s. Frontend: - dance.html (T13/T14/T16): reuses live.html's visual language via live.css, adds dance.css for the 9:16 boxed player and wardrobe grid. Left column is a 衣柜/传衣服/传人 tab set (only 衣柜 is wired up — the other two need accounts/credits, dev-plan-2.md 第三/四期); right column shows the queue with vote buttons instead of live.html's chat. Age-confirmation gate (5.1节) blocks the page on first visit via a cookie, non-dismissable by clicking the backdrop. Tests: dance-channel.test.js spins up a mock H3 Console (same approach as dressup-generate.test.js) to exercise wardrobe listing, pick rejection/happy-path/dedupe, vote, and independent viewer counts end to end. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
Breaks down dev-plan.md's phase-2 scope (dressup-dance-room.md 9节 第2条: dance.html + 免费衣柜模式 + 去重缓存, no paid modes/accounts/ credits yet) into T11-T17 with acceptance criteria, work estimates, and a dependency graph, same format as dev-plan.md's T1-T10. Notes that dev-plan.md's own phase-1 exit criterion (batch-generate >=30 seed videos with real assets) is still outstanding and is an operational step, not blocking this plan but blocking the wardrobe actually having content once T11-T17 land. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
-
Fetches characters/garments/dance-refs alongside the library on load and joins each clip's characterId/garmentId/refDanceVideoId back to their names, so an operator can see "谁的脸 + 谁的衣服 + 哪条参考视频" per row (M.7). No composedImageId column — the one-step pipeline never produces an intermediate composed image. Extends the dressup-generate.test.js happy-path test to confirm the join resolves real names, not just matching ids. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
POST /api/admin/batch-gen takes {characterId, garmentIds[], refDanceVideoIds?[]}, expands to one job per garment (cross-producted with refDanceVideoIds when given, else one random active dance-ref per garment like the single-generate default), and submits each through the same submitGeneration() helper the single POST /api/admin/generate route now uses — so the M.7 dedupe cache (existing characterId+ garmentId combo) is honored per combo, not just per batch. GET /api/admin/batch-gen/status?batchId= returns that batch's generationJobs records for progress polling. admin-batch-gen.html: pick one character, multiple garments, and optionally pin specific reference dances; submits the batch, polls status every 3s into a progress table, and lets failed rows be retried individually via POST /api/admin/generate. Linked from the other admin pages' nav. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
generateDanceVideo() takes a queued generationJobs record through prompt build -> forward character/garment/dance-ref uploads to H3 Console's /v1/assets -> POST /v1/videos -> poll -> push a traced clip into library.json (characterId/garmentId/refDanceVideoId). Mirrors generateForPrompt's submit/poll/persist shape but keyed off the new generationJobs store so a restart resumes any in-flight job by its h3JobId, same as resumeGenerations() does for the live queue. POST /api/admin/generate accepts characterId/garmentId (+ optional refDanceVideoId, else a random active dance-ref is picked) and skips straight to the cached clip if that character x garment combo was already generated (M.7 dedupe). GET /api/admin/generate/:id polls job status. Tests spin up a mock H3 Console over HTTP so the full submit/poll/land path runs offline. Also fixes two existing test fixtures (dressup-crud, admin-pages-flow) that spawn server.js without copying prompt-template.js — worked until T8 added the first require() of it into server.js, at which point the spawned server silently failed to boot. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
buildStage2Prompt() renders MVCP M.15's confirmed one-step six-section template and enforces the two dynamic risks M.15.1 flagged: caps appearanceDescriptor/garmentDescriptor at ~40 words each, and truncates motionDescriptor if it alone would push detailed_description past H6's 500-word cap (the only placeholder that lands in that section). Also fixes the footwear-drift the S1 spike found (model self-selected shoes when the prompt didn't constrain them) — pins footwear to <Picture 1> in both subject_definitions and retention_analysis, and says <Picture 2> doesn't affect it. Propagated the same fix into the M.15 template in the MVCP doc so the doc and the code don't drift. Tests check the mechanical M.15.1 items that are checkable from the rendered string (H1/H5/H6/H9) plus the truncation behavior and the footwear fix. H13 (reference counts) is a submission-payload concern, covered by T8's tests instead.
-
Table + inline edit + add-form pages matching admin.html's existing conventions, wired to the T3-T5 CRUD API and T2's upload endpoints. Cross-linked with admin.html and each other in the topbar. No browser tooling available in this environment to render/click through these, so admin-pages-flow.test.js exercises the exact API call sequence each page's JS performs (login -> upload a real file -> create with the returned URL -> list -> confirm the shape the table renders), which is where a field-name mismatch would surface.
-
POST /api/admin/upload-video: mp4 magic-byte sniff (checks the ftyp box, not offset-0 like images), 50MB cap, no re-encode needed (unlike images, no EXIF/GPS concern for video). Reuses the multipart parser and uploads/ layout from T2's image path via a shared placeInUploads helper.
-
mountCrud() is a small generic GET-list/POST-create/PATCH/DELETE router shared across the three entities (same shape, see MVCP M.3/M.4/M.5) instead of copy-pasting the boilerplate three times. Each entity fills in its own admin_seed-appropriate defaults on create. characters additionally enforces the single-default-character invariant (2 节) across create/update. HTML admin pages for these come next.
-
Single shared password (.env ADMIN_PASSWORD) + in-memory HttpOnly session cookie, no accounts/roles — MVCP M.1/M.10's real account system supersedes this in period 3. Covers the existing /api/admin/library/* routes (previously unauthenticated, see architecture.md 1.2's tech-debt note) plus the new upload endpoint. admin.html gets a fetch() interceptor that redirects to the new admin-login.html on any 401 from /api/admin/*, rather than patching every call site.
-
POST /api/admin/upload: hand-rolled multipart parser (no deps installed in this project), real magic-byte sniffing (rejects extension-spoofed files), 8MB cap, and EXIF/GPS stripping via a sips bmp round-trip (macOS-native, no dependency — sips's direct jpeg->jpeg re-encode alone does NOT strip EXIF, only the bmp intermediate does). GET /uploads/* serves the result with a path-traversal guard. forwardToH3Assets() is the T7/T8 hook for pushing a saved upload to H3 Console's own POST /v1/assets (found in the S1-S4 spike) — not covered by the automated suite since it needs a live network call, same treatment as the spike scripts.
-
S1: person+garment images directly into ref2va with attribute_transfer produce correct face/outfit/motion in one call — no separate compose step needed. S2: reference_video_urls has a real, strong effect on output motion (A/B tested). S4: H3 Console's own POST /v1/assets endpoint (undocumented until now) solves asset reachability without exposing our own uploads/ publicly. Evidence and scripts in spike/s1-s2-s4-2026-09-02/. Propagated the one-step design into the requirements doc, MVCP design doc, the architecture doc, and H3-CONSOLE.md; dev-plan.md's spike section marked done and its task table updated accordingly.
-
Generic createStore(filePath) shared by characters.json/garments.json/ dance-refs.json, same full-read/full-write pattern as library.json. Not yet wired into server.js routes — that's T3-T5.
-
Duration: fixed 10s (within H3's 4-15s hard constraint), frames=240 @ 24fps. Prompt: follows the internal H3 prompt-writing methodology already sitting in the repo (docs/h3skill.md, from a parallel session) — the "all-purpose reference mode" six-section structure. Character appearance details are auto-captioned from the Stage1 composed image (new composed_images. appearanceDescriptor field); dance motion phrasing is admin-authored once per reference video (new dance_refs.motionDescriptor field), since the format requires concrete descriptors and forbids "as shown in the picture." Flagged as needing a pass through h3skill.md's own 22-item mechanical acceptance checklist before production use, not claimed as fully compliant. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SdtXTsDRz5QWMjvt1HBXLz
-
H3_GEN_PARAMS.frames 120 -> 240 (at 24fps, 5s -> 10s), still within H3's 4-15s range (H2 in docs/h3skill.md). Updated the prompt-optimization system prompt's duration reference and widened its word budget (40-70 -> 60-100) to match — still one continuous shot, just more room to let the camera move and the action unfold. Verified against the real GLM endpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
Previously left as inline "勘误" patch notes; now the baseline doc (docs/done) states the current 480x832 default outright, and the dance-room docs describe live.html/dance.html as two independently configured H3_GEN_PARAMS that happen to agree, rather than flagging an erratum. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SdtXTsDRz5QWMjvt1HBXLz
-
Data model, front/back-end view inventory, button-level control design, and per-user-type process flows for the not-yet-built feature. Also corrects the requirements doc's stale "live.html stays landscape" claim now that H3_GEN_PARAMS was changed to portrait there too (commit 1dc7084). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SdtXTsDRz5QWMjvt1HBXLz
-
The previous system prompt asked GLM for a free-form "shot-by-shot" expansion, which reliably produced 4-5 fake cuts with timestamps running out to 8-10s — impossible for a clip fixed at ~5s (H3_GEN_PARAMS.frames / FPS). Rewrote it against docs/h3skill.md (MiniMax's own H3 prompt-writing methodology, added alongside this commit): every chat prompt has no reference images, so it's always T2VA mode, and at ~5s it's one continuous shot, never a montage. The new prompt asks for H3's actual three-field T2VA structure (integrated_multimodal_description / overall_soundscape / non_diegetic_music, fixed order and labels), a single dominant camera movement from the official vocabulary (type + amplitude + speed), concrete lighting (no hollow buzzwords like "8K"/"cinematic" alone), and — previously missing entirely — explicit sound design. Verified against the real GLM endpoint on several sample prompts: single continuous shot throughout, correct field structure, no more impossible multi-shot timestamps. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
Documents the new outfit-swap dance live room (dance.html) requirements alongside the existing text-prompt live channel baseline, plus the combined system architecture covering both. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SdtXTsDRz5QWMjvt1HBXLz
-
Adds a prompt-optimization step ahead of H3 generation: a viewer's short chat line ("一只猫跳舞") gets expanded into a detailed shot-by-shot English prompt (camera work, lighting, action, setting) via one GLM Coding Plan call (glm-5.3-flash, /api/coding/ endpoint — the coding-plan-specific path, not the pay-per-token one) before being handed to H3. The expanded prompt becomes the clip's fullPrompt; the original short text stays as the display prompt. Persisted on the queue entry so a restart mid-generation doesn't re-call GLM. Best-effort throughout — no API key, a timeout, or any GLM error just falls back to using the original text unchanged, never blocking generation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ -
Swaps the H3_GEN_PARAMS default so future chat-triggered generations come out mobile-friendly (9:16) instead of 832x480 landscape. Existing library clips keep whatever aspect ratio they were generated at — the player already uses object-fit: contain, so mixed aspect ratios render fine either way. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
Adds playCount to each library clip, incremented every time it airs (markPlayed). The idle-filler pick in pickNextClip now randomizes only among the least-played clips in the eligible pool — everyone at 0 plays first, then everyone tied at 1, and so on — instead of picking uniformly at random across the whole library, which let some clips rack up far more airtime than others by chance alone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
The video autoplays muted underneath a full-screen splash — logo, play icon, slogan and a credit line, matching infiniteslop.ai's own splash. Clicking it is the user gesture that lets the browser allow unmuted playback, so desktop viewers land with sound instead of the silent-until-you-find-the-mute-button experience from the previous change. Mobile stays muted after entry, same as infiniteslop.ai, since unmuted autoplay-adjacent playback is unreliable there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
Drops the muted attribute and tries an unmuted autoplay first; if the browser blocks unmuted autoplay (no prior user gesture on the page), falls back to muted playback and syncs the mute button label to match. Once a viewer unmutes once, later clip switches keep playing with sound. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ
-
Reworks live.css/live.html to match infiniteslop.ai's visual language: Tahoma bold type, pure-black canvas, hot-pink accent, and hand-drawn white cards with a thick black border + hard offset shadow for every button/bubble/prompt card. Left queue now groups into 接下来播放/生成中/排队中 sections, the center gets a white "now playing" card (time + requester + prompt) plus a pulsing LIVE pill, chat bubbles are colored per-nickname via a pastel hash, and the top bar gained a chat-close toggle alongside mute and the watching count. Adds real upvoting to go with the new queue UI: POST /api/queue/vote/:id toggles a per-viewer (cookie uid) vote on a queued prompt, and pickNextClip now schedules the highest-voted matched/ready entry first instead of strict FIFO — lets chat bump a favorite prompt to the front of the line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144MiJ2cLjMd9jWaeEpVfUJ