feat(video): resolve video metadata from the Assets API - #14340
Conversation
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1769 passed, 0 failed · 1 flaky📊 Browser Reports
📦 Bundle: 8.18 MB gzip 🔴 +68 BDetailsSummary
Category Glance App Entry Points — 3.66 kB (baseline 3.66 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.29 MB (baseline 1.29 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 1 unchanged Views & Navigation — 112 kB (baseline 112 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 12 added / 12 removed / 4 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 15 unchanged User & Accounts — 29.1 kB (baseline 29.1 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 6 added / 6 removed / 1 unchanged UI Components — 70.7 kB (baseline 70.7 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 removed / 9 unchanged Data & Services — 3.43 MB (baseline 3.43 MB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 14 added / 14 removed / 3 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 20 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.6 MB (baseline 12.6 MB) • 🔴 +943 BBundles that do not match a named category
Status: 69 added / 69 removed / 209 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-30T03:03:45.017Z",
"gitSha": "59c8ac631c7dfe0bbc7520269f6f96d1025a8303",
"branch": "feat/video-metadata-via-assets",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2069.788999999986,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.491,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 571.941,
"heapDeltaBytes": -22351220,
"heapUsedBytes": 45595744,
"domNodes": 18,
"jsHeapTotalBytes": 20176896,
"scriptDurationMs": 21.986,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2041.0790000000247,
"styleRecalcs": 11,
"styleRecalcDurationMs": 10.708,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 474.43,
"heapDeltaBytes": 3702600,
"heapUsedBytes": 72121284,
"domNodes": 22,
"jsHeapTotalBytes": 20049920,
"scriptDurationMs": 19.278999999999996,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2056.7379999999957,
"styleRecalcs": 81,
"styleRecalcDurationMs": 59.020999999999994,
"layouts": 12,
"layoutDurationMs": 3.9939999999999993,
"taskDurationMs": 1097.4510000000002,
"heapDeltaBytes": -1130900,
"heapUsedBytes": 66546796,
"domNodes": 64,
"jsHeapTotalBytes": 22409216,
"scriptDurationMs": 135.523,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1931.844999999953,
"styleRecalcs": 78,
"styleRecalcDurationMs": 41.832,
"layouts": 12,
"layoutDurationMs": 3.5309999999999993,
"taskDurationMs": 944.0260000000001,
"heapDeltaBytes": -17642588,
"heapUsedBytes": 50190080,
"domNodes": -275,
"jsHeapTotalBytes": 20176896,
"scriptDurationMs": 117.202,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1755.6089999999926,
"styleRecalcs": 31,
"styleRecalcDurationMs": 19.114,
"layouts": 6,
"layoutDurationMs": 0.652,
"taskDurationMs": 439.315,
"heapDeltaBytes": 7288400,
"heapUsedBytes": 75182740,
"domNodes": 77,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 24.749,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1738.083999999958,
"styleRecalcs": 31,
"styleRecalcDurationMs": 16.602,
"layouts": 6,
"layoutDurationMs": 0.6070000000000001,
"taskDurationMs": 394.831,
"heapDeltaBytes": 7330216,
"heapUsedBytes": 75567796,
"domNodes": 77,
"jsHeapTotalBytes": 19787776,
"scriptDurationMs": 22.294999999999995,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 577.8800000000217,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.605000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 387.37699999999995,
"heapDeltaBytes": -12473228,
"heapUsedBytes": 55620808,
"domNodes": 18,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 54.784,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "dom-widget-clipping",
"durationMs": 575.0370000000089,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.142,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 377.102,
"heapDeltaBytes": -12102248,
"heapUsedBytes": 55997572,
"domNodes": 20,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 53.317,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66666666666665,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "large-graph-idle",
"durationMs": 2028.855999999962,
"styleRecalcs": 6,
"styleRecalcDurationMs": 6.187000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 742.542,
"heapDeltaBytes": 6523552,
"heapUsedBytes": 66266260,
"domNodes": -278,
"jsHeapTotalBytes": 4780032,
"scriptDurationMs": 104.78599999999999,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2028.218000000038,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.134000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 717.1949999999999,
"heapDeltaBytes": 7347868,
"heapUsedBytes": 66744268,
"domNodes": -277,
"jsHeapTotalBytes": 4780032,
"scriptDurationMs": 102.47500000000001,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2172.67099999998,
"styleRecalcs": 69,
"styleRecalcDurationMs": 14.315999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1333.264,
"heapDeltaBytes": 5115452,
"heapUsedBytes": 64884664,
"domNodes": -276,
"jsHeapTotalBytes": 5246976,
"scriptDurationMs": 422.94200000000006,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2164.536999999939,
"styleRecalcs": 69,
"styleRecalcDurationMs": 14.578999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1330.29,
"heapDeltaBytes": 2886756,
"heapUsedBytes": 62730672,
"domNodes": -277,
"jsHeapTotalBytes": 4984832,
"scriptDurationMs": 413.87300000000005,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-zoom",
"durationMs": 3299.7399999999857,
"styleRecalcs": 65,
"styleRecalcDurationMs": 15.769000000000002,
"layouts": 60,
"layoutDurationMs": 8.026,
"taskDurationMs": 1555.783,
"heapDeltaBytes": 3792112,
"heapUsedBytes": 65226688,
"domNodes": -281,
"jsHeapTotalBytes": 7401472,
"scriptDurationMs": 528.867,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3235.190999999986,
"styleRecalcs": 64,
"styleRecalcDurationMs": 14.626999999999997,
"layouts": 60,
"layoutDurationMs": 7.953999999999999,
"taskDurationMs": 1510.8120000000001,
"heapDeltaBytes": 22781680,
"heapUsedBytes": 84844876,
"domNodes": 10,
"jsHeapTotalBytes": 8126464,
"scriptDurationMs": 513.961,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2042.6169999999502,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.454000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 767.242,
"heapDeltaBytes": 6334416,
"heapUsedBytes": 66951260,
"domNodes": -278,
"jsHeapTotalBytes": 4780032,
"scriptDurationMs": 108.25200000000001,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2033.1150000000662,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.691,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 700.4869999999999,
"heapDeltaBytes": 6812644,
"heapUsedBytes": 67159780,
"domNodes": -277,
"jsHeapTotalBytes": 3993600,
"scriptDurationMs": 103.098,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 627.7019999999993,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.216999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 431.45799999999997,
"heapDeltaBytes": -11822092,
"heapUsedBytes": 56272640,
"domNodes": 20,
"jsHeapTotalBytes": 21884928,
"scriptDurationMs": 123.77499999999999,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 606.9200000000592,
"styleRecalcs": 46,
"styleRecalcDurationMs": 9.801,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 400.673,
"heapDeltaBytes": -11706288,
"heapUsedBytes": 56204740,
"domNodes": 18,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 118.093,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2020.2229999999872,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.636000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 477.672,
"heapDeltaBytes": 3406776,
"heapUsedBytes": 71492480,
"domNodes": 20,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 16.756,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2035.2960000000166,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.273,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 523.401,
"heapDeltaBytes": -22311104,
"heapUsedBytes": 45771980,
"domNodes": 22,
"jsHeapTotalBytes": 20701184,
"scriptDurationMs": 16.989000000000004,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1757.4680000000171,
"styleRecalcs": 79,
"styleRecalcDurationMs": 43.791,
"layouts": 16,
"layoutDurationMs": 5.44,
"taskDurationMs": 851.959,
"heapDeltaBytes": -5440316,
"heapUsedBytes": 62580756,
"domNodes": 66,
"jsHeapTotalBytes": 21360640,
"scriptDurationMs": 94.95100000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1769.407000000001,
"styleRecalcs": 78,
"styleRecalcDurationMs": 37.089,
"layouts": 16,
"layoutDurationMs": 4.144,
"taskDurationMs": 869.711,
"heapDeltaBytes": -21852768,
"heapUsedBytes": 46120008,
"domNodes": 64,
"jsHeapTotalBytes": 20963328,
"scriptDurationMs": 89.932,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-transition-enter",
"durationMs": 1367.7409999999668,
"styleRecalcs": 18,
"styleRecalcDurationMs": 27.467,
"layouts": 14,
"layoutDurationMs": 11.318999999999999,
"taskDurationMs": 940.9709999999998,
"heapDeltaBytes": 29484068,
"heapUsedBytes": 97541664,
"domNodes": 13673,
"jsHeapTotalBytes": 15990784,
"scriptDurationMs": 34.639,
"eventListeners": 2371,
"totalBlockingTimeMs": 117,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8258.938,
"styleRecalcs": 251,
"styleRecalcDurationMs": 41.31,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4843.589,
"heapDeltaBytes": 8903972,
"heapUsedBytes": 69728244,
"domNodes": -272,
"jsHeapTotalBytes": 6819840,
"scriptDurationMs": 1402.957,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8277.25600000008,
"styleRecalcs": 250,
"styleRecalcDurationMs": 37.801,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4670.219999999999,
"heapDeltaBytes": 10734704,
"heapUsedBytes": 69748244,
"domNodes": -275,
"jsHeapTotalBytes": 7081984,
"scriptDurationMs": 1374.846,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 15465.02700000002,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15439.578000000001,
"heapDeltaBytes": -53790368,
"heapUsedBytes": 172158600,
"domNodes": -8312,
"jsHeapTotalBytes": -9900032,
"scriptDurationMs": 547.79,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 15215.498000000025,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15186.167999999998,
"heapDeltaBytes": -35333792,
"heapUsedBytes": 171859156,
"domNodes": -8312,
"jsHeapTotalBytes": -4653056,
"scriptDurationMs": 560.8789999999999,
"eventListeners": -16390,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 18882.462000000032,
"styleRecalcs": 124,
"styleRecalcDurationMs": 16.49199999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18850.790999999997,
"heapDeltaBytes": -64981980,
"heapUsedBytes": 154274404,
"domNodes": -8312,
"jsHeapTotalBytes": -12750848,
"scriptDurationMs": 895.1560000000001,
"eventListeners": -16387,
"totalBlockingTimeMs": 47,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 18433.25500000003,
"styleRecalcs": 121,
"styleRecalcDurationMs": 16.342999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18408.861,
"heapDeltaBytes": -43056768,
"heapUsedBytes": 177272268,
"domNodes": -8312,
"jsHeapTotalBytes": -13131776,
"scriptDurationMs": 828.287,
"eventListeners": -16383,
"totalBlockingTimeMs": 16,
"frameDurationMs": 17.223333333333237,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 457.9580000000192,
"styleRecalcs": 13,
"styleRecalcDurationMs": 16.485,
"layouts": 2,
"layoutDurationMs": 0.3389999999999999,
"taskDurationMs": 116.16699999999999,
"heapDeltaBytes": -15933268,
"heapUsedBytes": 51225720,
"domNodes": 130,
"jsHeapTotalBytes": 7991296,
"scriptDurationMs": 10.465999999999998,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "workflow-execution",
"durationMs": 457.3319999999512,
"styleRecalcs": 12,
"styleRecalcDurationMs": 21.703,
"layouts": 3,
"layoutDurationMs": 0.5299999999999999,
"taskDurationMs": 110.821,
"heapDeltaBytes": -15922760,
"heapUsedBytes": 51070068,
"domNodes": 117,
"jsHeapTotalBytes": 7467008,
"scriptDurationMs": 9.039,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
📝 WalkthroughWalkthrough
ChangesVideo metadata retrieval
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Client
participant fetchVideoMetadata
participant AssetsAPI
participant MetadataParser
Client->>fetchVideoMetadata: provide view URL
fetchVideoMetadata->>fetchVideoMetadata: parse trusted URL
fetchVideoMetadata->>AssetsAPI: request matching asset
AssetsAPI-->>fetchVideoMetadata: return asset list
fetchVideoMetadata->>MetadataParser: parse asset metadata
MetadataParser-->>fetchVideoMetadata: return video fields or null fallback
fetchVideoMetadata-->>Client: return VideoMetadata or undefined
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/utils/videoMetadataUtil.test.ts`:
- Around line 79-103: Extend the fetchVideoMetadata tests around the existing
missing-video-metadata case to add a separate asset with empty or absent
metadata.kind. Assert that fps, duration, frame_count, width, and height remain
null while size is preserved, covering the fallback for missing kind in addition
to the existing incorrect-kind case.
In `@src/utils/videoMetadataUtil.ts`:
- Around line 77-88: Update the asset lookup around the `api.fetchApi` call and
`zAssetListResponse` parsing to paginate through all result pages, continuing
while `has_more` is true until an asset with exact `name === file.filename` is
found. Preserve the existing early return when no exact match exists after
pagination, and reuse the API’s pagination fields and request parameters.
🪄 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: ASSERTIVE
Plan: Pro Plus
Run ID: d053f5c4-080b-41a6-a97b-9366e3067477
📒 Files selected for processing (2)
src/utils/videoMetadataUtil.test.tssrc/utils/videoMetadataUtil.ts
| it('still returns the file size when the asset lacks video metadata', async () => { | ||
| mockResponse(true, { | ||
| assets: [ | ||
| { | ||
| id: 'asset-1', | ||
| name: 'a.mp4', | ||
| size: 4096, | ||
| metadata: { kind: 'image' } | ||
| } | ||
| ] | ||
| }) | ||
|
|
||
| const result = await fetchVideoMetadata( | ||
| '/api/view?filename=a.mp4&type=input' | ||
| ) | ||
|
|
||
| expect(result).toEqual({ | ||
| fps: null, | ||
| duration: null, | ||
| frame_count: null, | ||
| width: null, | ||
| height: null, | ||
| size: 4096 | ||
| }) | ||
| }) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Cover missing metadata.kind separately.
This only covers an incorrect kind (image). Add a metadata: {} or absent-metadata case and assert the null video fields with preserved size; the fallback also handles missing kind.
As per path instructions, tests must cover missing/incorrect metadata.kind.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/videoMetadataUtil.test.ts` around lines 79 - 103, Extend the
fetchVideoMetadata tests around the existing missing-video-metadata case to add
a separate asset with empty or absent metadata.kind. Assert that fps, duration,
frame_count, width, and height remain null while size is preserved, covering the
fallback for missing kind in addition to the existing incorrect-kind case.
Source: Path instructions
| const params = new URLSearchParams({ | ||
| include_tags: includeTags.join(','), | ||
| name_contains: file.filename, | ||
| limit: '100' | ||
| }) | ||
|
|
||
| try { | ||
| const response = await api.fetchApi(`/video_metadata?${query}`) | ||
| const response = await api.fetchApi(`/assets?${params}`) | ||
| if (!response.ok) return undefined | ||
| return zVideoMetadata.parse(await response.json()) | ||
| const { assets } = zAssetListResponse.parse(await response.json()) | ||
| const asset = assets.find((entry) => entry.name === file.filename) | ||
| if (!asset) return undefined |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n -C3 'name_contains|include_tags|limit.*100|/assets' src docsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 50385
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- src/utils/videoMetadataUtil.ts ---\n'
cat -n src/utils/videoMetadataUtil.ts | sed -n '1,130p'
printf '\n--- videoMetadataUtil tests around relevant assertions ---\n'
cat -n src/utils/videoMetadataUtil.test.ts | sed -n '1,120p'
printf '\n--- assetService list asset pagination/filter helpers ---\n'
cat -n src/platform/assets/services/assetService.ts | sed -n '340,410p'
printf '\nassetService query/filter constants references:\n'
rg -n "name_contains|exact|after|limit|DEFAULT_LIMIT|getAssets|ListAsset" src/platform/assets/services/assetService.ts src/platform/assets/schemas src/platform/assets/types -g '*.ts' --max-count 50
printf '\n--- asset schemas names and pagination/filter fields ---\n'
cat -n src/platform/assets/schemas/assetSchema.ts | sed -n '1,140p'Repository: Comfy-Org/ComfyUI_frontend
Length of output: 255
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- src/utils/videoMetadataUtil.ts ---'
cat -n src/utils/videoMetadataUtil.ts | sed -n '1,130p'
printf '%s\n' ''
printf '%s\n' '--- videoMetadataUtil tests around relevant assertions ---'
cat -n src/utils/videoMetadataUtil.test.ts | sed -n '1,120p'
printf '%s\n' ''
printf '%s\n' '--- assetService list asset pagination/filter helpers ---'
cat -n src/platform/assets/services/assetService.ts | sed -n '340,410p'
printf '%s\n' ''
printf '%s\n' 'assetService query/filter constants references:'
rg -n "name_contains|exact|after|limit|DEFAULT_LIMIT|getAssets|ListAsset" src/platform/assets/services/assetService.ts src/platform/assets/schemas src/platform/assets/types -g '*.ts' --max-count 80
printf '%s\n' ''
printf '%s\n' '--- asset schemas pagination/filter fields ---'
cat -n src/platform/assets/schemas/assetSchema.ts | sed -n '1,140p'Repository: Comfy-Org/ComfyUI_frontend
Length of output: 21325
🌐 Web query:
ComfyUI Assets API name_contains exact name list assets name_eq documentation
💡 Result:
In the ComfyUI Cloud API for listing assets, the name_contains parameter is supported as a query parameter for filtering assets where the name contains a specific substring (case-insensitive) [1][2]. Regarding your query for name_eq, this parameter is not documented in the official ComfyUI API reference for asset listing [1][2]. Based on the source code definitions for the API's input schemas (ListAssetsQuery), only name_contains is implemented as a string field for name filtering [3][4][5]. There is no standard name_eq (exact match) filter exposed via these query parameters; filtering by exact name would typically require retrieving the list and performing the match on the client side [1][6]. Summary of relevant filtering parameters for /api/assets: - name_contains: Filter assets where the name contains this substring (case-insensitive) [1][2]. - include_tags: Filter assets that have ALL of these tags [1][2]. - exclude_tags: Exclude assets that have ANY of these tags [1][2]. - metadata_filter: JSON object for filtering by metadata fields [1][2].
Citations:
- 1: https://docs.comfy.org/api-reference/cloud/asset/list-user-assets
- 2: https://github.com/Comfy-Org/docs/blob/main/openapi-cloud.yaml
- 3: https://github.com/Comfy-Org/ComfyUI/blob/c011fb52/app/assets/api/schemas_in.py
- 4: https://github.com/Comfy-Org/ComfyUI/blob/79c555ce/app/assets/api/schemas_in.py
- 5: https://github.com/Comfy-Org/ComfyUI/blob/64cc0780/app/assets/api/schemas_in.py
- 6: https://github.com/Comfy-Org/ComfyUI/blob/c011fb52/app/assets/api/routes.py
Paginate when searching assets by filename.
name_contains only filters substrings, while this call returns a single page of 100 assets. If the exact-name asset is beyond that page and previous pages only contain partial matches (for example name_prefix/a.mp4), metadata resolution returns undefined. Use pagination until has_more is false and the exact name === file.filename asset is found, or use a true exact-name filter if the API provides one.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/videoMetadataUtil.ts` around lines 77 - 88, Update the asset lookup
around the `api.fetchApi` call and `zAssetListResponse` parsing to paginate
through all result pages, continuing while `has_more` is true until an asset
with exact `name === file.filename` is found. Preserve the existing early return
when no exact match exists after pagination, and reuse the API’s pagination
fields and request parameters.
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14340 +/- ##
==========================================
- Coverage 79.55% 79.50% -0.06%
==========================================
Files 1759 1760 +1
Lines 111692 112034 +342
Branches 37626 37797 +171
==========================================
+ Hits 88860 89071 +211
- Misses 22313 22434 +121
- Partials 519 529 +10
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 15 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Summary
Now the VIDEO_EDIT widget is merged, this replaces the /video_metadata probe with the Assets API as the metadata source. fetchVideoMetadata matches the /view URL to an asset record (type/subfolder tags + exact name) and reads duration/fps/frame_count/width/height from the asset metadata field populated by asset ingest.
Requires --enable-assets and the backend feat/asset-video-metadata branch.