@dnyantra/dtly 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -4
- package/dist/agents.d.ts +7 -0
- package/dist/agents.js +62 -0
- package/dist/agents.js.map +1 -0
- package/dist/cli.js +24 -7
- package/dist/cli.js.map +1 -1
- package/dist/mcp/server.js +31 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/ops/ops.d.ts +1 -0
- package/dist/ops/ops.js +13 -0
- package/dist/ops/ops.js.map +1 -1
- package/dist/studio/server.d.ts +12 -0
- package/dist/studio/server.js +190 -0
- package/dist/studio/server.js.map +1 -0
- package/dist/studio-app/app.css +2 -0
- package/dist/studio-app/app.css.map +7 -0
- package/dist/studio-app/app.js +5 -0
- package/dist/studio-app/app.js.map +7 -0
- package/dist/studio-app/index.html +15 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -4
- package/plugin/skills/dtly/SKILL.md +164 -75
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
<title>DT.ly Studio</title>
|
|
7
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 32 32%22%3E%3Crect width=%2232%22 height=%2232%22 rx=%227%22 fill=%22%23e8692a%22/%3E%3Cpath d=%22M11 9l13 7-13 7z%22 fill=%22white%22/%3E%3C/svg%3E" />
|
|
8
|
+
<link rel="stylesheet" href="/app/app.css" />
|
|
9
|
+
<script>window.DTLY = __DTLY_CONFIG__;</script>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="root"></div>
|
|
13
|
+
<script type="module" src="/app/app.js"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.2.1";
|
|
2
2
|
export declare const BRAND = "DT.ly \u2014 from the creator of CustomerPro.in";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnyantra/dtly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "DT.ly — After Effects-style motion graphics as JSON, rendered to MP4, with an MCP server for AI agents. From the creator of CustomerPro.in.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"motion-graphics",
|
|
@@ -58,13 +58,14 @@
|
|
|
58
58
|
"node": ">=20"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
61
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/cli.js && node scripts/build-studio.mjs",
|
|
62
62
|
"prepare": "npm run build",
|
|
63
|
-
"typecheck": "tsc -p .",
|
|
63
|
+
"typecheck": "tsc -p . && tsc -p tsconfig.app.json",
|
|
64
64
|
"dev": "tsx src/cli.ts",
|
|
65
65
|
"mcp": "tsx src/cli.ts mcp",
|
|
66
66
|
"test": "npm run typecheck && tsx test/smoke.ts",
|
|
67
|
-
"prepublishOnly": "npm test && npm run build"
|
|
67
|
+
"prepublishOnly": "npm test && npm run build",
|
|
68
|
+
"test:studio": "tsx test/studio.e2e.ts"
|
|
68
69
|
},
|
|
69
70
|
"dependencies": {
|
|
70
71
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
@@ -73,6 +74,9 @@
|
|
|
73
74
|
},
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@types/node": "^26.6.5",
|
|
77
|
+
"esbuild": "^0.28.2",
|
|
78
|
+
"preact": "^11.0.2",
|
|
79
|
+
"puppeteer-core": "^24.43.1",
|
|
76
80
|
"tsx": "^4.23.15",
|
|
77
81
|
"typescript": "^7.0.2"
|
|
78
82
|
},
|
|
@@ -1,89 +1,178 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dtly
|
|
3
|
-
description: Make motion graphics and videos with DT.ly — After Effects-style
|
|
3
|
+
description: Make motion graphics and short videos with DT.ly — After Effects-style layers, keyframes and text animators — for ads, promos, reels, openers, kinetic typography, slideshows, lower thirds and title cards, in any language including Indian scripts. Uses the dtly MCP tools (or the dtly CLI). Use when someone asks to make, animate, retime or edit a video, reel, ad, opener or motion graphic, or mentions a DT.ly project.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# DT.ly
|
|
6
|
+
# DT.ly
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
You are the motion designer. You plan the piece, build it layer by layer, look at your own frames,
|
|
9
|
+
and hand over a video someone would actually post.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The bar: it should feel made by a good studio for this exact brand — every move eased, every line
|
|
12
|
+
readable, nothing on screen that doesn't earn its place.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
4. Reach for presets (`preset_list`) for anything standard, then refine with
|
|
20
|
-
`keyframe_set` / `keyframe_ease` / `layer_update`.
|
|
21
|
-
5. **Always look.** `render_sheet` across the key moments (entrances mid-way, holds, exits),
|
|
22
|
-
fix, look again. `render_frame` at scale 0.4 for detail. `project_validate` before export.
|
|
23
|
-
6. `render_video` only when the sheet looks right.
|
|
14
|
+
| Option | Default |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Format | vertical 1080×1920 at 30 fps; also `landscape` 1920×1080, `square` 1080×1080 |
|
|
17
|
+
| Length | 15 s for a reel or ad; 6 s for an opener; follow the brief when it says |
|
|
18
|
+
| Style | inferred from the brief (see [Styles](#styles)) |
|
|
19
|
+
| Language | the language of the brief; keep brand names and numbers as the client writes them |
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
Work in a `dtly-output/` folder in the current directory unless the user names a project file:
|
|
22
|
+
`project.json`, `plan.md`, the final `.mp4`, and a `work/` subfolder for frames and downloads.
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
| Blending modes | `blendMode: multiply|screen|overlay|add|…` |
|
|
43
|
-
|
|
44
|
-
Layer-space origins: solids/images/videos/precomps use their top-left with the anchor at the
|
|
45
|
-
centre by default; shapes are centred on the origin; text is anchored at its alignment point,
|
|
46
|
-
vertically centred on the block. Position defaults to comp centre.
|
|
47
|
-
|
|
48
|
-
## Motion design rules of thumb
|
|
49
|
-
|
|
50
|
-
- **Ease everything.** Entrances: `cubicOut`/`expoOut` (fast in, gentle settle). Exits: `easeIn`/`expoIn`.
|
|
51
|
-
Moves between two rests: `easyEase` or `expoInOut`. Linear only for constant drift (Ken Burns, rotation loops).
|
|
52
|
-
- **Timing.** UI-style moves 0.3–0.6 s; titles 0.6–1.2 s; nothing important shorter than 0.25 s.
|
|
53
|
-
Stagger: graphemes 0.02–0.05 s, words 0.06–0.15 s, lines 0.1–0.2 s.
|
|
54
|
-
- **Overshoot sparingly** (`backOut`, springs): one bouncy element per beat, the rest calm.
|
|
55
|
-
- **Overlap actions.** Start the next element before the previous one settles (≈ 30–50 % overlap); it reads as one gesture.
|
|
56
|
-
- **Hierarchy.** One hero element per moment. Size contrast ≥ 1.6× between title and support text.
|
|
57
|
-
- **Legibility.** Text on footage needs a plate (`box`), a `dropShadow`, or a darkened background
|
|
58
|
-
(`brightness` 40–60 %). Keep text inside the safe area: for 9:16 keep important content
|
|
59
|
-
between y ≈ 250 and y ≈ 1600 and x 60–1020 (UI covers the edges on Reels/Shorts).
|
|
60
|
-
- **Hold.** Let finished text sit still long enough to read before the next thing moves.
|
|
61
|
-
- **Kinetic typography.** Vary scale and colour for emphasis words; alternate entrance directions;
|
|
62
|
-
cut on the beat of the music (markers help: `comp_update` with `markers`).
|
|
63
|
-
|
|
64
|
-
## Indian scripts (Devanagari, etc.)
|
|
65
|
-
|
|
66
|
-
- Shaping is correct at any unit; per-grapheme animation keeps conjuncts (क्ष, श्र, र्ह) intact.
|
|
67
|
-
- Prefer `word` units for Marathi/Hindi body text — readers parse whole words; keep `grapheme`
|
|
68
|
-
effects for short display words.
|
|
69
|
-
- Avoid large `tracking` on Devanagari: it breaks the visual headline (शिरोरेखा) between letters.
|
|
70
|
-
- Bundled fonts: `Baloo 2` (display, default) and `Mukta` (text). Register others in `project.fonts`.
|
|
24
|
+
## 0. Tools
|
|
25
|
+
|
|
26
|
+
DT.ly's editing tools come from its MCP server: `project_create`, `layer_add`, `keyframe_set`,
|
|
27
|
+
`preset_apply`, `render_sheet`, `render_video`, `studio_open` and more (some agents prefix them
|
|
28
|
+
`dtly` or `mcp__dtly__`). If they're missing, give the user their one-line setup and carry on with
|
|
29
|
+
the CLI meanwhile:
|
|
30
|
+
|
|
31
|
+
- Claude Code: `claude mcp add --scope user dtly -- npx -y @dnyantra/dtly mcp`
|
|
32
|
+
- Codex: `codex mcp add dtly -- npx -y @dnyantra/dtly mcp`
|
|
33
|
+
- Cursor, Gemini CLI, Windsurf, VS Code Copilot: `npx @dnyantra/dtly setup <agent>` prints the config.
|
|
34
|
+
- **CLI fallback:** edit `project.json` directly (see [The model](#the-model)), check with
|
|
35
|
+
`dtly sheet project.json work/sheet.png 0.5,2,4` and look at the image, render with
|
|
36
|
+
`dtly render project.json out.mp4`. `dtly init --starter opener|kinetic|bars` gives a start.
|
|
37
|
+
Use the installed `dtly` command if there is one (`npm i -g @dnyantra/dtly`); otherwise
|
|
38
|
+
`npx @dnyantra/dtly …`, which needs network access.
|
|
71
39
|
|
|
72
|
-
|
|
40
|
+
If a tool call is refused for approval, or neither the tools nor the CLI run, stop and tell the user
|
|
41
|
+
exactly what to fix. Don't rebuild the video with other tools — they asked for a DT.ly project they
|
|
42
|
+
can open and edit.
|
|
73
43
|
|
|
74
|
-
|
|
75
|
-
- `text.*` — fadeUp, popIn, slam, blurIn, maskedLines, cascade, trackingIn, centerOut, typewriter, colorSweep, exits (`fadeOutDown`, `blurOut`, `maskedLinesOut`).
|
|
76
|
-
- `kinetic.sequence` — phrase-by-phrase kinetic typography with emphasis words.
|
|
77
|
-
- `opener.logoReveal`, `opener.bars` — brand openers.
|
|
78
|
-
- `slides.slideshow` — sliders from images/clips with Ken Burns, captions and transitions.
|
|
79
|
-
- `transition.between` — push, crossfade, zoom, wipe, whip (motion-blurred), slideUp between two overlapping layers.
|
|
80
|
-
- `element.lowerThird`, `element.highlightWord`.
|
|
44
|
+
DT.ly needs Node.js 20+ and FFmpeg on the PATH.
|
|
81
45
|
|
|
82
|
-
|
|
46
|
+
## 1. Gather
|
|
83
47
|
|
|
84
|
-
|
|
48
|
+
Collect the real material before designing anything.
|
|
49
|
+
|
|
50
|
+
| Source | What to take from it |
|
|
51
|
+
|---|---|
|
|
52
|
+
| The brief | the offer, the audience, the one action the viewer should take, the script if given |
|
|
53
|
+
| Brand | logo, exact colours, fonts, tagline, phone, address, website |
|
|
54
|
+
| Media | the client's clips and photos — look at them (`render_frame` on a test layer, or extract stills) and note the strongest shots |
|
|
55
|
+
| An existing DT.ly project | `project_describe` first; change only what was asked |
|
|
56
|
+
|
|
57
|
+
Then answer, in one line each: What is being sold? To whom? Why them over the shop next door? What
|
|
58
|
+
must the viewer remember? What should they do next, and how (call, visit, tap)? What's the visual
|
|
59
|
+
hook for the first two seconds?
|
|
60
|
+
|
|
61
|
+
Never invent facts: no made-up phone numbers, prices, discounts, ratings or testimonials. If the
|
|
62
|
+
brief leaves a contact detail out, use a clearly marked placeholder and say so when you deliver.
|
|
63
|
+
|
|
64
|
+
## 2. Plan
|
|
65
|
+
|
|
66
|
+
Write `plan.md`: the angle, the hook, the beats with durations that add up to the length, the
|
|
67
|
+
style, the colours and fonts, and what moves in each beat.
|
|
68
|
+
|
|
69
|
+
**Shape for ads and promos:** Hook (2–3 s) → Brand (2–3 s) → 2–3 benefits or proofs → Call to
|
|
70
|
+
action (3–4 s, the phone number or address on screen long enough to write down). A starting
|
|
71
|
+
shape, not a template — openers and kinetic pieces have their own rhythm.
|
|
72
|
+
|
|
73
|
+
If the user points at one thing — a new product, an offer, a festival — make the whole piece
|
|
74
|
+
about that.
|
|
75
|
+
|
|
76
|
+
## Creative laws
|
|
77
|
+
|
|
78
|
+
- **The hook decides.** The first two seconds must move and must say something. Plan them first.
|
|
79
|
+
- **One idea per beat.** One hero element on screen at a time; support text at least 1.6× smaller.
|
|
80
|
+
- **Ease everything.** Entrances `expoOut`/`cubicOut`, exits `easeIn`/`expoIn`, moves between rests
|
|
81
|
+
`easyEase`. Linear only for slow drifts. One bouncy (`backOut`, spring) element per beat, the rest calm.
|
|
82
|
+
- **Readable.** A line the viewer must read stays fully settled for about 0.35 s per word, counted
|
|
83
|
+
from when the whole line has landed. Pace comes from cuts and motion, not from yanking text early.
|
|
84
|
+
- **Overlap, don't queue.** Start the next element while the last one is settling (30–50 %). It
|
|
85
|
+
reads as one gesture instead of a slideshow.
|
|
86
|
+
- **Use the real thing.** The client's footage, photos, logo and words beat stock shapes. Darken or
|
|
87
|
+
blur footage behind text (`brightness` 40–60 %, light `blur`) rather than hiding it.
|
|
88
|
+
- **Safe and legible.** Keep text inside x 60–1020, y 250–1600 on vertical (platform UI covers the
|
|
89
|
+
edges). Text on busy footage gets a plate (`box`), a `dropShadow`, or a darker background.
|
|
90
|
+
- **Specific.** Their words, their colours, their town. "Quality you can trust" on its own is banned;
|
|
91
|
+
say what makes it true.
|
|
92
|
+
- **Every frame postable.** Pause anywhere — it should still look designed.
|
|
93
|
+
|
|
94
|
+
## Styles
|
|
95
|
+
|
|
96
|
+
Presets are defaults; a freeform direction from the user ("like a Diwali sale banner") overrides them.
|
|
97
|
+
|
|
98
|
+
| Style | Feel | Motion and cuts |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| `clean` | Calm, trustworthy, local business | `fadeUp`/`maskedLines`, pushes and crossfades, long holds |
|
|
101
|
+
| `bold` | Loud offer, sale, launch | `slam`/`popIn`, colour bars, whip transitions, short beats |
|
|
102
|
+
| `premium` | Elegant, restrained | `blurIn`/`trackingIn`, slow eases, lots of empty space |
|
|
103
|
+
| `kinetic` | Words are the visuals | `kinetic.sequence`, emphasis words bigger and coloured, cut on the beat |
|
|
104
|
+
| `festive` | Celebration, greetings | warm palette, `cascade`/`popIn`, gentle wiggle on accents |
|
|
105
|
+
| `explainer` | Steps, features | lower thirds, numbered cards, slideUp transitions |
|
|
106
|
+
|
|
107
|
+
## Sound
|
|
108
|
+
|
|
109
|
+
Music sits under everything; a voiceover sits on top of the music. Under a voice keep music around
|
|
110
|
+
0.15–0.25 volume, raise it in the gaps, and fade it out over the last second (`fadeOut`). Match cuts
|
|
111
|
+
to the beat where you can (`comp_update` with `markers` helps). For voiceovers in Indian languages,
|
|
112
|
+
generate them per beat so each line fits its scene, and check the spoken words against the script.
|
|
113
|
+
|
|
114
|
+
## 3. Build
|
|
115
|
+
|
|
116
|
+
- `project_create` with the chosen format and length. Scenes edited as a unit → `comp_add` and
|
|
117
|
+
`precomp` layers.
|
|
118
|
+
- Build bottom-up: background → graphics → text → audio. `layer_add` index 0 is the top.
|
|
119
|
+
- Reach for presets first (`preset_list`): openers, `kinetic.sequence`, `slides.slideshow`,
|
|
120
|
+
`transition.between`, `element.lowerThird`, the `text.*` animators. They write ordinary layers
|
|
121
|
+
and keyframes, so refine them with `keyframe_set`, `keyframe_ease`, `keyframe_move`, `layer_update`.
|
|
122
|
+
- If a person is around, `studio_open` early: they watch your edits land live and can drag keyframes
|
|
123
|
+
or fix text themselves. Their edits save to the same file — `project_describe` again before your
|
|
124
|
+
next change when they say they adjusted something.
|
|
125
|
+
|
|
126
|
+
## 4. Look, then fix
|
|
127
|
+
|
|
128
|
+
Before rendering, `render_sheet` across every beat **and** mid-transition, and `render_frame` at
|
|
129
|
+
scale 0.4 for detail. Fix text overflowing or colliding, low contrast, anything clipped by the safe
|
|
130
|
+
area, and entrances still moving when the viewer should be reading. Two busy layouts crossfading
|
|
131
|
+
make a muddy double exposure: move the old content out, then bring the new in, or dip through the
|
|
132
|
+
background. Run `project_validate`. Only then `render_video`.
|
|
133
|
+
|
|
134
|
+
## 5. Deliver
|
|
135
|
+
|
|
136
|
+
- The `.mp4`, plus a poster: the strongest settled frame (text fully landed, not mid-move) saved
|
|
137
|
+
with `render_frame` as `poster.png`.
|
|
138
|
+
- Tell the user where the files are, the angle in one sentence, any placeholders they must fill,
|
|
139
|
+
and offer the next step: open it in Studio to tweak, another style, or 30 s / 60 s and square versions.
|
|
85
140
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## The model
|
|
144
|
+
|
|
145
|
+
A project is JSON: `comps[]`, each with `width`, `height`, `fps`, `duration`, `background` and
|
|
146
|
+
`layers[]` (index 0 is the top layer).
|
|
147
|
+
|
|
148
|
+
| After Effects | DT.ly |
|
|
149
|
+
|---|---|
|
|
150
|
+
| Composition / precomp | `comps[]`, layer `type: "precomp"` |
|
|
151
|
+
| Layer in/out | `inPoint` / `outPoint` (seconds) |
|
|
152
|
+
| Transform | `transform.anchor/position/scale(%)/rotation(°)/opacity(%)/skew` |
|
|
153
|
+
| Keyframes | any property as `{keyframes: [{t, v, ease}]}`; `ease` shapes the segment *leaving* that key |
|
|
154
|
+
| Easing | `easyEase`, `easeIn`, `easeOut`, `cubicOut`, `expoIn/Out/InOut`, `backOut`, bezier `[x1,y1,x2,y2]`, `{spring: {stiffness, damping}}`, `hold` |
|
|
155
|
+
| `wiggle()` | `{keyframes: […], wiggle: {freq, amp, seed}}` |
|
|
156
|
+
| Parenting / null | `parent: layerId`, `type: "null"` (inherits transform, not opacity) |
|
|
157
|
+
| Masks | `masks: [{shape: rect\|ellipse\|path, rect: [x,y,w,h], inverted}]`, in layer space |
|
|
158
|
+
| Track matte | `matte: {layer, mode: alpha\|alphaInverted}` |
|
|
159
|
+
| Trim paths | shape `trim: {start, end}` in % — draw-on lines, rings, underlines |
|
|
160
|
+
| Text animators | `animators: [{unit: grapheme\|word\|line, stagger, duration, delay, order, ease, from: {opacity, x, y, scale, rotation, blur, tracking, color}, clip, mode: "out"}]` |
|
|
161
|
+
| Effects | `blur`, `dropShadow`, `glow`, `fill`, `brightness`, `saturate`, `contrast` |
|
|
162
|
+
| Motion blur | `motionBlur: {samples, shutter}` |
|
|
163
|
+
| Blending | `blendMode: multiply\|screen\|overlay\|add\|…` |
|
|
164
|
+
|
|
165
|
+
Layer types: `text`, `shape` (`rect`, `ellipse`, `polygon`, `path`, `line`), `solid`, `image`,
|
|
166
|
+
`video` (`trimIn`, `speed`, `volume`), `audio` (`volume`, `fadeIn`, `fadeOut`), `precomp`, `null`.
|
|
167
|
+
Solids, images, videos and precomps are anchored at their centre; shapes are centred on their
|
|
168
|
+
origin; text is anchored at its alignment point, vertically centred. Position defaults to the
|
|
169
|
+
comp centre.
|
|
170
|
+
|
|
171
|
+
## Indian scripts
|
|
172
|
+
|
|
173
|
+
- Devanagari and other Indic scripts shape correctly at every unit; per-letter animation keeps
|
|
174
|
+
conjuncts (क्ष, श्र, र्ह) whole.
|
|
175
|
+
- Animate body text by `word` — readers take Marathi and Hindi in whole words. Save `grapheme`
|
|
176
|
+
effects for one or two display words.
|
|
177
|
+
- Avoid wide `tracking` on Devanagari; it breaks the headline bar (शिरोरेखा) between letters.
|
|
178
|
+
- Bundled fonts: `Baloo 2` (display, default) and `Mukta` (text). Register others in `project.fonts`.
|