feat(website): add responsive media tooling for marketing assets#11869
feat(website): add responsive media tooling for marketing assets#11869
Conversation
Adds <SiteVideo> Vue component that renders a multi-source <video> tag, plus a buildVideoSources() helper for URL construction. Component pairs with media.comfy.org assets named <name>-<width>.<format> to give marketing pages proper webm + mp4 fallbacks via <source>.
Local developer tool that produces multi-resolution VP9/WebM + H.264/MP4 variants and a poster JPG for source videos. Naming matches buildVideoSources() so outputs drop straight into media.comfy.org and pair with <SiteVideo>. Not wired into CI by design; the team uploads to media.comfy.org out-of-band.
Adds shared MARKETING_FORMATS / MARKETING_WIDTHS constants and a README for src/assets/marketing/. Pages render local marketing images via Astro's built-in <Picture> with these defaults; a custom wrapper is intentionally avoided because Astro's LocalImageProps | RemoteImageProps discriminated union does not survive a thin wrapper without unsafe casts.
Wraps source list in computed() so prop changes propagate. Keys the <video> element on the joined source URLs to force a remount when the source set changes (browsers do not reload <video> when nested <source> children mutate). Restricts aria-hidden=true to the decorative case (no alt and no controls) to avoid hiding interactive controls from assistive tech. Adds videoKey() helper plus tests.
… extensions Probe duration with ffprobe and fall back to t=0 when the clip is shorter than 1s; the previous fixed -ss 00:00:01 aborted the script under set -e for short clips. Enable nocaseglob so camera-exported files like CLIP.MP4 are picked up. Documents the new ffprobe dependency.
Adds a section explaining when to use the lightweight multi-source SiteVideo vs the full-featured VideoPlayer with controls, captions, and scrubber. Updates the poster note to reflect the new short-clip fallback behavior.
SiteVideo, marketingImage, and the VideoFormat / VideoSource type exports are intentionally unreferenced until follow-up PRs adopt them. Mark the files in knip.config ignore (matching the existing 'Pending integration in stacked PR' pattern) and tag the unused type exports with @knipIgnoreUsedByStackedPR.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds video and marketing asset tooling: a Bash script to transcode videos and extract posters; TypeScript utilities to build typed video source lists and keys; a Vue SiteVideo component; marketing image constants; READMEs and tests; and knip ignores for the new files. (Documentation + new runtime UI + scripts + tests.) ChangesVideo & Marketing Asset System
Sequence DiagramsequenceDiagram
actor Dev as Developer
participant Script as process-videos.sh
participant Src as Source Files
participant Media as Output Media
participant Utils as buildVideoSources()
participant Comp as SiteVideo.vue
participant Browser as Browser/Video Tag
Dev->>Script: run (inputDir, outputDir, widths)
Script->>Src: read source video files
Script->>Media: write {name}-{w}.webm, {name}-{w}.mp4, {name}-poster.jpg
Dev->>Comp: render with name, baseUrl, width, formats
Comp->>Utils: call buildVideoSources(name, baseUrl, width, formats)
Utils->>Comp: return VideoSource[] (src,type,format)
Comp->>Browser: render <video> with <source> tags and poster
Browser->>Media: request video files
Browser->>Browser: play video
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 7✅ Passed checks (7 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 3/5 reviews remaining, refill in 18 minutes and 15 seconds. Comment |
🌐 Website E2ETip All tests passed.
🔗 Website PreviewWebsite Preview: https://comfy-website-preview-pr-11869.vercel.app This commit: https://website-frontend-d1f5hod9k-comfyui.vercel.app Last updated: 2026-05-04T06:24:17Z for |
|
Acknowledged — that's a CodeRabbit rate-limit notice, not review feedback, so there's nothing to address. No code changes will be pushed for it. The review can be re-triggered with |
🎭 Playwright: ✅ 1467 passed, 0 failed📊 Browser Reports
|
📦 Bundle: 5.26 MB gzip 🟢 -37 BDetailsSummary
Category Glance App Entry Points — 22.6 kB (baseline 22.6 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.24 MB (baseline 1.24 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 81.8 kB (baseline 81.8 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed / 2 unchanged Panels & Settings — 489 kB (baseline 489 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 10 added / 10 removed / 11 unchanged User & Accounts — 17.5 kB (baseline 17.5 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 5 added / 5 removed / 2 unchanged Editors & Dialogs — 112 kB (baseline 112 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 4 added / 4 removed UI Components — 62.9 kB (baseline 62.9 kB) • ⚪ 0 BReusable component library chunks
Status: 5 added / 5 removed / 9 unchanged Data & Services — 3.05 MB (baseline 3.05 MB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 13 added / 13 removed / 4 unchanged Utilities & Hooks — 365 kB (baseline 365 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 13 added / 13 removed / 18 unchanged Vendor & Third-Party — 9.94 MB (baseline 9.94 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 8.84 MB (baseline 8.84 MB) • ⚪ 0 BBundles that do not match a named category
Status: 57 added / 57 removed / 78 unchanged ⚡ Performance Report
No regressions detected. All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-05-04T06:50:46.926Z",
"gitSha": "7a71f002ae9c350b41046fd386f91ab79a5b12ed",
"branch": "glary/responsive-media-tooling",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2013.6909999999943,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.386999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 379.45199999999994,
"heapDeltaBytes": 23427508,
"heapUsedBytes": 71692116,
"domNodes": 18,
"jsHeapTotalBytes": 14680064,
"scriptDurationMs": 16.826999999999995,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2008.1610000000296,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.498999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 347.405,
"heapDeltaBytes": 23407524,
"heapUsedBytes": 71692180,
"domNodes": 17,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 16.330000000000002,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-idle",
"durationMs": 2030.33999999991,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.574,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 350.92,
"heapDeltaBytes": 22806484,
"heapUsedBytes": 71543672,
"domNodes": 18,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 17.282000000000007,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1962.5800000000027,
"styleRecalcs": 78,
"styleRecalcDurationMs": 43.866,
"layouts": 12,
"layoutDurationMs": 5.709,
"taskDurationMs": 846.6289999999999,
"heapDeltaBytes": -5078436,
"heapUsedBytes": 43871928,
"domNodes": -266,
"jsHeapTotalBytes": 15855616,
"scriptDurationMs": 128.589,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1798.7660000000005,
"styleRecalcs": 73,
"styleRecalcDurationMs": 33.62800000000001,
"layouts": 12,
"layoutDurationMs": 3.2050000000000005,
"taskDurationMs": 785.119,
"heapDeltaBytes": -3505612,
"heapUsedBytes": 45200556,
"domNodes": -264,
"jsHeapTotalBytes": 15331328,
"scriptDurationMs": 128.466,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1772.6109999999835,
"styleRecalcs": 74,
"styleRecalcDurationMs": 35.215,
"layouts": 12,
"layoutDurationMs": 3.236,
"taskDurationMs": 763.067,
"heapDeltaBytes": 7857976,
"heapUsedBytes": 56139196,
"domNodes": -263,
"jsHeapTotalBytes": 15593472,
"scriptDurationMs": 124.68099999999998,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1717.488000000003,
"styleRecalcs": 30,
"styleRecalcDurationMs": 15.258999999999999,
"layouts": 6,
"layoutDurationMs": 0.5249999999999999,
"taskDurationMs": 291.69800000000004,
"heapDeltaBytes": 189952,
"heapUsedBytes": 48886492,
"domNodes": 75,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 18.309000000000005,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1753.0549999999607,
"styleRecalcs": 32,
"styleRecalcDurationMs": 19.919,
"layouts": 6,
"layoutDurationMs": 0.6299999999999999,
"taskDurationMs": 308.952,
"heapDeltaBytes": -101604,
"heapUsedBytes": 48109144,
"domNodes": 77,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 19.752,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1753.7740000000213,
"styleRecalcs": 32,
"styleRecalcDurationMs": 19.665,
"layouts": 6,
"layoutDurationMs": 0.7050000000000001,
"taskDurationMs": 322.897,
"heapDeltaBytes": 205080,
"heapUsedBytes": 48878696,
"domNodes": 78,
"jsHeapTotalBytes": 14942208,
"scriptDurationMs": 21.618,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 552.9389999999808,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.563000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 324.003,
"heapDeltaBytes": 8550444,
"heapUsedBytes": 57163896,
"domNodes": 16,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 56.65400000000001,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "dom-widget-clipping",
"durationMs": 583.6630000000014,
"styleRecalcs": 12,
"styleRecalcDurationMs": 11.367000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 353.4240000000001,
"heapDeltaBytes": 9784708,
"heapUsedBytes": 58705992,
"domNodes": 20,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 64.976,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "dom-widget-clipping",
"durationMs": 528.4450000000334,
"styleRecalcs": 10,
"styleRecalcDurationMs": 6.970999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 325.61899999999997,
"heapDeltaBytes": 9420040,
"heapUsedBytes": 58658072,
"domNodes": 15,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 57.31900000000001,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "large-graph-idle",
"durationMs": 2072.8129999999965,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.642999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 550.371,
"heapDeltaBytes": 14095716,
"heapUsedBytes": 72166532,
"domNodes": -262,
"jsHeapTotalBytes": 290816,
"scriptDurationMs": 97.103,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2012.7110000000243,
"styleRecalcs": 8,
"styleRecalcDurationMs": 8.811,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 532.0229999999999,
"heapDeltaBytes": 2754340,
"heapUsedBytes": 61288912,
"domNodes": -263,
"jsHeapTotalBytes": 28672,
"scriptDurationMs": 93.2,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2037.0220000000927,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.440999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 567.298,
"heapDeltaBytes": 12571752,
"heapUsedBytes": 69596852,
"domNodes": -260,
"jsHeapTotalBytes": 28672,
"scriptDurationMs": 106.215,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2141.42099999998,
"styleRecalcs": 68,
"styleRecalcDurationMs": 17.907,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1099.966,
"heapDeltaBytes": 18400664,
"heapUsedBytes": 78906240,
"domNodes": -266,
"jsHeapTotalBytes": 4718592,
"scriptDurationMs": 400.31600000000003,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2133.5540000000037,
"styleRecalcs": 67,
"styleRecalcDurationMs": 16.791,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1087.211,
"heapDeltaBytes": -1368248,
"heapUsedBytes": 58180748,
"domNodes": -267,
"jsHeapTotalBytes": 6262784,
"scriptDurationMs": 391.32,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-pan",
"durationMs": 2145.77799999995,
"styleRecalcs": 68,
"styleRecalcDurationMs": 17.553,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1078.0320000000002,
"heapDeltaBytes": -5926816,
"heapUsedBytes": 53497596,
"domNodes": -264,
"jsHeapTotalBytes": 5533696,
"scriptDurationMs": 384.344,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3167.5409999999715,
"styleRecalcs": 64,
"styleRecalcDurationMs": 17.123999999999995,
"layouts": 60,
"layoutDurationMs": 7.172,
"taskDurationMs": 1362.715,
"heapDeltaBytes": -8297548,
"heapUsedBytes": 53784224,
"domNodes": -269,
"jsHeapTotalBytes": 4542464,
"scriptDurationMs": 511.806,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3178.437000000031,
"styleRecalcs": 65,
"styleRecalcDurationMs": 18.209,
"layouts": 60,
"layoutDurationMs": 7.420000000000001,
"taskDurationMs": 1366.8280000000002,
"heapDeltaBytes": 9293288,
"heapUsedBytes": 70376028,
"domNodes": -269,
"jsHeapTotalBytes": 28672,
"scriptDurationMs": 521.887,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3119.8770000000877,
"styleRecalcs": 64,
"styleRecalcDurationMs": 16.735999999999997,
"layouts": 60,
"layoutDurationMs": 7.292,
"taskDurationMs": 1319.452,
"heapDeltaBytes": 8274316,
"heapUsedBytes": 69498512,
"domNodes": -270,
"jsHeapTotalBytes": 4485120,
"scriptDurationMs": 491.08799999999997,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2036.245000000008,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.828,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 532.551,
"heapDeltaBytes": 14605244,
"heapUsedBytes": 75856544,
"domNodes": -262,
"jsHeapTotalBytes": 3756032,
"scriptDurationMs": 92.86100000000002,
"eventListeners": -131,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2026.7999999999802,
"styleRecalcs": 6,
"styleRecalcDurationMs": 5.891,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 538.4290000000001,
"heapDeltaBytes": 10208288,
"heapUsedBytes": 71289000,
"domNodes": -270,
"jsHeapTotalBytes": 28672,
"scriptDurationMs": 98.128,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2046.7409999999973,
"styleRecalcs": 9,
"styleRecalcDurationMs": 12.077000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 561.171,
"heapDeltaBytes": 14964788,
"heapUsedBytes": 75486612,
"domNodes": -258,
"jsHeapTotalBytes": -233472,
"scriptDurationMs": 99.14699999999999,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 533.4170000000427,
"styleRecalcs": 46,
"styleRecalcDurationMs": 10.442,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 339.1329999999999,
"heapDeltaBytes": 9482928,
"heapUsedBytes": 57781096,
"domNodes": 17,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 115.371,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 512.6829999999813,
"styleRecalcs": 46,
"styleRecalcDurationMs": 10.520000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 346.47499999999997,
"heapDeltaBytes": 9062868,
"heapUsedBytes": 57716240,
"domNodes": 18,
"jsHeapTotalBytes": 16252928,
"scriptDurationMs": 116.90100000000001,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 550.0090000000455,
"styleRecalcs": 45,
"styleRecalcDurationMs": 9.920000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 351.78299999999996,
"heapDeltaBytes": 9037672,
"heapUsedBytes": 57805552,
"domNodes": 16,
"jsHeapTotalBytes": 15990784,
"scriptDurationMs": 129.105,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-idle",
"durationMs": 1991.1440000000198,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.776999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 333.28,
"heapDeltaBytes": 22351540,
"heapUsedBytes": 70864972,
"domNodes": 16,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 13.860999999999992,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 1997.4439999999731,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.906,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 333.19999999999993,
"heapDeltaBytes": 23269688,
"heapUsedBytes": 71881376,
"domNodes": 16,
"jsHeapTotalBytes": 14680064,
"scriptDurationMs": 14.999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2020.605000000046,
"styleRecalcs": 10,
"styleRecalcDurationMs": 10.254,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 363.947,
"heapDeltaBytes": 22503072,
"heapUsedBytes": 70928924,
"domNodes": 19,
"jsHeapTotalBytes": 14680064,
"scriptDurationMs": 17.130000000000006,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1675.8449999999812,
"styleRecalcs": 75,
"styleRecalcDurationMs": 37.842999999999996,
"layouts": 16,
"layoutDurationMs": 4.774,
"taskDurationMs": 668.221,
"heapDeltaBytes": 14841072,
"heapUsedBytes": 63317340,
"domNodes": 60,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 94.69,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1673.5410000000002,
"styleRecalcs": 75,
"styleRecalcDurationMs": 37.379000000000005,
"layouts": 16,
"layoutDurationMs": 4.262999999999999,
"taskDurationMs": 642.79,
"heapDeltaBytes": 13930376,
"heapUsedBytes": 63663088,
"domNodes": 61,
"jsHeapTotalBytes": 14680064,
"scriptDurationMs": 92.219,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1681.7810000000009,
"styleRecalcs": 74,
"styleRecalcDurationMs": 35.376999999999995,
"layouts": 16,
"layoutDurationMs": 4.379,
"taskDurationMs": 673.119,
"heapDeltaBytes": 14314720,
"heapUsedBytes": 62964600,
"domNodes": 59,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 96.389,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8131.992000000026,
"styleRecalcs": 250,
"styleRecalcDurationMs": 51.00599999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3659.866,
"heapDeltaBytes": 11537400,
"heapUsedBytes": 68298840,
"domNodes": -259,
"jsHeapTotalBytes": 6262784,
"scriptDurationMs": 1241.95,
"eventListeners": -113,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8140.0409999999965,
"styleRecalcs": 250,
"styleRecalcDurationMs": 54.307,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3920.646,
"heapDeltaBytes": 26724776,
"heapUsedBytes": 85054520,
"domNodes": -257,
"jsHeapTotalBytes": 8622080,
"scriptDurationMs": 1393.5970000000002,
"eventListeners": -113,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8152.612999999974,
"styleRecalcs": 250,
"styleRecalcDurationMs": 50.538,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3711.4650000000006,
"heapDeltaBytes": 11833716,
"heapUsedBytes": 69968364,
"domNodes": -263,
"jsHeapTotalBytes": 6524928,
"scriptDurationMs": 1244.4550000000002,
"eventListeners": -113,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "vue-large-graph-idle",
"durationMs": 12174.811000000034,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12161.795,
"heapDeltaBytes": -25701488,
"heapUsedBytes": 172467928,
"domNodes": -8331,
"jsHeapTotalBytes": 25489408,
"scriptDurationMs": 636.231,
"eventListeners": -16464,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.220000000000073,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 12149.050999999985,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12136.964,
"heapDeltaBytes": -23266880,
"heapUsedBytes": 168149448,
"domNodes": -8331,
"jsHeapTotalBytes": 20246528,
"scriptDurationMs": 600.2890000000001,
"eventListeners": -16464,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.216666666666665,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 12452.19099999997,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12437.691,
"heapDeltaBytes": -29075532,
"heapUsedBytes": 170811660,
"domNodes": -8331,
"jsHeapTotalBytes": 23392256,
"scriptDurationMs": 623.676,
"eventListeners": -16464,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 14094.403999999997,
"styleRecalcs": 64,
"styleRecalcDurationMs": 15.699999999999992,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14061.953000000003,
"heapDeltaBytes": -2687924,
"heapUsedBytes": 192688408,
"domNodes": -8331,
"jsHeapTotalBytes": 26451968,
"scriptDurationMs": 899.874,
"eventListeners": -16458,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 14282.198999999991,
"styleRecalcs": 66,
"styleRecalcDurationMs": 15.871000000000024,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14241.290000000003,
"heapDeltaBytes": -33097820,
"heapUsedBytes": 165365540,
"domNodes": -8329,
"jsHeapTotalBytes": -3346432,
"scriptDurationMs": 859.5699999999999,
"eventListeners": -16460,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 14558.477000000039,
"styleRecalcs": 68,
"styleRecalcDurationMs": 18.05399999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14534.809,
"heapDeltaBytes": -25149964,
"heapUsedBytes": 174724196,
"domNodes": -8335,
"jsHeapTotalBytes": -2908160,
"scriptDurationMs": 862.694,
"eventListeners": -16488,
"totalBlockingTimeMs": 26,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "workflow-execution",
"durationMs": 478.29300000000785,
"styleRecalcs": 23,
"styleRecalcDurationMs": 25.913999999999998,
"layouts": 5,
"layoutDurationMs": 1.718,
"taskDurationMs": 136.80200000000002,
"heapDeltaBytes": 5477544,
"heapUsedBytes": 55197100,
"domNodes": 194,
"jsHeapTotalBytes": 262144,
"scriptDurationMs": 26.258000000000003,
"eventListeners": 69,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 471.86199999998735,
"styleRecalcs": 15,
"styleRecalcDurationMs": 21.676000000000005,
"layouts": 5,
"layoutDurationMs": 1.2989999999999997,
"taskDurationMs": 132.57899999999998,
"heapDeltaBytes": -15173576,
"heapUsedBytes": 51914496,
"domNodes": 155,
"jsHeapTotalBytes": 4812800,
"scriptDurationMs": 24.325,
"eventListeners": 69,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 452.5979999999663,
"styleRecalcs": 18,
"styleRecalcDurationMs": 23.813,
"layouts": 4,
"layoutDurationMs": 1.033,
"taskDurationMs": 116.56699999999998,
"heapDeltaBytes": 5054644,
"heapUsedBytes": 56146796,
"domNodes": 157,
"jsHeapTotalBytes": 262144,
"scriptDurationMs": 22.908,
"eventListeners": 69,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
}
]
} |
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #11869 +/- ##
===========================================
- Coverage 71.79% 56.08% -15.71%
===========================================
Files 1492 1383 -109
Lines 85011 70796 -14215
Branches 23233 18814 -4419
===========================================
- Hits 61031 39708 -21323
- Misses 23091 30561 +7470
+ Partials 889 527 -362
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
b62248f to
9ec6640
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/website/scripts/README.md`:
- Around line 27-33: The fenced code block that lists the output files (the
block containing "foo-640.webm foo-640.mp4" through "foo-poster.jpg") is
missing a language identifier and triggers markdownlint MD040; update the
opening fence from ``` to ```text (or another appropriate language) so the block
becomes a labeled fenced code block (no other content changes required).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dd4b40cb-fee8-4b94-aff0-e1c5126be800
📒 Files selected for processing (8)
apps/website/scripts/README.mdapps/website/scripts/process-videos.shapps/website/src/assets/marketing/README.mdapps/website/src/components/common/SiteVideo.vueapps/website/src/utils/marketingImage.tsapps/website/src/utils/video.test.tsapps/website/src/utils/video.tsknip.config.ts
Adds a 'text' language identifier to the bare fenced code block listing the script's output files. Satisfies markdownlint MD040 (no markdownlint enforcement in this repo, but small improvement; flagged by CodeRabbit on PR #11869).
9ec6640 to
0b7de9d
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/website/scripts/process-videos.sh`:
- Around line 90-93: The ffprobe duration parsing can yield non-numeric values
so guard the comparison by validating that the duration variable is a numeric
value before using awk; update the block that assigns duration (the ffprobe
command result stored in the duration variable) to validate or normalize its
output (e.g., check duration matches a numeric/float regex or use awk to coerce
to 0 when non-numeric) and only run the numeric comparison (the current awk
"BEGIN { exit !($duration >= 1.0) }") when duration is numeric, otherwise set
poster_seek=0/skip the comparison so poster_seek is only set when a valid
numeric duration >= 1.0 is confirmed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 190268cb-68b7-4904-874e-6e1f467bdef7
📒 Files selected for processing (8)
apps/website/scripts/README.mdapps/website/scripts/process-videos.shapps/website/src/assets/marketing/README.mdapps/website/src/components/common/SiteVideo.vueapps/website/src/utils/marketingImage.tsapps/website/src/utils/video.test.tsapps/website/src/utils/video.tsknip.config.ts
✅ Files skipped from review due to trivial changes (4)
- apps/website/src/utils/marketingImage.ts
- apps/website/scripts/README.md
- apps/website/src/assets/marketing/README.md
- apps/website/src/utils/video.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- knip.config.ts
- apps/website/src/utils/video.ts
- apps/website/src/components/common/SiteVideo.vue
If ffprobe succeeds but emits a non-numeric value (e.g. N/A for unreadable streams, or empty for containers without duration metadata), the previous `awk "BEGIN { exit !($duration >= 1.0) }"` was a syntax error and aborted the whole script under set -euo pipefail. Validate the raw output against a numeric regex and fall back to 0 otherwise; pass duration into awk via -v to avoid eval-style interpolation. Flagged by CodeRabbit on #11869.
PR Created by the Glary-Bot Agent
Summary
Adds the building blocks for a responsive media system on
apps/website, motivated by the gallery video blurriness raised in Slack. Three independent pieces:<SiteVideo>Vue component + URL helper — emits a<video>with multiple<source>tags, designed to pair with assets named${name}-${width}.${format}onmedia.comfy.org.scripts/process-videos.sh— local-developerffmpeghelper that produces VP9/WebM + H.264/MP4 variants and a poster JPG. Not wired into CI; the team uploads tomedia.comfy.orgout-of-band.MARKETING_FORMATS/MARKETING_WIDTHSconstants and a README documenting how to render local marketing images via Astro's built-in<Picture>fromastro:assets.This PR is infrastructure only — no existing pages are modified. Adoption (e.g. converting
HeroSection, gallery videos) is a follow-up. The new files are added to knip's ignore list with the existing "pending stacked PR" pattern.Why this shape
<Picture>wrapper. Astro 5 already ships aResponsiveImagecomponent (name conflict), and Astro'sLocalImageProps | RemoteImagePropsdiscriminated union does not survive a thin wrapper without unsafeascasts. Shared constants give the consistency benefit at lower cost.Release: Websiteworkflow currently only refreshes the Ashby snapshot; wiring GCS uploads into it would require new secrets and team coordination beyond this PR's scope. The script runs locally and outputs are uploaded tomedia.comfy.orgthe same way as today.<video>.<source media="...">inside<video>is unreliable across browsers (Safari ignores it). The script generates multiple widths so callers can pick one per page; JS-based selection can be layered on later if metrics demand it.What's verified
pnpm --filter @comfyorg/website test:unit— 30 pass (7 new forbuildVideoSources/videoKey)pnpm --filter @comfyorg/website typecheck— cleanpnpm --filter @comfyorg/website build— 41 pages built cleanpnpm knip— exit 0oxfmt --checkandoxlintclean on all changed filesbash -nonprocess-videos.shclean; usage and missing-deps paths exercised manually/galleryrendered viaastro dev— both unchanged with zero console errors (screenshots attached)Review feedback addressed
After Oracle review, three follow-up commits land:
SiteVideoreactivity —sourcesis nowcomputed; the<video>is keyed on the joined source URLs so it remounts when the source set changes (browsers don't reload on<source>mutation).SiteVideoaccessibility —aria-hidden="true"only when truly decorative (noaltand nocontrols).ffprobeand falls back tot=0for clips shorter than 1s; enablesnocaseglobsoCLIP.MP4is picked up.<SiteVideo>(lightweight multi-source) vs<VideoPlayer>(captions, controls, scrubber).Out of scope (follow-ups)
HeroSection, customer detail heros, gallery) to use the new components. Most current images are CDN-hosted and migrating them is a separate decision.process-videos.shagainst the source clips and re-upload.<SiteVideo>'s multi-source support with<VideoPlayer>'s rich chrome.Screenshots
┆Issue is synchronized with this Notion page by Unito