mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-13 15:49:53 +00:00
initial code (#2)
* feat: initial code port from hyperframes-internal Port all OSS-ready packages from the internal monorepo: - @hyperframes/core — shared types, HTML generation, GSAP utilities, runtime - @hyperframes/cli — CLI for creating, previewing, and rendering compositions - @hyperframes/engine — framework-agnostic rendering engine (BeginFrame + FFmpeg) - @hyperframes/producer — video rendering pipeline (Puppeteer + FFmpeg) - @hyperframes/ui-player — browser-based video player component - @hyperframes/studio — composition editor (React frontend + Hono backend) Includes regression test suite with Docker-based test harness. All HeyGen-internal references, deployment infrastructure, and proprietary assets have been removed. Package names migrated from @app/* to @hyperframes/*. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: scrub internal codenames and stale references from OSS port - Replace static.heygen.ai runtime URLs in test fixtures - Remove internal CDN publish script (publish-hyperframe-runtime.ts) - Replace sandbox-studio, sandbox-interceptor, __magicEditRuntime with neutral names (studio, hyperframe-runtime, __hyperframeRuntime) - Fix stale Vault API / localhost references in docs - Remove broken deprecated_studio link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove remaining internal codenames and stale references - Delete stale producer README.md and PIPELINE.md (referenced nonexistent files) - Replace "Cerberus" codename with "HyperFrames" in test design reviews - Replace magic-edit postMessage identifiers with hf-preview/hf-parent - Rename debug-magic-edit-timeline.ts to debug-timeline.ts - Replace "Motion Cut" with "HyperFrames" in Timeline comments - Fix studio/CLI references to nonexistent archive package (use local data/projects/ dir, stub render proxy) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
10621e7903
commit
9f8e5ba5a1
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "style-3-prod",
|
||||
"description": "Regression fixture imported from normalized style pack style-3-prod",
|
||||
"tags": [
|
||||
"style-regression",
|
||||
"prod-style",
|
||||
"slow",
|
||||
"landscape"
|
||||
],
|
||||
"minPsnr": 30,
|
||||
"maxFrameFailures": 0,
|
||||
"minAudioCorrelation": 0.9,
|
||||
"maxAudioLagWindows": 120,
|
||||
"renderConfig": {
|
||||
"fps": 30
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<svg viewBox="0 0 1920 1080" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1920" height="1080" fill="#F2F2F2" />
|
||||
|
||||
<g id="thin-grid-lines" stroke="#0A1E3D" stroke-width="1" opacity="0.1">
|
||||
<line id="v-thin-1" x1="60" y1="0" x2="60" y2="1080" />
|
||||
<line id="v-thin-2" x1="120" y1="0" x2="120" y2="1080" />
|
||||
<line id="v-thin-3" x1="180" y1="0" x2="180" y2="1080" />
|
||||
<line id="v-thin-5" x1="300" y1="0" x2="300" y2="1080" />
|
||||
<line id="v-thin-6" x1="360" y1="0" x2="360" y2="1080" />
|
||||
<line id="v-thin-7" x1="420" y1="0" x2="420" y2="1080" />
|
||||
<line id="v-thin-9" x1="540" y1="0" x2="540" y2="1080" />
|
||||
<line id="v-thin-10" x1="600" y1="0" x2="600" y2="1080" />
|
||||
<line id="v-thin-11" x1="660" y1="0" x2="660" y2="1080" />
|
||||
<line id="v-thin-13" x1="780" y1="0" x2="780" y2="1080" />
|
||||
<line id="v-thin-14" x1="840" y1="0" x2="840" y2="1080" />
|
||||
<line id="v-thin-15" x1="900" y1="0" x2="900" y2="1080" />
|
||||
<line id="v-thin-17" x1="1020" y1="0" x2="1020" y2="1080" />
|
||||
<line id="v-thin-18" x1="1080" y1="0" x2="1080" y2="1080" />
|
||||
<line id="v-thin-19" x1="1140" y1="0" x2="1140" y2="1080" />
|
||||
<line id="v-thin-21" x1="1260" y1="0" x2="1260" y2="1080" />
|
||||
<line id="v-thin-22" x1="1320" y1="0" x2="1320" y2="1080" />
|
||||
<line id="v-thin-23" x1="1380" y1="0" x2="1380" y2="1080" />
|
||||
<line id="v-thin-25" x1="1500" y1="0" x2="1500" y2="1080" />
|
||||
<line id="v-thin-26" x1="1560" y1="0" x2="1560" y2="1080" />
|
||||
<line id="v-thin-27" x1="1620" y1="0" x2="1620" y2="1080" />
|
||||
<line id="v-thin-29" x1="1740" y1="0" x2="1740" y2="1080" />
|
||||
<line id="v-thin-30" x1="1800" y1="0" x2="1800" y2="1080" />
|
||||
<line id="v-thin-31" x1="1860" y1="0" x2="1860" y2="1080" />
|
||||
<line id="h-thin-1" x1="0" y1="60" x2="1920" y2="60" />
|
||||
<line id="h-thin-2" x1="0" y1="120" x2="1920" y2="120" />
|
||||
<line id="h-thin-3" x1="0" y1="180" x2="1920" y2="180" />
|
||||
<line id="h-thin-5" x1="0" y1="300" x2="1920" y2="300" />
|
||||
<line id="h-thin-6" x1="0" y1="360" x2="1920" y2="360" />
|
||||
<line id="h-thin-7" x1="0" y1="420" x2="1920" y2="420" />
|
||||
<line id="h-thin-9" x1="0" y1="540" x2="1920" y2="540" />
|
||||
<line id="h-thin-10" x1="0" y1="600" x2="1920" y2="600" />
|
||||
<line id="h-thin-11" x1="0" y1="660" x2="1920" y2="660" />
|
||||
<line id="h-thin-13" x1="0" y1="780" x2="1920" y2="780" />
|
||||
<line id="h-thin-14" x1="0" y1="840" x2="1920" y2="840" />
|
||||
<line id="h-thin-15" x1="0" y1="900" x2="1920" y2="900" />
|
||||
<line id="h-thin-17" x1="0" y1="1020" x2="1920" y2="1020" />
|
||||
</g>
|
||||
|
||||
<g id="thick-grid-lines" stroke="#0A1E3D" stroke-width="3" opacity="0.2">
|
||||
<line id="v-thick-1" x1="240" y1="0" x2="240" y2="1080" />
|
||||
<line id="v-thick-2" x1="480" y1="0" x2="480" y2="1080" />
|
||||
<line id="v-thick-3" x1="720" y1="0" x2="720" y2="1080" />
|
||||
<line id="v-thick-4" x1="960" y1="0" x2="960" y2="1080" />
|
||||
<line id="v-thick-5" x1="1200" y1="0" x2="1200" y2="1080" />
|
||||
<line id="v-thick-6" x1="1440" y1="0" x2="1440" y2="1080" />
|
||||
<line id="v-thick-7" x1="1680" y1="0" x2="1680" y2="1080" />
|
||||
<line id="h-thick-1" x1="0" y1="240" x2="1920" y2="240" />
|
||||
<line id="h-thick-2" x1="0" y1="480" x2="1920" y2="480" />
|
||||
<line id="h-thick-3" x1="0" y1="720" x2="1920" y2="720" />
|
||||
<line id="h-thick-4" x1="0" y1="960" x2="1920" y2="960" />
|
||||
</g>
|
||||
|
||||
<g id="intersections" stroke="#0A1E3D" stroke-width="2" opacity="0.3">
|
||||
<line x1="230" y1="240" x2="250" y2="240" />
|
||||
<line x1="240" y1="230" x2="240" y2="250" />
|
||||
<line x1="230" y1="480" x2="250" y2="480" />
|
||||
<line x1="240" y1="470" x2="240" y2="490" />
|
||||
<line x1="230" y1="720" x2="250" y2="720" />
|
||||
<line x1="240" y1="710" x2="240" y2="730" />
|
||||
<line x1="230" y1="960" x2="250" y2="960" />
|
||||
<line x1="240" y1="950" x2="240" y2="970" />
|
||||
<line x1="470" y1="240" x2="490" y2="240" />
|
||||
<line x1="480" y1="230" x2="480" y2="250" />
|
||||
<line x1="470" y1="480" x2="490" y2="480" />
|
||||
<line x1="480" y1="470" x2="480" y2="490" />
|
||||
<line x1="470" y1="720" x2="490" y2="720" />
|
||||
<line x1="480" y1="710" x2="480" y2="730" />
|
||||
<line x1="470" y1="960" x2="490" y2="960" />
|
||||
<line x1="480" y1="950" x2="480" y2="970" />
|
||||
<line x1="710" y1="240" x2="730" y2="240" />
|
||||
<line x1="720" y1="230" x2="720" y2="250" />
|
||||
<line x1="710" y1="480" x2="730" y2="480" />
|
||||
<line x1="720" y1="470" x2="720" y2="490" />
|
||||
<line x1="710" y1="720" x2="730" y2="720" />
|
||||
<line x1="720" y1="710" x2="720" y2="730" />
|
||||
<line x1="710" y1="960" x2="730" y2="960" />
|
||||
<line x1="720" y1="950" x2="720" y2="970" />
|
||||
<line x1="950" y1="240" x2="970" y2="240" />
|
||||
<line x1="960" y1="230" x2="960" y2="250" />
|
||||
<line x1="950" y1="480" x2="970" y2="480" />
|
||||
<line x1="960" y1="470" x2="960" y2="490" />
|
||||
<line x1="950" y1="720" x2="970" y2="720" />
|
||||
<line x1="960" y1="710" x2="960" y2="730" />
|
||||
<line x1="950" y1="960" x2="970" y2="960" />
|
||||
<line x1="960" y1="950" x2="960" y2="970" />
|
||||
<line x1="1190" y1="240" x2="1210" y2="240" />
|
||||
<line x1="1200" y1="230" x2="1200" y2="250" />
|
||||
<line x1="1190" y1="480" x2="1210" y2="480" />
|
||||
<line x1="1200" y1="470" x2="1200" y2="490" />
|
||||
<line x1="1190" y1="720" x2="1210" y2="720" />
|
||||
<line x1="1200" y1="710" x2="1200" y2="730" />
|
||||
<line x1="1190" y1="960" x2="1210" y2="960" />
|
||||
<line x1="1200" y1="950" x2="1200" y2="970" />
|
||||
<line x1="1430" y1="240" x2="1450" y2="240" />
|
||||
<line x1="1440" y1="230" x2="1440" y2="250" />
|
||||
<line x1="1430" y1="480" x2="1450" y2="480" />
|
||||
<line x1="1440" y1="470" x2="1440" y2="490" />
|
||||
<line x1="1430" y1="720" x2="1450" y2="720" />
|
||||
<line x1="1440" y1="710" x2="1440" y2="730" />
|
||||
<line x1="1430" y1="960" x2="1450" y2="960" />
|
||||
<line x1="1440" y1="950" x2="1440" y2="970" />
|
||||
<line x1="1670" y1="240" x2="1690" y2="240" />
|
||||
<line x1="1680" y1="230" x2="1680" y2="250" />
|
||||
<line x1="1670" y1="480" x2="1690" y2="480" />
|
||||
<line x1="1680" y1="470" x2="1680" y2="490" />
|
||||
<line x1="1670" y1="720" x2="1690" y2="720" />
|
||||
<line x1="1680" y1="710" x2="1680" y2="730" />
|
||||
<line x1="1670" y1="960" x2="1690" y2="960" />
|
||||
<line x1="1680" y1="950" x2="1680" y2="970" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,53 @@
|
||||
# HyperFrame Schema Compliance Review
|
||||
|
||||
## Executive Summary
|
||||
- Total files reviewed: 4
|
||||
- Critical issues: 0
|
||||
- Overall compliance status: PASS
|
||||
|
||||
## Critical Issues
|
||||
None. All files now comply with the HyperFrame schema.
|
||||
|
||||
## Compliance Checklist
|
||||
- [x] All compositions have `data-width` and `data-height` attributes
|
||||
- [x] All timelines are finite with duration > 0
|
||||
- [x] All compositions registered in `window.__timelines`
|
||||
- [x] No use of `Math.random()`, `Date.now()`, or non-deterministic code
|
||||
- [x] Primitive clips have required data attributes (`id`, `data-start`, `data-track`)
|
||||
- [x] `data-duration` specified for all `<img>` clips
|
||||
- [x] No manual media playback control (`video.play()`, `audio.pause()`, etc.)
|
||||
- [x] No manual clip mounting/unmounting in scripts
|
||||
- [x] Relative timing references are valid (N/A - absolute used)
|
||||
- [x] Clips on same track don't overlap in time
|
||||
- [x] Reusable compositions in separate HTML files
|
||||
- [x] Composition files use `<template>` tags
|
||||
- [x] External compositions loaded via `data-composition-src`
|
||||
- [x] All script-animated content wrapped in compositions
|
||||
- [x] No infinite or zero-duration timelines
|
||||
|
||||
## File Reviews
|
||||
|
||||
### index.html
|
||||
**Status**: COMPLIANT
|
||||
|
||||
**Issues Found**:
|
||||
- None. Correctly uses `data-composition-id`, `data-width`, `data-height`, and `data-duration`. Registers `master` timeline.
|
||||
|
||||
### compositions/intro.html
|
||||
**Status**: COMPLIANT
|
||||
|
||||
**Issues Found**:
|
||||
- None. Correctly uses `<template>`, registers `intro` timeline, and has required attributes.
|
||||
|
||||
### compositions/captions.html
|
||||
**Status**: HAS_ISSUES
|
||||
|
||||
**Issues Found**:
|
||||
- **Line 95**: Attempting to set `data-duration` via script. This should be a static attribute on the composition root (Line 2).
|
||||
- **Line 2**: `data-duration="30"` is set, but the script calculates a different duration. These should be synchronized manually in the HTML.
|
||||
|
||||
### compositions/graphics.html
|
||||
**Status**: COMPLIANT
|
||||
|
||||
**Issues Found**:
|
||||
- **Line 135**: Redundant GSAP script import inside a composition template. While not a schema violation, it's unnecessary as GSAP is loaded in `index.html`.
|
||||
@@ -0,0 +1,95 @@
|
||||
<template id="captions-template">
|
||||
<div data-composition-id="captions" data-width="1920" data-height="1080" data-duration="16.04">
|
||||
<div id="caption-container"></div>
|
||||
|
||||
<style>
|
||||
[data-composition-id="captions"] {
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
position: relative;
|
||||
font-family: 'Helvetica', 'Arial', sans-serif;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-composition-id="captions"] #caption-container {
|
||||
position: absolute;
|
||||
bottom: 120px; /* Consistent bottom positioning */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
[data-composition-id="captions"] .caption-box {
|
||||
background-color: #0A1E3D; /* Solid navy */
|
||||
padding: 20px 40px;
|
||||
display: none; /* Hidden by default, shown via GSAP */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* Swiss Grid: sharp corners, solid block */
|
||||
}
|
||||
|
||||
[data-composition-id="captions"] .caption-text {
|
||||
color: #F2F2F2; /* Off-white */
|
||||
font-size: 72px;
|
||||
text-transform: uppercase; /* Swiss style often uses uppercase for impact */
|
||||
letter-spacing: -2px;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const TRANSCRIPT = [{'text': 'We', 'start': 0.119, 'end': 0.259}, {'text': 'asked', 'start': 0.319, 'end': 0.479}, {'text': 'what', 'start': 0.519, 'end': 0.659}, {'text': 'you', 'start': 0.699, 'end': 0.819}, {'text': 'needed.', 'start': 0.859, 'end': 1.819}, {'text': 'Forty-seven', 'start': 1.86, 'end': 2.299}, {'text': 'percent', 'start': 2.399, 'end': 2.679}, {'text': 'of', 'start': 2.7, 'end': 2.799}, {'text': 'you', 'start': 2.839, 'end': 2.939}, {'text': 'said', 'start': 3.039, 'end': 3.179}, {'text': 'motion', 'start': 3.24, 'end': 3.559}, {'text': 'graphics,', 'start': 3.579, 'end': 4.599}, {'text': 'sixty-two', 'start': 4.679, 'end': 5.179}, {'text': 'percent', 'start': 5.299, 'end': 5.759}, {'text': 'said', 'start': 5.859, 'end': 5.98}, {'text': 'static', 'start': 6.079, 'end': 6.399}, {'text': 'content', 'start': 6.46, 'end': 6.879}, {'text': 'was', 'start': 6.92, 'end': 7.079}, {'text': 'costing', 'start': 7.099, 'end': 7.48}, {'text': 'you', 'start': 7.5, 'end': 7.579}, {'text': 'attention,', 'start': 7.679, 'end': 8.659}, {'text': 'and', 'start': 8.699, 'end': 8.86}, {'text': 'three', 'start': 8.88, 'end': 9.06}, {'text': 'out', 'start': 9.079, 'end': 9.18}, {'text': 'of', 'start': 9.199, 'end': 9.34}, {'text': 'four', 'start': 9.38, 'end': 9.799}, {'text': 'said', 'start': 9.84, 'end': 10.0}, {'text': 'you', 'start': 10.019, 'end': 10.159}, {'text': 'know', 'start': 10.179, 'end': 10.36}, {'text': 'the', 'start': 10.38, 'end': 10.42}, {'text': 'look', 'start': 10.519, 'end': 10.699}, {'text': 'you', 'start': 10.739, 'end': 10.859}, {'text': 'want', 'start': 10.98, 'end': 11.34}, {'text': 'but', 'start': 11.359, 'end': 11.52}, {'text': "don't", 'start': 11.56, 'end': 11.779}, {'text': 'have', 'start': 11.819, 'end': 11.94}, {'text': 'the', 'start': 11.96, 'end': 12.06}, {'text': 'editing', 'start': 12.079, 'end': 12.4}, {'text': 'skills', 'start': 12.52, 'end': 12.86}, {'text': 'to', 'start': 12.88, 'end': 13.0}, {'text': 'get', 'start': 13.019, 'end': 13.18}, {'text': 'there.', 'start': 13.22, 'end': 14.22}, {'text': 'So', 'start': 14.239, 'end': 14.399}, {'text': 'we', 'start': 14.42, 'end': 14.52}, {'text': 'built', 'start': 14.619, 'end': 14.88}, {'text': 'Editor', 'start': 15.079, 'end': 15.42}, {'text': 'Agent.', 'start': 15.619, 'end': 16.02}];
|
||||
const container = document.getElementById('caption-container');
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
|
||||
if (!TRANSCRIPT || TRANSCRIPT.length === 0) {
|
||||
window.__timelines["captions"] = tl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Group transcript into max 5 words per group
|
||||
const groups = [];
|
||||
let currentGroup = [];
|
||||
|
||||
TRANSCRIPT.forEach((word, index) => {
|
||||
currentGroup.push(word);
|
||||
// Group by 5 words OR if it's the last word
|
||||
if (currentGroup.length === 5 || index === TRANSCRIPT.length - 1) {
|
||||
groups.push([...currentGroup]);
|
||||
currentGroup = [];
|
||||
}
|
||||
});
|
||||
|
||||
// Create DOM elements and timeline for each group
|
||||
groups.forEach((group, i) => {
|
||||
const box = document.createElement('div');
|
||||
box.className = 'caption-box';
|
||||
box.id = `group-${i}`;
|
||||
|
||||
const text = document.createElement('div');
|
||||
text.className = 'caption-text';
|
||||
text.textContent = group.map(w => w.text).join(' ');
|
||||
|
||||
box.appendChild(text);
|
||||
container.appendChild(box);
|
||||
|
||||
const startTime = group[0].start;
|
||||
const endTime = group[group.length - 1].end;
|
||||
|
||||
// Hard cut animation (no fades) as requested
|
||||
tl.set(box, { display: 'flex' }, startTime);
|
||||
tl.set(box, { display: 'none' }, endTime);
|
||||
});
|
||||
|
||||
window.__timelines["captions"] = tl;
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,198 @@
|
||||
<template id="graphics-template">
|
||||
<div data-composition-id="graphics" data-width="1920" data-height="1080" data-duration="15">
|
||||
<div class="grid-container">
|
||||
<!-- Stat 1: 47% -->
|
||||
<div id="stat1" class="stat-group">
|
||||
<div class="stat-value">47%</div>
|
||||
<div class="stat-label">NEED MOTION GRAPHICS</div>
|
||||
</div>
|
||||
|
||||
<!-- Stat 2: 62% -->
|
||||
<div id="stat2" class="stat-group">
|
||||
<div class="stat-value">62%</div>
|
||||
<div class="stat-label">LOSING ATTENTION</div>
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stat 3: 3 OF 4 -->
|
||||
<div id="stat3" class="stat-group">
|
||||
<div class="stat-value">3 OF 4</div>
|
||||
<div class="stat-label">LACK EDITING SKILLS</div>
|
||||
<div class="grid-blocks">
|
||||
<div class="block gold"></div>
|
||||
<div class="block gold"></div>
|
||||
<div class="block gold"></div>
|
||||
<div class="block navy"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
[data-composition-id="graphics"] {
|
||||
font-family: 'Helvetica', Arial, sans-serif;
|
||||
color: #0A1E3D;
|
||||
background: transparent;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-template-rows: repeat(12, 1fr);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 80px;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .stat-group {
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
background: #F2F2F2;
|
||||
padding: 40px;
|
||||
border-left: 10px solid #D4A017;
|
||||
box-shadow: 20px 20px 0px rgba(10, 30, 61, 0.1);
|
||||
}
|
||||
|
||||
/* Positioning Stats on Grid - Adjusted for A-roll structure */
|
||||
[data-composition-id="graphics"] #stat1 {
|
||||
grid-column: 2 / 6;
|
||||
grid-row: 3 / 7;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] #stat2 {
|
||||
grid-column: 2 / 6;
|
||||
grid-row: 3 / 7;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] #stat3 {
|
||||
grid-column: 7 / 12;
|
||||
grid-row: 3 / 7;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .stat-value {
|
||||
font-size: 140px;
|
||||
font-weight: 900;
|
||||
color: #D4A017;
|
||||
line-height: 0.8;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .stat-label {
|
||||
font-size: 24px;
|
||||
font-weight: 300; /* Lighter weight */
|
||||
color: #0A1E3D;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Progress Bar for Stat 2 */
|
||||
[data-composition-id="graphics"] .progress-container {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
background: #E0E0E0;
|
||||
margin-top: 30px;
|
||||
border: 2px solid #0A1E3D;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .progress-bar {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background: #D4A017;
|
||||
}
|
||||
|
||||
/* Grid Blocks for Stat 3 */
|
||||
[data-composition-id="graphics"] .grid-blocks {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .block {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border: 3px solid #0A1E3D;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .block.gold {
|
||||
background: #D4A017;
|
||||
}
|
||||
|
||||
[data-composition-id="graphics"] .block.navy {
|
||||
background: #0A1E3D;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
|
||||
// Timing Constants
|
||||
const S1_START = 1.86;
|
||||
const S1_END = 4.5;
|
||||
const S2_START = 4.68;
|
||||
const S2_END = 8.6;
|
||||
const S3_START = 8.88;
|
||||
const S3_END = 14.2;
|
||||
|
||||
const SLIDE_DUR = 0.25; // 250ms
|
||||
const SHARP_EASE = "power2.out";
|
||||
|
||||
// Stat 1 Animation
|
||||
tl.fromTo('#stat1',
|
||||
{ x: -200, opacity: 0 },
|
||||
{ x: 0, opacity: 1, duration: SLIDE_DUR, ease: SHARP_EASE },
|
||||
S1_START
|
||||
);
|
||||
tl.to('#stat1',
|
||||
{ x: 200, opacity: 0, duration: SLIDE_DUR, ease: "power2.in" },
|
||||
S1_END - SLIDE_DUR
|
||||
);
|
||||
|
||||
// Stat 2 Animation
|
||||
tl.fromTo('#stat2',
|
||||
{ y: 200, opacity: 0 },
|
||||
{ y: 0, opacity: 1, duration: SLIDE_DUR, ease: SHARP_EASE },
|
||||
S2_START
|
||||
);
|
||||
// Progress bar fill
|
||||
tl.to('#stat2 .progress-bar',
|
||||
{ width: '62%', duration: S2_END - S2_START - (SLIDE_DUR * 2), ease: "none" },
|
||||
S2_START + SLIDE_DUR
|
||||
);
|
||||
tl.to('#stat2',
|
||||
{ y: -200, opacity: 0, duration: SLIDE_DUR, ease: "power2.in" },
|
||||
S2_END - SLIDE_DUR
|
||||
);
|
||||
|
||||
// Stat 3 Animation
|
||||
tl.fromTo('#stat3',
|
||||
{ x: 200, opacity: 0 },
|
||||
{ x: 0, opacity: 1, duration: SLIDE_DUR, ease: SHARP_EASE },
|
||||
S3_START
|
||||
);
|
||||
// Stagger blocks
|
||||
tl.from('#stat3 .block',
|
||||
{ scale: 0, duration: 0.3, stagger: 0.1, ease: "back.out(1.7)" },
|
||||
S3_START + SLIDE_DUR
|
||||
);
|
||||
tl.to('#stat3',
|
||||
{ x: -200, opacity: 0, duration: SLIDE_DUR, ease: "power2.in" },
|
||||
S3_END - SLIDE_DUR
|
||||
);
|
||||
|
||||
window.__timelines["graphics"] = tl;
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
<template id="intro-template">
|
||||
<div data-composition-id="intro" data-width="1920" data-height="1080" data-duration="1.86">
|
||||
<div class="container">
|
||||
<div class="grid-line"></div>
|
||||
<div class="text-wrapper">
|
||||
<h1 class="title">EDITOR AGENT</h1>
|
||||
<h2 class="subtitle">THE SURVEY FINDINGS</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
[data-composition-id="intro"] {
|
||||
background-color: #F5F5F5; /* Off-white */
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-composition-id="intro"] .container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-left: 160px; /* Swiss grid alignment */
|
||||
}
|
||||
|
||||
[data-composition-id="intro"] .grid-line {
|
||||
position: absolute;
|
||||
left: 160px;
|
||||
top: 50%;
|
||||
width: 0px;
|
||||
height: 12px;
|
||||
background-color: #0A1E3D; /* Navy */
|
||||
transform: translateY(-180px); /* Positioned above the text */
|
||||
}
|
||||
|
||||
[data-composition-id="intro"] .text-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-composition-id="intro"] .title {
|
||||
color: #0A1E3D;
|
||||
font-size: 180px;
|
||||
font-weight: 900; /* Black weight */
|
||||
line-height: 0.9;
|
||||
margin: 0;
|
||||
letter-spacing: -0.04em;
|
||||
text-transform: uppercase;
|
||||
transform: translateX(-100%); /* Start off-screen left */
|
||||
}
|
||||
|
||||
[data-composition-id="intro"] .subtitle {
|
||||
color: #0A1E3D;
|
||||
font-size: 64px;
|
||||
font-weight: 300; /* Lighter weight for contrast */
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
transform: translateX(-100%); /* Start off-screen left */
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
|
||||
// Mechanical timing: 200ms (0.2s)
|
||||
const MECHANICAL_DURATION = 0.2;
|
||||
const STAGGER = 0.1;
|
||||
|
||||
// 1. Animate the grid line first
|
||||
tl.to('.grid-line', {
|
||||
width: '1200px',
|
||||
duration: 0.4,
|
||||
ease: 'power4.out'
|
||||
}, 0.2);
|
||||
|
||||
// 2. Slide in the title
|
||||
tl.to('.title', {
|
||||
x: 0,
|
||||
duration: MECHANICAL_DURATION,
|
||||
ease: 'power2.inOut'
|
||||
}, 0.5);
|
||||
|
||||
// 3. Slide in the subtitle with a slight stagger
|
||||
tl.to('.subtitle', {
|
||||
x: 0,
|
||||
duration: MECHANICAL_DURATION,
|
||||
ease: 'power2.inOut'
|
||||
}, 0.5 + STAGGER);
|
||||
|
||||
// 4. Subtle ambient motion (slow drift) to keep it alive
|
||||
tl.to('.text-wrapper', {
|
||||
x: 30,
|
||||
duration: 1.16, // Adjusted to fit 1.86s total
|
||||
ease: 'none'
|
||||
}, 0.7);
|
||||
|
||||
window.__timelines["intro"] = tl;
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,57 @@
|
||||
# HyperFrames Design Review
|
||||
|
||||
## First Impression
|
||||
This looks like a "Swiss Style" template that someone found in a dumpster and tried to glue back together. It’s a clinical, soulless mess that mistakes "minimalism" for "I didn't have time to finish the design."
|
||||
|
||||
---
|
||||
|
||||
## CRITICAL Design Failures
|
||||
|
||||
### The "Swiss Grid" is a Lie
|
||||
**Where:** `assets/swiss-grid.svg` and `index.html`
|
||||
**What's wrong:** You’ve included a grid background that looks like a blueprint for a parking lot. It’s distracting, cluttered, and serves no purpose other than to scream "I'm trying to be edgy." The intersections and thick lines create a visual vibration that makes the actual content hard to focus on.
|
||||
**Why it matters:** A grid should be a guide for the designer, not a cage for the viewer. It’s visually exhausting and makes the entire composition feel like a technical drawing rather than a professional video.
|
||||
**Fix it:** Lower the opacity of the grid to 0.05 or remove it entirely. Use the grid to align elements, don't make the viewer look at it.
|
||||
|
||||
### Typography Hierarchy is Non-Existent
|
||||
**Where:** `compositions/intro.html` and `compositions/graphics.html`
|
||||
**What's wrong:** You’re using Helvetica (the default choice of the uninspired) and just cranking the font size up to 180px. The "EDITOR AGENT" title is so massive it’s practically shouting in the viewer's face, while the subtitle is just... there. There’s no elegance, no play with weight, just "BIG TEXT" and "SMALLER TEXT."
|
||||
**Why it matters:** Without a clear typographic hierarchy, the viewer doesn't know where to look first. It feels amateur and "default."
|
||||
**Fix it:** Experiment with tighter letter spacing (kerning) and more dramatic weight contrasts. Try a heavier weight for the title and a much lighter, tracked-out weight for the subtitle.
|
||||
|
||||
### The "Gold" is Actually Mustard
|
||||
**Where:** `compositions/graphics.html` (`#D4A017`)
|
||||
**What's wrong:** You’ve paired a sophisticated Navy (`#0A1E3D`) with a "gold" that looks like expired Dijon mustard. It’s flat, muddy, and lacks any premium feel.
|
||||
**Why it matters:** Color choice dictates the "vibe." This color palette feels like a budget airline from the 90s, not a cutting-edge "Editor Agent."
|
||||
**Fix it:** Use a more vibrant, metallic-leaning gold or a sharp, high-contrast accent color like a neon cyan or a deep crimson to actually give this some life.
|
||||
|
||||
---
|
||||
|
||||
## Design Improvements
|
||||
|
||||
### Robotic Motion
|
||||
**Where:** `compositions/graphics.html` and `index.html`
|
||||
**The problem:** The animations are "mechanical" in the worst way. `power2.out` is the "I just started using GSAP" of easing functions. The A-roll video jumps around the screen like a glitchy security camera.
|
||||
**Make it better:** Use more sophisticated easing like `expo.out` or `customEase`. Add some secondary motion—maybe the text doesn't just slide, it scales slightly or has a subtle blur on entry. Make the transitions feel like they have weight and momentum.
|
||||
|
||||
### Caption Box Laziness
|
||||
**Where:** `compositions/captions.html`
|
||||
**The problem:** A solid navy box with white text. It’s the most basic implementation possible. It covers up the A-roll and looks like a closed-captioning fail.
|
||||
**Make it better:** Lose the solid box. Use a subtle text shadow or a semi-transparent blurred background (glassmorphism) to keep the text readable without blocking the frame. Or, lean into the Swiss style and use a high-contrast, offset background block that actually feels intentional.
|
||||
|
||||
---
|
||||
|
||||
## What Actually Works
|
||||
|
||||
The **layout logic** in `index.html` where the A-roll moves to accommodate the graphics is actually a smart move. It shows you’re thinking about the composition as a whole, even if the execution is currently hideous. The use of a 12x12 grid for positioning is a solid foundation—you just need to stop showing your work.
|
||||
|
||||
---
|
||||
|
||||
## Design Verdict
|
||||
|
||||
**Visual Impact:** 3/10 - It’s as exciting as a spreadsheet.
|
||||
**Color & Typography:** 2/10 - Helvetica and mustard. Groundbreaking.
|
||||
**Motion & Animation Feel:** 4/10 - Functional, but lacks any soul or "flow."
|
||||
**Overall Aesthetic:** 3/10 - A "Swiss Style" attempt that fell off the mountain.
|
||||
|
||||
**Bottom Line:** This looks like a prototype for a corporate training video that everyone will mute and minimize. It needs a massive injection of personality, better color theory, and motion that doesn't feel like it was programmed by a calculator. Fix the grid, fix the colors, and for the love of design, find a better font.
|
||||
@@ -0,0 +1,172 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Swiss Grid - Editor Agent</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background-color: #F2F2F2;
|
||||
overflow: hidden;
|
||||
font-family: 'Helvetica', Arial, sans-serif;
|
||||
}
|
||||
|
||||
#master-root {
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.background-grid {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* A-roll styling */
|
||||
#short_mag_cut_frame {
|
||||
position: absolute;
|
||||
border-radius: 8px; /* Required */
|
||||
z-index: 1;
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
#short_mag_cut,
|
||||
#short_mag_cut_frame > img.__render_frame__,
|
||||
#short_mag_cut_frame > img.__preview_render_frame__ {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Overlay layers */
|
||||
.overlay-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#intro-comp { z-index: 2; }
|
||||
#graphics-comp { z-index: 3; }
|
||||
#captions-comp { z-index: 4; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="master-root" data-composition-id="master" data-width="1920" data-height="1080" data-duration="16.04">
|
||||
|
||||
<!-- Background Grid -->
|
||||
<img id="bg-grid"
|
||||
class="background-grid"
|
||||
src="assets/swiss-grid.svg"
|
||||
alt="Grid"
|
||||
data-start="0"
|
||||
data-duration="16.04"
|
||||
data-track-index="0">
|
||||
|
||||
<!-- A-roll Video -->
|
||||
<div id="short_mag_cut_frame">
|
||||
<video id="short_mag_cut"
|
||||
src="https://gen-os-static.s3.us-east-2.amazonaws.com/astral_assets/uploaded_assets/8eb26801_b5ca4d50bb91437dac375c58b86d005c.mp4"
|
||||
data-start="0"
|
||||
data-duration="16.04"
|
||||
data-track-index="1">
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<!-- Intro Sub-composition -->
|
||||
<div id="intro-comp"
|
||||
class="overlay-layer"
|
||||
data-composition-id="intro"
|
||||
data-composition-src="compositions/intro.html"
|
||||
data-start="0"
|
||||
data-duration="1.86"
|
||||
data-track-index="2">
|
||||
</div>
|
||||
|
||||
<!-- Graphics Sub-composition -->
|
||||
<div id="graphics-comp"
|
||||
class="overlay-layer"
|
||||
data-composition-id="graphics"
|
||||
data-composition-src="compositions/graphics.html"
|
||||
data-start="0"
|
||||
data-duration="16.04"
|
||||
data-track-index="3">
|
||||
</div>
|
||||
|
||||
<!-- Captions Sub-composition -->
|
||||
<div id="captions-comp"
|
||||
class="overlay-layer"
|
||||
data-composition-id="captions"
|
||||
data-composition-src="compositions/captions.html"
|
||||
data-start="0"
|
||||
data-duration="16.04"
|
||||
data-track-index="4">
|
||||
</div>
|
||||
|
||||
<!-- Sound Effects -->
|
||||
<audio id="sfx-intro" data-start="0" data-track-index="5" data-duration="1" src="https://gen-os-static.s3.us-east-2.amazonaws.com/astral_assets/generated_assets/051b5d38_af2426f283a749de94ab615d459a565d.mp3"></audio>
|
||||
<audio id="sfx-stat1" data-start="1.86" data-track-index="5" data-duration="1" src="https://gen-os-static.s3.us-east-2.amazonaws.com/astral_assets/generated_assets/bd3cb328_5d3f0ddf41c14bb8bfad8ae242024334.mp3"></audio>
|
||||
<audio id="sfx-stat2" data-start="4.68" data-track-index="5" data-duration="1" src="https://gen-os-static.s3.us-east-2.amazonaws.com/astral_assets/generated_assets/61ada7ed_142d9432f783410185afebd0d00f1b7a.mp3"></audio>
|
||||
<audio id="sfx-stat3" data-start="8.88" data-track-index="5" data-duration="1" src="https://gen-os-static.s3.us-east-2.amazonaws.com/astral_assets/generated_assets/bd3cb328_5d3f0ddf41c14bb8bfad8ae242024334.mp3"></audio>
|
||||
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
|
||||
const masterTL = gsap.timeline({ paused: true });
|
||||
const v = document.getElementById('short_mag_cut_frame');
|
||||
|
||||
// --- A-ROLL MOVEMENT (Structured Swiss Layout) ---
|
||||
|
||||
// 1. Entrance (0-1.86s): Slide in from left, settle centered for Intro
|
||||
masterTL.fromTo(v,
|
||||
{ x: -1000, y: 120, width: 960, height: 840 },
|
||||
{ x: 480, y: 120, width: 960, height: 840, duration: 0.8, ease: "power2.out" },
|
||||
0
|
||||
);
|
||||
|
||||
// 2. Stat 1 (1.86s - 4.68s): Move to right side (Graphic is on left)
|
||||
masterTL.to(v, {
|
||||
x: 1080, y: 120, width: 720, height: 720,
|
||||
duration: 0.25, ease: "expo.out"
|
||||
}, 1.86);
|
||||
|
||||
// 3. Stat 2 (4.68s - 8.88s): Stay right, zoom in slightly
|
||||
masterTL.to(v, {
|
||||
x: 1080, y: 60, width: 780, height: 780,
|
||||
duration: 0.25, ease: "expo.out"
|
||||
}, 4.68);
|
||||
|
||||
// 4. Stat 3 (8.88s - 14.2s): Move to left side (Graphic is on right)
|
||||
masterTL.to(v, {
|
||||
x: 120, y: 120, width: 720, height: 720,
|
||||
duration: 0.25, ease: "expo.out"
|
||||
}, 8.88);
|
||||
|
||||
// 5. Conclusion (14.2s - 16.04s): Center large
|
||||
masterTL.to(v, {
|
||||
x: 240, y: 60, width: 1440, height: 810,
|
||||
duration: 0.5, ease: "expo.out"
|
||||
}, 14.2);
|
||||
|
||||
window.__timelines["master"] = masterTL;
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user