LapinLogic commited on
Commit
bf4e8d0
·
verified ·
1 Parent(s): 8f2fed5

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +30 -5
  2. app.js +37 -0
  3. index.html +73 -17
  4. style.css +15 -28
README.md CHANGED
@@ -1,10 +1,35 @@
1
  ---
2
- title: 10eros Workflow Studio
3
- emoji: 📚
4
- colorFrom: red
5
- colorTo: green
6
  sdk: static
 
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: 10Eros Workflow Studio
3
+ emoji: 🎞️
4
+ colorFrom: purple
5
+ colorTo: pink
6
  sdk: static
7
+ app_file: index.html
8
+ short_description: Compose image-to-video prompts for 10Eros
9
  pinned: false
10
  ---
11
 
12
+ # 10Eros Workflow Studio
13
+
14
+ A browser-based companion demo for [TenStrip/LTX2.3-10Eros](https://huggingface.co/TenStrip/LTX2.3-10Eros), an LTX 2.3 image-to-video checkpoint.
15
+
16
+ Use it to preview an input image, compose a precise motion prompt, and export a compact prompt pack for a compatible ComfyUI workflow. The model itself is not hosted in this Space: the original weights are extremely large and require paid GPU hardware for practical inference.
17
+
18
+ ## How to use
19
+
20
+ 1. Add a starting image (it stays in your browser).
21
+ 2. Describe the opening frame, then direct the motion, camera movement, and sound.
22
+ 3. Copy the assembled prompt or download a JSON prompt pack.
23
+ 4. Use it with a compatible LTX 2.3 / 10Eros ComfyUI workflow.
24
+
25
+ ## Notes
26
+
27
+ - This model is tagged `not-for-all-audiences`; use it responsibly and in accordance with Hugging Face policies and applicable law.
28
+ - The prompt presets in this demo are non-explicit.
29
+ - No images or prompts are uploaded by this static app.
30
+
31
+ ## Links
32
+
33
+ - [Original model](https://huggingface.co/TenStrip/LTX2.3-10Eros)
34
+ - [Official workflows](https://huggingface.co/TenStrip/LTX2.3-10Eros_Workflows)
35
+ - [10S Comfy nodes](https://github.com/TenStrip/10S-Comfy-nodes)
app.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fields = ["scene", "motion", "camera", "duration", "sound"].map((id) => document.getElementById(id));
2
+ const output = document.getElementById("prompt-output");
3
+ const status = document.getElementById("copy-status");
4
+ const imageInput = document.getElementById("image-input");
5
+ const preview = document.getElementById("image-preview");
6
+ const dropCopy = document.getElementById("drop-copy");
7
+ const clearImage = document.getElementById("clear-image");
8
+
9
+ function values() { return { scene: fields[0].value.trim(), motion: fields[1].value.trim(), camera: fields[2].value, duration: fields[3].value, sound: fields[4].value.trim() }; }
10
+ function buildPrompt() {
11
+ const v = values();
12
+ if (!v.scene && !v.motion && !v.sound) return "Start describing your scene to build a prompt.";
13
+ const parts = [];
14
+ if (v.scene) parts.push(`Opening frame: ${v.scene}`);
15
+ if (v.motion) parts.push(`Action sequence: ${v.motion}`);
16
+ parts.push(`Camera: ${v.camera.toLowerCase()} over approximately ${v.duration}.`);
17
+ if (v.sound) parts.push(`Audio: ${v.sound}`);
18
+ parts.push("Natural motion, stable composition, coherent anatomy, cinematic detail. No timestamps. Plain English scene direction.");
19
+ return parts.join("\n\n");
20
+ }
21
+ function refresh() { output.textContent = buildPrompt(); status.textContent = ""; }
22
+ fields.forEach((field) => field.addEventListener("input", refresh));
23
+ fields.slice(2).forEach((field) => field.addEventListener("change", refresh));
24
+
25
+ document.querySelectorAll("[data-preset]").forEach((button) => button.addEventListener("click", () => {
26
+ const presets = {
27
+ cinematic: ["A close portrait of a traveler in a red coat on a misty coastal path at dawn.", "They turn toward the ocean, take two slow steps forward, and the coat moves naturally in the sea breeze.", "Soft surf and distant gulls."],
28
+ nature: ["A bright orange monarch butterfly rests on a purple flower in a sunlit meadow.", "The butterfly opens and closes its wings, then lifts off as surrounding wildflowers sway in a light breeze.", "Gentle wind through grass and faint birdsong."],
29
+ product: ["A handcrafted ceramic cup sits on a pale stone table in warm window light.", "The camera makes a slow orbit as a hand gently rotates the cup, revealing its glaze and texture.", "Quiet room tone and a soft ceramic touch."],
30
+ };
31
+ const p = presets[button.dataset.preset];
32
+ fields[0].value = p[0]; fields[1].value = p[1]; fields[4].value = p[2]; refresh();
33
+ }));
34
+ imageInput.addEventListener("change", () => { const file = imageInput.files[0]; if (!file) return; preview.src = URL.createObjectURL(file); preview.hidden = false; dropCopy.hidden = true; clearImage.hidden = false; });
35
+ clearImage.addEventListener("click", () => { imageInput.value = ""; preview.removeAttribute("src"); preview.hidden = true; dropCopy.hidden = false; clearImage.hidden = true; });
36
+ document.getElementById("copy-prompt").addEventListener("click", async () => { try { await navigator.clipboard.writeText(buildPrompt()); status.textContent = "Prompt copied."; } catch { status.textContent = "Copy unavailable — select the text above."; } });
37
+ document.getElementById("download-pack").addEventListener("click", () => { const pack = { model: "TenStrip/LTX2.3-10Eros", generated_at: new Date().toISOString(), input_image_selected: Boolean(imageInput.files[0]), settings: values(), prompt: buildPrompt() }; const link = document.createElement("a"); link.href = URL.createObjectURL(new Blob([JSON.stringify(pack, null, 2)], { type: "application/json" })); link.download = "10eros-prompt-pack.json"; link.click(); URL.revokeObjectURL(link.href); status.textContent = "Prompt pack downloaded."; });
index.html CHANGED
@@ -1,19 +1,75 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="description" content="A prompt and workflow companion for TenStrip's 10Eros image-to-video model." />
7
+ <title>10Eros Workflow Studio</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&display=swap" rel="stylesheet" />
11
+ <link rel="stylesheet" href="style.css" />
12
+ </head>
13
+ <body>
14
+ <main>
15
+ <header class="hero">
16
+ <p class="eyebrow">LTX 2.3 · IMAGE TO VIDEO</p>
17
+ <h1>10Eros <span>Workflow Studio</span></h1>
18
+ <p class="lede">Turn a reference image and a clear direction into a compact, ready-to-use video prompt.</p>
19
+ <div class="badges"><span>Browser-only</span><span>Private by design</span><span>ComfyUI-ready</span></div>
20
+ </header>
21
+
22
+ <section class="notice" aria-label="About this demo">
23
+ <strong>Workflow companion, not hosted inference.</strong> 10Eros is a large checkpoint; running it needs compatible GPU hardware. This free Space helps you prepare a high-quality input locally.
24
+ </section>
25
+
26
+ <section class="studio" aria-label="Prompt studio">
27
+ <div class="panel reference-panel">
28
+ <div class="panel-heading"><span class="step">01</span><h2>Reference frame</h2></div>
29
+ <label class="dropzone" for="image-input" id="dropzone">
30
+ <input id="image-input" type="file" accept="image/*" />
31
+ <img id="image-preview" alt="Your selected reference frame" hidden />
32
+ <div id="drop-copy"><span class="upload-mark">↑</span><strong>Add an opening frame</strong><small>PNG, JPG, WEBP · stays on your device</small></div>
33
+ </label>
34
+ <button class="text-button" id="clear-image" type="button" hidden>Remove image</button>
35
+ <p class="hint">Describe what changes from this frame instead of repeating every visible detail.</p>
36
+ </div>
37
+
38
+ <div class="panel compose-panel">
39
+ <div class="panel-heading"><span class="step">02</span><h2>Direct the scene</h2></div>
40
+ <div class="presets" aria-label="Prompt starters">
41
+ <button type="button" data-preset="cinematic">Cinematic portrait</button>
42
+ <button type="button" data-preset="nature">Nature study</button>
43
+ <button type="button" data-preset="product">Product reveal</button>
44
+ </div>
45
+ <label for="scene">Opening scene <span>what is already in frame?</span></label>
46
+ <textarea id="scene" rows="3" placeholder="A traveler in a red coat stands on a misty coastal path at dawn."></textarea>
47
+ <label for="motion">Motion direction <span>be concrete and chronological</span></label>
48
+ <textarea id="motion" rows="4" placeholder="The traveler turns toward the ocean; the coat moves in the wind as they take two measured steps forward."></textarea>
49
+ <div class="two-up">
50
+ <div><label for="camera">Camera</label><select id="camera"><option>Locked frame</option><option selected>Slow push-in</option><option>Gentle orbit</option><option>Handheld follow</option><option>Slow pull-back</option></select></div>
51
+ <div><label for="duration">Suggested length</label><select id="duration"><option>4 seconds</option><option selected>6 seconds</option><option>8 seconds</option><option>10 seconds</option></select></div>
52
+ </div>
53
+ <label for="sound">Sound / dialogue <span>optional</span></label>
54
+ <input id="sound" type="text" placeholder="Soft surf, gulls, and fabric moving in the wind." />
55
+ </div>
56
+
57
+ <div class="panel output-panel">
58
+ <div class="panel-heading"><span class="step">03</span><h2>Prompt pack</h2></div>
59
+ <p class="hint">This is assembled as you write. Detailed, directive prompts work best with 10Eros.</p>
60
+ <pre id="prompt-output" aria-live="polite">Start describing your scene to build a prompt.</pre>
61
+ <div class="actions"><button id="copy-prompt" type="button">Copy prompt</button><button id="download-pack" class="secondary" type="button">Download JSON</button></div>
62
+ <p id="copy-status" class="status" aria-live="polite"></p>
63
+ <div class="workflow-link"><span>Next step</span><a href="https://huggingface.co/TenStrip/LTX2.3-10Eros_Workflows" target="_blank" rel="noreferrer">Open official workflows ↗</a></div>
64
+ </div>
65
+ </section>
66
+
67
+ <section class="guide">
68
+ <p class="eyebrow">PROMPTING NOTES</p>
69
+ <div class="guide-grid"><article><h3>State the starting point</h3><p>Anchor the first frame with subject, composition, lighting, and setting.</p></article><article><h3>Sequence the movement</h3><p>Use a natural order: action, visible reaction, then any composition change.</p></article><article><h3>Keep audio purposeful</h3><p>Give short dialogue and a few audible cues only when they support the scene.</p></article></div>
70
+ </section>
71
+ </main>
72
+ <footer><span>Built for <a href="https://huggingface.co/TenStrip/LTX2.3-10Eros" target="_blank" rel="noreferrer">TenStrip/LTX2.3-10Eros</a></span><span>Use responsibly · Images never leave your browser</span></footer>
73
+ <script src="app.js"></script>
74
+ </body>
75
  </html>
style.css CHANGED
@@ -1,28 +1,15 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
- }
5
-
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
- }
10
-
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
- }
17
-
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }
 
1
+ :root { --ink:#201927; --muted:#786d7e; --paper:#fffafc; --purple:#5726a2; --pink:#ee488d; --line:#e8dce7; --lavender:#f3edff; }
2
+ * { box-sizing:border-box; }
3
+ body { margin:0; color:var(--ink); background:radial-gradient(circle at 7% 0%, #f4e8ff 0, transparent 27rem), var(--paper); font-family:"DM Sans",Arial,sans-serif; }
4
+ main, footer { max-width:1240px; margin:auto; padding-left:24px; padding-right:24px; }
5
+ .hero { padding:72px 0 35px; max-width:780px; }.eyebrow { color:var(--purple); font:500 .73rem "DM Mono",monospace; letter-spacing:.15em; margin:0 0 14px; }
6
+ h1 { font-size:clamp(2.6rem,6vw,5.6rem); line-height:.93; letter-spacing:-.065em; margin:0; } h1 span { color:var(--pink); display:block; }
7
+ .lede { color:var(--muted); font-size:1.15rem; line-height:1.55; max-width:580px; margin:24px 0; }.badges { display:flex; gap:8px; flex-wrap:wrap; }.badges span { border:1px solid #d9c8e8; border-radius:999px; color:#624a78; font-size:.78rem; padding:6px 11px; }
8
+ .notice { background:#27133f; color:#fff8ff; border-radius:14px; padding:15px 18px; font-size:.92rem; line-height:1.45; margin:0 0 22px; }.notice strong { color:#ffb8d8; }
9
+ .studio { display:grid; grid-template-columns:1fr 1.35fr 1.1fr; gap:16px; align-items:start; }.panel { background:#fff; border:1px solid var(--line); border-radius:16px; padding:22px; box-shadow:0 8px 22px rgba(65,31,80,.035); }.panel-heading { display:flex; gap:10px; align-items:center; margin-bottom:18px; }.panel-heading h2 { font-size:1.03rem; margin:0; }.step { color:var(--pink); font:500 .75rem "DM Mono",monospace; }
10
+ .dropzone { min-height:250px; border:1.5px dashed #c4a4d9; border-radius:11px; display:grid; place-items:center; position:relative; overflow:hidden; cursor:pointer; background:linear-gradient(135deg,#fbf7ff,#fff8fb); text-align:center; padding:16px; }.dropzone input { position:absolute; inset:0; opacity:0; cursor:pointer; }.dropzone img { width:100%; height:100%; position:absolute; inset:0; object-fit:cover; }.dropzone strong, .dropzone small { display:block; }.dropzone small,.hint,label span { color:var(--muted); font-size:.76rem; }.upload-mark { color:var(--purple); display:block; font-size:1.9rem; line-height:1; margin-bottom:8px; }.text-button { border:0; background:none; color:var(--purple); padding:12px 0 0; cursor:pointer; }.hint { color:var(--muted); font-size:.8rem; line-height:1.5; }
11
+ label { display:block; color:#433747; font-size:.83rem; font-weight:600; margin:16px 0 7px; } textarea,input,select { width:100%; color:var(--ink); border:1px solid #dcd0de; background:#fffdfd; border-radius:8px; padding:10px; font:400 .88rem "DM Sans",sans-serif; outline:none; } textarea { resize:vertical; line-height:1.45; } textarea:focus,input:focus,select:focus { border-color:var(--purple); box-shadow:0 0 0 3px #eee4fb; }.two-up { display:grid; grid-template-columns:1fr 1fr; gap:10px; }.two-up label { margin-top:16px; }.presets { display:flex; flex-wrap:wrap; gap:6px; }.presets button,.secondary { background:var(--lavender); color:var(--purple); border:1px solid #d9c8f3; }.presets button { border-radius:999px; padding:6px 9px; font-size:.72rem; cursor:pointer; }
12
+ pre { white-space:pre-wrap; word-break:break-word; min-height:310px; margin:0; padding:15px; background:#201827; color:#f8eefe; border-radius:10px; font:400 .79rem/1.6 "DM Mono",monospace; }.actions { display:flex; gap:8px; margin-top:12px; }.actions button { flex:1; border-radius:8px; padding:10px; font:600 .8rem "DM Sans",sans-serif; cursor:pointer; } #copy-prompt { border:1px solid var(--purple); color:white; background:var(--purple); }.status { color:var(--purple); min-height:1em; font-size:.78rem; }.workflow-link { border-top:1px solid var(--line); padding-top:14px; font-size:.8rem; display:flex; flex-direction:column; gap:4px; }.workflow-link span { color:var(--muted); }.workflow-link a,footer a { color:var(--purple); font-weight:600; }
13
+ .guide { padding:72px 0; }.guide-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:25px; }.guide h3 { margin:0 0 8px; font-size:1rem; }.guide article p { color:var(--muted); font-size:.9rem; line-height:1.5; margin:0; } footer { border-top:1px solid var(--line); padding-top:22px; padding-bottom:32px; color:var(--muted); display:flex; justify-content:space-between; gap:15px; font-size:.76rem; }
14
+ @media (max-width:900px) { .studio { grid-template-columns:1fr 1fr; }.output-panel { grid-column:span 2; } pre { min-height:200px; } }
15
+ @media (max-width:620px) { .hero { padding-top:48px; }.studio,.guide-grid { grid-template-columns:1fr; }.output-panel { grid-column:auto; }.two-up { grid-template-columns:1fr; gap:0; } footer { flex-direction:column; } }