Kinetic Typography

Kinetic Typography [2026]: 12 Steps in 40 Min

Kinetic Typography [2026]: 12 Steps in 40 Min

Kinetic typography is text that moves in time with speech or music, and you can build a clean 20-second piece in about 40 minutes if you plan the timing before you touch a keyframe. This guide builds one project twice: once in Adobe After Effects, where you control every frame, and once in CapCut, where presets get you a readable result faster. After Effects is listed at US$22.99 per month on Adobe’s annual plan billed monthly, and CapCut has a US$0 Free tier, so the cost question is settled before the craft question starts.

The project is a 1920×1080, 30 fps, 600-frame video set to 120 BPM. At that tempo one beat is exactly 15 frames, one bar is 60 frames, and every word entrance lands on a number you can type into the timeline. That arithmetic is the whole trick. Most weak animated text fails on timing, not on fonts or effects.

You get 12 numbered steps, a script that builds the whole composition for you, an ffmpeg export recipe, a list of pitfalls and a troubleshooting table. If you want more on this style of work, the kinetic typography section collects the related guides on text animation and animated type.

What kinetic typography is and what you will build

Kinetic typography is a technique, not a product. There is no standalone version number and no subscription for it. You make it inside a video editor or motion graphics app by animating text layers so each word enters, holds and leaves on a planned beat. The two tools that matter most for this today are After Effects (the precise option) and CapCut (the fast option).

The finished piece in this tutorial has ten phrase cards, starting with WORDS, HAVE, TIMING, IN, HOLD and OUT, followed by two longer lines and a closing card. Each card follows one pattern: a 12-frame entrance with a small scale pop and an upward slide, a hold that matches its word count, and a 6-frame exit. Keeping one pattern across all cards is deliberate. A viewer reads the rhythm first and the words second, so the rhythm needs to stay consistent.

You will end with three files: an After Effects project containing a composition called KT_Main, a lossless or ProRes master render, and an H.264 MP4 for upload. Along the way you will learn how to convert beats to frames, how to give text a gentle camera-like drift without hurting readability, and how to animate per character when a word needs extra emphasis.

A few definitions keep the later steps short. An in is the entrance animation. A hold is the stretch where the word sits still enough to read. An out is the exit. A cue is one phrase with its start time and length. A beat grid is the list of cues snapped to musical time. If you can describe a card as in, hold, out on a grid, you can build it in any app.

The same structure works for lyric videos, podcast teasers, quote cards, product explainers and the text-driven openers that start a video. If you want a finished title sequence instead of building one, Vipid’s smoke title sequence theme is one ready-made option. The build below is for people who want to own every frame.

After Effects or CapCut: pick the tool before you start

Use After Effects when the text needs per-character control, expressions or reusable rigs. Use CapCut when you need a readable result in minutes and the preset animations are enough. Adobe describes After Effects as its motion graphics and visual effects app, and lists the Creative Cloud Pro bundle that includes it at US$69.99 per month on an annual plan billed monthly.

CapCut sits on the other side of that trade. Its official materials show a Free tier at US$0 with basic editing and templates, plus paid tiers. CapCut says Pro pricing varies by region, device and promotion, and it tells users to check the subscription screen in the app for the price that applies to them. On March 25, 2026, CapCut restructured its plans, introduced a Standard plan and upgraded Pro, and old pricing stopped being offered to new subscribers.

On October 27, 2026, CapCut announced new AI editing tools and a planned ChatGPT plugin at its CapCut World event in Los Angeles. Those tools may speed up rough cuts, captions and timing changes. The material published so far does not show a dedicated replacement for After Effects-style per-letter animation, graph editing or text rigging, so treat CapCut as the rapid option and After Effects as the controllable one. The plugin was described as upcoming, which means you should not plan a workflow around it today.

QuestionAfter EffectsCapCut
Cost to startUS$22.99 per month, annual plan billed monthly (Adobe plan page)Free tier at US$0, paid tiers vary by region
Per-character animationYes, through text animators and range selectorsPresets and templates, no dedicated per-letter rig in current materials
KeyframesFull control with a graph editorPosition, scale and opacity keyframes
Expressions and scriptingYes, including ExtendScriptNo
Time to a first readable resultSlower, you build the systemFaster, you pick a preset and adjust
Reuse across projectsComps, presets and scriptsTemplates

A practical split works for many creators. Build the hero piece, such as a channel opener, in After Effects and keep it as a template. Use CapCut for the weekly short-form clips where speed matters more than a rig. Both tools can share one audio file and one script, so planning the beat grid once serves both.

Prerequisites and versions

You need a computer that runs After Effects, a license or trial, a music track at a known tempo, and a command-line copy of ffmpeg for the final encode. Everything else in this guide is free.

  • Adobe After Effects: the latest release. Adobe’s release notes list a September 2026 release as the newest, so check Help > About in your install and update if you are behind. Earlier 2026 releases added the AI-powered Object Matte tool (26.2) and depth of field in the Advanced 3D renderer for 3D text (26.3). Adobe’s FAQ reportedly offers a 7-day trial through Creative Cloud.
  • CapCut Desktop: the latest version from capcut.com. Features and export limits vary by account and region, so check the export panel in your own install.
  • ffmpeg and ffprobe: any recent build that includes libx264 and the ProRes encoder. Run ffmpeg -version to confirm.
  • Python 3: only for the optional cue converter in the planning section.
  • A font you are licensed to use in video: a bold sans serif works best for a first attempt. Check the font license for video and commercial use before you publish.
  • A music track at a fixed tempo: this guide uses 120 BPM. If you do not have one, a metronome-style click track exported from any audio app works for the first run.
  • Disk space: a few gigabytes free for the master render and caches.

Adobe’s FAQ page and release notes are the places to confirm what your own install can do, since tutorials tied to one interface go stale when the app updates. Adobe also documents an After Effects AI Assistant that was in beta in October 2026. It is a feature under test, not a replacement for the main workflow, and nothing in this guide depends on it.

Render settings for the 20-second project

Lock the numbers first. Resolution, frame rate and length decide every later calculation, and changing the frame rate mid-project forces you to retime every keyframe. The table below is the spec for the whole tutorial.

SettingValueWhy
Resolution1920×1080Standard 16:9 delivery size, light to render
Frame rate30 fpsMakes 120 BPM land on whole frames (15 per beat)
Length20 seconds (600 frames)10 bars at 120 BPM
Title-safe margin80% of frame (1536×864, 192 px side margins)Keeps text clear of edges and interface overlays
Master exportA high-quality master export from After EffectsClean source for every later encode
Delivery exportH.264 MP4, yuv420p, CRF 16 to 18, AAC 192kPlays almost everywhere
Overlay exportProRes 4444 with alphaKeeps transparency for lower-third style use

If you plan to publish a vertical version, build the horizontal master first, then re-lay the text in a 1080×1920 composition. Center-cropping a horizontal text piece cuts words in half, and the pitfalls section explains the fix. For other platform sizes, check the platform’s own specs page before you export.

The delivery numbers above are working starting points, not platform rules. CRF 16 to 18 gives a high-quality H.264 file for flat-color motion graphics, and you can raise the CRF to shrink the file if an upload limit forces you to. Sharp edges on flat color show compression damage sooner than live footage does, so lower the CRF before you lower the resolution.

Plan the script and the beat grid

Write the cues on paper or in a spreadsheet before you open After Effects. Each cue gets a start beat and a length in beats. At 120 BPM and 30 fps, multiply the beat number by 15 to get the frame. A cue starting on beat 4 begins at frame 60. A five-beat cue runs 75 frames.

The grid for this project is below. Frames count from 0, and the out frame is where the exit finishes and the next card begins.

CardTextIn (seconds)In frameOut frameBeats
1WORDS0.515603
2HAVE2.0601053
3TIMING3.51051503
4IN5.0150Not listed3
5HOLDNot listedNot listed2403
6OUT8.0240Not listed3
712 FRAMES TO ARRIVENot listedNot listed3605
8READABLE FIRST12.0360Not listed5
9THEN MOVENot listedNot listedNot listed4
10RENDER ITNot listedNot listedNot listed6

The lengths come from a simple reading rule. Give a one-word card a short hold, then add a little more time for each extra word. Add the entrance and the exit on top. A four-word card therefore needs a longer hold and a longer total than a one-word card, which is why card 7 gets the longest slot. Treat the rule as a floor. If the music is slow or the words are unusual, give the viewer more time.

Words on the cardMinimum holdMinimum total on screenFrames at 30 fps
10.6 s1.2 s36
20.9 s1.5 s45
31.2 sNot listed54
41.5 s2.1 s63
62.1 s2.7 s81

If you would rather let a script do the arithmetic, save the cues in a CSV file with the columns text, start_beat and beats, then run the small converter below. It prints each cue in seconds and in frames, formatted so you can paste the lines straight into the build script later. A \n inside the text field becomes a line break.

# cues.csv
text,start_beat,beats
WORDS,1,3
HAVE,4,3
TIMING,7,3
IN,10,3
HOLD,13,3
OUT,16,3
12 FRAMES\nTO ARRIVE,19,5
READABLE\nFIRST,24,5
THEN MOVE,29,4
RENDER IT,33,6

# beats_to_frames.py
import csv
from fractions import Fraction

BPM = 120
FPS = Fraction(30)          # use Fraction(30000, 1001) for 29.97

def beat_to_seconds(beat):
    return beat * 60 / BPM

def seconds_to_frame(sec):
    return round(sec * FPS)

with open("cues.csv", newline="") as f:
    for row in csv.DictReader(f):
        t = beat_to_seconds(float(row["start_beat"]))
        d = beat_to_seconds(float(row["beats"]))
        text = row["text"].replace("\\n", "\\r")
        print('{ text: "%s", t: %.3f, d: %.3f },  // frames %d-%d'
              % (text, t, d, seconds_to_frame(t), seconds_to_frame(t + d)))

Expected output for the first two cues:

{ text: "WORDS", t: 0.500, d: 1.500 },  // frames 15-60
{ text: "HAVE", t: 2.000, d: 1.500 },  // frames 60-105

Frame by frame: set up the composition (steps 1 to 3)

Steps 1 to 3 give you an empty stage with safe margins and one correctly typeset word. Do them by hand once so you understand what the script automates later.

Step 1: Create the composition

Choose Composition > New Composition. Name it KT_Main, set the width to 1920 and the height to 1080, pixel aspect ratio to square, frame rate to 30, and duration to 0:00:20:00. Set the background to a dark flat color such as near-black blue. Dark flat backgrounds keep contrast high and make compression artifacts less visible in the final MP4. Turn on Motion Blur for the composition with the switch at the top of the timeline, since moving type without blur looks stepped at 30 fps.

Step 2: Add safe margins and a beat ruler

Use guides to keep the type inside the title-safe area. Adobe’s release notes for version 26.5 describe percentage-based positioning and custom guide colors, which makes this easier on a current install. On older builds, pixel guides do the same job.

Next, add a beat ruler. Create a Null layer called BEATS, then add a layer marker every 15 frames. You can type each one in by hand, but the build script at the end of this guide does it in one pass. The markers matter because layer snapping can lock your keyframes to them, and a keyframe that sits exactly on a beat feels tight to the viewer.

Step 3: Add the first text layer

Use the Type tool to click once in the viewer and type WORDS. In the Character panel, set a bold sans serif at 240 px, white fill, no stroke. In the Paragraph panel, choose center justification. Then set the layer’s Anchor Point to the center of the text so scaling grows from the middle. The fast way is an expression on Anchor Point:

r = sourceRectAtTime(time, false);
[r.left + r.width / 2, r.top + r.height / 2];

Set the layer’s Position to the exact center of the frame. The anchor expression keeps the text centered even when you edit the wording, so later changes do not push cards off-center. Check the width. A long line in a bold sans serif at a large size can run past the title-safe width. Longer lines need a smaller size or a line break.

Frame by frame: animate one word in, hold and out (steps 4 to 6)

Steps 4 to 6 build the in, hold, out pattern on a single layer. Get this one card right and every other card is a duplicate with new text.

Step 4: Set the in point and the entrance keyframes

Park the playhead at frame 15, which is 0.5 seconds, and press Alt+[ on Windows or Option+[ on a Mac to trim the layer start there. Move to frame 60 and press Alt+] or Option+] to trim the end. Now add keyframes for the entrance:

  • Opacity: 0% at frame 15, 100% at frame 18. A three-frame fade removes the hard pop without softening the arrival.
  • Scale: 60% at frame 15, 100% at frame 27. The 12-frame arrival lasts 0.4 seconds, inside the 9 to 18 frame range (0.3 to 0.6 seconds) that works as a default for entrances at 30 fps.
  • Position Y: 600 at frame 15, 540 at frame 27. The word rises 60 px as it grows.

Preview the entrance with RAM Preview. If the pop feels flat, the usual cause is linear timing, which Step 5 fixes. If it feels slow, shorten the arrival to 9 frames. If it feels frantic, stretch it toward 18.

Step 5: Add easing and an overshoot

Select the Position keyframes and press F9 for Easy Ease. Open the graph editor and drag the handles so the motion leaves fast and settles slowly. That curve reads as weight. For the scale pop, a small overshoot adds a springy feel. Keep the Scale keyframes linear, because the overshoot expression reads the speed at the final keyframe, and a fully eased stop has speed near zero, which means no bounce. Alt-click the Scale stopwatch and paste this:

amp = 12;      // overshoot strength
freq = 3;      // bounces per second
decay = 6;     // how fast the bounce dies
n = 0;
if (numKeys > 0) {
  n = nearestKey(time).index;
  if (key(n).time > time) n--;
}
if (n > 0) {
  t = time - key(n).time;
  v = velocityAtTime(key(n).time - thisComp.frameDuration / 10);
  value + v * amp * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t);
} else {
  value;
}

The word now grows past 100% by a few percent and settles within about a quarter of a second. If the bounce looks cartoonish, drop amp to 6. If it is barely visible, raise it to 18. Never let the overshoot push the word outside the title-safe box, since a bounce that clips the edge looks like a mistake.

Step 6: Set the hold and the exit

The hold is the stretch between frame 27 and frame 54, where nothing moves except the faint drift you add in Step 9. Do not animate during the hold. A still word is how the viewer reads it. Add the exit with keyframes at its end: Opacity from 100% to 0%, plus a small upward move in Position Y. The word lifts and fades over just a few frames.

Exits should be shorter than entrances. The eye needs time to land on a new word, but it does not need time to watch an old one leave. When the exit ends at frame 60, the next card begins at frame 60, so the screen never sits empty for longer than a few frames. If you want overlapping cards, start the next entrance 4 to 6 frames before the previous exit ends, then compare both versions with the music on.

Frame by frame: per-character animation and a drift null (steps 7 to 9)

Steps 7 to 9 add the two moves that make a card feel designed rather than merely animated: a per-letter reveal for emphasis words and a slow shared drift so the frame never freezes completely. Use the per-character reveal sparingly. One or two cards per piece is enough.

Step 7: Build a per-character reveal with a text animator

Duplicate the WORDS layer and rename the copy TIMING_REVEAL, then change its text to TIMING. Expand the layer, find Text, and click Animate. Choose Opacity and set the value to 0%. Click Animate again and add Position, then set Y to 60. You now have one animator holding two properties, and it applies to whichever characters the Range Selector covers. With Opacity at 0%, the covered letters are invisible and sit 60 px low.

Open Range Selector 1 and expand Advanced. Set Based On to Characters, Shape to Ramp Up and Smoothness to 100%. Ramp Up gives each letter a slightly later start than the one before it, which makes the reveal sweep across the word instead of flashing all at once. Leave Ease High and Ease Low at their defaults for the first pass, then tune them by eye.

Step 8: Stagger the letters with the Start value

The Range Selector Start value controls who is hidden. At Start 0%, every letter is covered, so the word is invisible and low. At Start 100%, nothing is covered, so the word is fully visible and in place. Animate Start from 0% at frame 105 to 100% at frame 117, a 12-frame reveal that matches the standard card entrance. Because the word TIMING has six letters, each letter gets roughly two frames of offset from its neighbor, which reads as a quick ripple.

Then remove the standard Scale and Opacity keyframes from this layer so the animator does the entrance alone. Keep the 6-frame exit from Step 6. Mixing a per-letter entrance with a whole-word scale pop makes the letters shimmer, and the shimmer looks like a bug at 30 fps. If you want a bigger move, animate the Range Selector Offset instead of Start, which lets a highlighted band of letters travel through the word.

Step 9: Parent every card to a drift null

A drift is a tiny, slow move shared by every card. It keeps the held words alive without competing with the entrances. Create a Null layer called DRIFT, set its Anchor Point to 0, 0 and its Position to 0, 0, then parent all text layers to it with the pick whip. Setting the null’s anchor and position to zero matters, because a parent’s offsets add to each child, and a null with a default anchor would shift every card by half the null’s size. Add this expression to the null’s Position:

[Math.sin(time * 0.8) * 12, Math.cos(time * 0.6) * 8]

The text now floats by at most 12 px sideways and 8 px up and down, on two slightly different cycles so the path never looks mechanical. If viewers can notice the drift on a first look, it is too strong. Cut the multipliers in half. The right amount is the amount you only see when you pause the clip and compare two frames.

Frame by frame: sync to music and export (steps 10 to 12)

Steps 10 to 12 attach the audio, snap each card to the grid and send the piece out as a master and a delivery file. The order matters, because retiming cards after export means a second render.

Step 10: Add the audio and drop beat markers

Drag your 120 BPM track into the timeline, trim it to 20 seconds and make sure the first beat sits at time 0 or at a known offset. Play the composition and press the asterisk key on the numeric keypad on each beat to drop a marker on the audio layer, or let the build script generate the markers from the BPM. After Effects can show the waveform with the L key twice, so you can check that markers sit on the visible peaks of the kick drum. If they drift, your track is not a fixed tempo, and a grid built on 15-frame beats will not match it.

Step 11: Snap every card to the beat grid

Duplicate the finished WORDS card nine times and replace the text in each copy. Turn on the Snap magnet in the timeline and drag each layer so its in point lands on its marker from the grid table. Trim each out point to the frame in the table. Because the keyframes were set relative to the in point of the first card, move whole layers rather than individual keyframes, and the 12-frame entrance and 6-frame exit travel with them.

Scrub through the cut at half speed. On every card, the first visible movement should coincide with a beat, and the word should be readable before the next beat arrives. If a card feels late, nudge it earlier by 2 or 3 frames. Visual motion that lands a touch before the sound usually feels more in sync than motion that lands dead on it.

Step 12: Render a master, then encode the delivery file

Add the composition to the render queue, choose a high-quality or lossless output, include audio, and render. You can also send the composition to Adobe Media Encoder and pick H.264 there. Rendering a master first keeps a clean source, and ffmpeg then gives you repeatable settings for every upload.

# H.264 MP4 for upload (audio included in the master)
ffmpeg -i kinetic_master.mov \
  -c:v libx264 -preset slow -crf 17 -pix_fmt yuv420p \
  -colorspace bt709 -color_primaries bt709 -color_trc bt709 \
  -r 30 -c:a aac -b:a 192k -movflags +faststart \
  kinetic_1080p30.mp4

# ProRes 4444 with alpha for overlay use (needs a master with alpha)
ffmpeg -i kinetic_master_alpha.mov \
  -c:v prores_ks -profile:v 4444 -pix_fmt yuva444p10le \
  kinetic_overlay_alpha.mov

# Fallback 9:16 center crop (re-laying the text is better)
ffmpeg -i kinetic_master.mov \
  -vf "crop=606:1080:657:0,scale=1080:1920" \
  -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac -b:a 192k \
  kinetic_vertical.mp4

Verify the delivery file before you upload it. The command below prints the properties that most often go wrong.

ffprobe -v error -select_streams v:0 \
  -show_entries stream=codec_name,width,height,pix_fmt,r_frame_rate,nb_frames \
  -of default=noprint_wrappers=1 kinetic_1080p30.mp4

# expected
codec_name=h264
width=1920
height=1080
pix_fmt=yuv420p
r_frame_rate=30/1
nb_frames=600

A frame count of 600 confirms the render kept the 20-second length. A pix_fmt of yuv420p confirms the file will play in browsers, phones and most TVs. If either differs, fix the cause before you upload instead of hoping the platform’s re-encode will mask it. From the Vipid archive: the intro themes page lists resolution, length and frame rate for each theme, which is a handy reference when you pick specs for your own opener.

Build the same piece in CapCut

CapCut gets you a similar result with presets instead of keyframes, and the timing rules carry over unchanged. The plan: one solid-color background, ten text clips placed on the same frame grid, and an entrance, exit and optional loop on each. According to CapCut’s own guide on animating text, the workflow supports entrance, exit and looping animations, and the timing controls exist to keep text readable early in the shot.

  1. Create the project and set the ratio. Use 16:9 for YouTube, 9:16 for TikTok or Instagram Reels, or 1:1 for square feeds. Add a dark solid color clip as the background and stretch it to 20 seconds.
  2. Add the text. Open Text > Add text and click the default style. Type WORDS and choose a bold font. Move the clip so it starts on the 0.5-second mark.
  3. Apply an animation. Open the Animation tab and pick an In effect. Then set the Out effect for the exit. CapCut also offers Loop effects, which run during the hold, so leave them off for a first pass.
  4. Tune speed, direction and position. After you pick an effect, adjust its speed so the arrival takes about 0.4 seconds, which is 12 frames at 30 fps. Make the exit shorter than the arrival.
  5. Add keyframes for custom moves. Use keyframes on Position, Scale and Opacity if a preset does not give the slide or pop you want. The values from Steps 4 to 6 transfer directly.
  6. Copy the style. Duplicate the clip, change the text and drag it to the next grid time. Duplicating keeps the animation settings, so the pattern stays consistent.
  7. Add music and align. Import the 120 BPM track, zoom the timeline until you can see single frames and line each clip start up with a beat.
  8. Export. In the export panel, choose the resolution and frame rate you set at the start and a codec. H.264 is the safe choice for wide playback.

CapCut’s own pages say the Free tier covers basic editing and free templates, and that export limits, AI trials and credits vary by account and region. Its PC page reportedly describes watermark-free exports up to 4K on the free PC edition and associates Pro with advanced AI functions and 4K at 60 fps, subject to plan and region. Check the export screen in your own account before you promise a client a spec.

CapCut also reportedly promoted a Free Kinetic Text Template in July 2026. A template is a fast start when the brief is a lyric line or a quote, but you give up the per-letter control that Steps 7 and 8 provide. When the brand’s type needs exact tracking, custom easing or a reusable system, go back to After Effects.

Complete working project: one script that builds the whole composition

The script below creates KT_Main at 1920×1080 and 30 fps, adds the background, the DRIFT null, the BEATS marker layer, ten text cards with the in, hold, out pattern and motion blur, and imports your audio if the file exists. It uses standard ExtendScript calls and the same numbers as Steps 1 to 11. Save it as kt_build.jsx, open After Effects, choose File > Scripts > Run Script File and pick it. Try it on a scratch project first, and keep the version you are happy with.

// kt_build.jsx
(function () {
  var W = 1920, H = 1080, FPS = 30, DUR = 20, BPM = 120;
  var FR = 1 / FPS;
  var ENTER = 12 * FR, FADE = 3 * FR, EXIT = 6 * FR;

  var cues = [
    { text: "WORDS", t: 0.5, d: 1.5 },
    { text: "HAVE", t: 2.0, d: 1.5 },
    { text: "TIMING", t: 3.5, d: 1.5 },
    { text: "IN", t: 5.0, d: 1.5 },
    { text: "HOLD", t: 6.5, d: 1.5 },
    { text: "OUT", t: 8.0, d: 1.5 },
    { text: "12 FRAMES\rTO ARRIVE", t: 9.5, d: 2.5 },
    { text: "READABLE\rFIRST", t: 12.0, d: 2.5 },
    { text: "THEN MOVE", t: 14.5, d: 2.0 },
    { text: "RENDER IT", t: 16.5, d: 3.0 }
  ];

  var ANCHOR = "r = sourceRectAtTime(time, false);\n" +
               "[r.left + r.width / 2, r.top + r.height / 2];";
  var OVERSHOOT = [
    "amp = 12; freq = 3; decay = 6; n = 0;",
    "if (numKeys > 0) { n = nearestKey(time).index; if (key(n).time > time) n--; }",
    "if (n > 0) {",
    "  t = time - key(n).time;",
    "  v = velocityAtTime(key(n).time - thisComp.frameDuration / 10);",
    "  value + v * amp * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t);",
    "} else { value; }"
  ].join("\n");

  function fill(prop, v) {
    var a = [];
    for (var i = 0; i < prop.dimensions; i++) a.push(v);
    return a;
  }
  function ease(prop, idx, infl) {
    var n = prop.isSpatial ? 1 : prop.dimensions, e = [];
    for (var i = 0; i < n; i++) e.push(new KeyframeEase(0, infl));
    prop.setTemporalEaseAtKey(idx, e, e);
  }

  app.beginUndoGroup("Kinetic type build");
  var comp = app.project.items.addComp("KT_Main", W, H, 1, DUR, FPS);
  comp.motionBlur = true;
  comp.openInViewer();

  comp.layers.addSolid([0.05, 0.06, 0.09], "BG", W, H, 1);

  var drift = comp.layers.addNull(DUR);
  drift.name = "DRIFT";
  drift.property("Anchor Point").setValue([0, 0]);
  drift.property("Position").setValue([0, 0]);
  drift.property("Position").expression =
    "[Math.sin(time * 0.8) * 12, Math.cos(time * 0.6) * 8]";

  var beatLayer = comp.layers.addNull(DUR);
  beatLayer.name = "BEATS";
  var mk = beatLayer.property("Marker");
  for (var b = 0; b < DUR * BPM / 60; b++) {
    mk.setValueAtTime(b * 60 / BPM, new MarkerValue(b % 4 === 0 ? "bar " + (b / 4 + 1) : ""));
  }

  var cx = W / 2, cy = H / 2;
  for (var i = 0; i < cues.length; i++) {
    var c = cues[i];
    var lines = c.text.split("\r"), longest = 0;
    for (var k = 0; k < lines.length; k++) longest = Math.max(longest, lines[k].length);
    var size = Math.min(240, Math.floor((W * 0.8) / (longest * 0.68)));

    var tl = comp.layers.addText(c.text);
    var src = tl.property("Source Text");
    var td = src.value;
    td.fontSize = size;
    td.font = "Arial-BoldMT";
    td.fillColor = [1, 1, 1];
    td.applyFill = true;
    td.applyStroke = false;
    td.justification = ParagraphJustification.CENTER_JUSTIFY;
    src.setValue(td);

    tl.property("Anchor Point").expression = ANCHOR;
    tl.parent = drift;
    tl.motionBlur = true;
    tl.inPoint = c.t;
    tl.outPoint = c.t + c.d;

    var t0 = c.t, t1 = c.t + ENTER, tEx = c.t + c.d - EXIT, tEnd = c.t + c.d;

    var op = tl.property("Opacity");
    op.setValueAtTime(t0, 0);
    op.setValueAtTime(t0 + FADE, 100);
    op.setValueAtTime(tEx, 100);
    op.setValueAtTime(tEnd, 0);

    var sc = tl.property("Scale");
    sc.setValueAtTime(t0, fill(sc, 60));
    sc.setValueAtTime(t1, fill(sc, 100));
    sc.expression = OVERSHOOT;

    var pos = tl.property("Position");
    pos.setValueAtTime(t0, [cx, cy + 60]);
    pos.setValueAtTime(t1, [cx, cy]);
    pos.setValueAtTime(tEx, [cx, cy]);
    pos.setValueAtTime(tEnd, [cx, cy - 40]);
    for (var j = 1; j <= 4; j++) ease(pos, j, 66);
  }

  var audio = new File("~/Desktop/kt/music_120bpm.wav");
  if (audio.exists) {
    var item = app.project.importFile(new ImportOptions(audio));
    comp.layers.add(item).moveToEnd();
  }

  app.endUndoGroup();
  alert("Built " + cues.length + " cards in KT_Main (" + Math.round(DUR * FPS) +
        " frames, " + (60 * FPS / BPM) + " frames per beat).");
})();

When the script finishes you should see this dialog, and a new composition in the Project panel with 600 frames of timeline:

Built 10 cards in KT_Main (600 frames, 15 frames per beat).

Scrub the timeline and check three things. Every card should enter on a marker, no line should cross the title-safe box, and the DRIFT null should move everything together without any single card moving alone. Then add your per-character reveal from Steps 7 and 8 to one or two emphasis cards, drop the audio, render the master and run the ffmpeg commands from Step 12.

To reuse the build, change only the cues array. Paste in lines from the Python converter, adjust BPM and DUR at the top, and rerun. A different tempo changes the frame count per beat, so keep the alert text as a quick check that the numbers still divide evenly. At 128 BPM, for instance, a beat is 14.06 frames, and you will want to round entrances to whole frames or switch to a frame rate that divides your tempo more cleanly.

Common pitfalls that make animated text hard to read

Most failed kinetic text projects share the same handful of mistakes. Check your cut against this list before you render.

  • Entrances longer than about 18 frames at 30 fps. A 24-frame entrance means the viewer waits nearly a second for each word. Keep arrivals between 9 and 18 frames and use the rest of the card for the hold.
  • Animating everything on every card. Position, scale, rotation, blur and a per-letter reveal on every word turns the piece into noise. Use one pattern for most cards and spend the extra effort on one or two emphasis words.
  • Ignoring the safe margins. A word that touches the edge can be cut off by a phone’s rounded corners or covered by interface elements. Stay inside the 80% title-safe area, even during overshoot and drift.
  • Linear motion on everything. Straight-line timing looks mechanical. Ease the position and fades, and keep scale linear only when you rely on the overshoot expression.
  • Mixing frame rates. A 30 fps project fed a 29.97 fps edit, or a music track cut at another rate, drifts out of sync. Over 10 minutes, 30 fps and 29.97 fps drift apart by about 18 frames. For a 20-second piece the gap is under one frame, but long videos expose it.
  • Poor contrast and busy backgrounds. White bold type on a dark flat color is the safe baseline. If you place text over footage, add a darkening layer or a soft shadow before you trust your eyes at full screen.
  • Center-cropping for vertical. A 16:9 layout cropped to 9:16 loses the sides of every wide card. Rebuild the cards in a 1080×1920 composition, shorten lines and split phrases across two lines.
  • Unlicensed fonts. A font bundled with a design app is not automatically licensed for video or commercial use. Read the license before a client piece goes out.

A quick self-test catches most of these. Mute the video and watch it once at full screen. Can you read every word as it arrives? Then play it with sound and no picture, if your editor allows, and tap along to check the beat. If both tests pass, the details are probably right.

Troubleshooting kinetic text builds and exports

These are the problems that most often appear on a first build, with the cause and the fix.

SymptomLikely causeFix
Overshoot expression does nothingScale keyframes are fully eased, so the speed at the last key is near zero, or there is only one keyframeUse at least two linear Scale keyframes, then raise amp to 12 or more
Text shimmers or jitters during the holdDrift too strong, thin font weight, or motion blur offHalve the DRIFT multipliers, use a bolder weight, turn on motion blur
Cards sit off-center after editing the textThe Anchor Point expression is missing or justification is not centeredReapply the sourceRectAtTime anchor expression and set center justification
Script stops with a syntax errorSmart quotes or stray characters from pasting out of a web pagePaste into a plain text editor first, save as .jsx, run again
Script cannot find the audioThe path in the script does not match your folder, or file access is restrictedEdit the File path, and check the scripting preferences if file access is blocked
Colors look washed out after encodingMissing color tags or a range mismatch in the playerAdd the bt709 tags shown in Step 12 and test in a second player
Black fringe or no transparency on the overlayMaster was not rendered with an alpha channel, or alpha is premultiplied against blackRender RGB + Alpha, encode ProRes 4444 with yuva444p10le, and match the alpha setting in your editor
Audio lands a few frames lateLeading silence or encoder padding on the music file, or a 29.97 versus 30 mismatchUse a WAV file, slide the audio layer, and keep the project at one frame rate
MP4 will not play on a TV or phonePixel format is 4:4:4 or 10-bitForce -pix_fmt yuv420p in the ffmpeg command
Font changes on another computerThe font is not installed thereInstall it, or collect files with the project, or convert the text to shapes for delivery
Preview stuttersMotion blur and expressions are heavy at full resolutionUse half resolution for previews, and only turn on motion blur for the final pass
CapCut export looks softExport resolution or frame rate differs from the projectMatch the export panel to 1920×1080 at 30 fps

If the problem is not in the table, bisect it. Turn off the DRIFT parent, then motion blur, then expressions, one at a time, and re-preview. The setting that makes the glitch disappear is the culprit, and from there the fix is usually one of the rows above.

Advanced tips for tighter kinetic text

Once the basic card pattern works, these upgrades add polish without adding chaos.

  • Drive scale from the audio. Select the audio layer, choose Animation > Keyframe Assistant > Convert Audio to Keyframes, and tie a subtle pulse to the generated amplitude. Keep the range narrow so the type breathes without wobbling.
  • Put text behind a subject. Adobe’s release notes say version 26.2 introduced an AI-powered Object Matte tool for one-click subject selection and tracking. Use it to mask a speaker and slide a word behind them for a depth effect.
  • Add depth to 3D text. Version 26.3 added depth of field in the Advanced 3D renderer, covering 3D text and shape layers. A shallow focus on a background word makes the foreground card read first.
  • Use the new guide tools. According to Adobe’s release notes, 26.5 added percentage-based positioning, edge pinning and custom guide colors. Percentage values keep a layout correct when you switch between 16:9 and 9:16 compositions.
  • Package it for reuse. Turn the card into a precomp and expose the text and colors in the Essential Graphics panel, so teammates can swap words without opening the layers.
  • Treat the AI Assistant as optional. Adobe documents an After Effects AI Assistant in beta, with custom skills. It is under test, so keep your core build manual and use the assistant only for experiments.
// Scale expression driven by audio amplitude (after Convert Audio to Keyframes)
amp = thisComp.layer("Audio Amplitude").effect("Both Channels")("Slider");
s = linear(amp, 0, 30, 100, 108);
[s, s]

Apply that expression to a held card’s Scale, or to a separate background shape, never to a card that is also running its entrance. Two systems fighting over Scale cause a visible stutter. Most of the best-looking pieces keep the type calm and let a background element carry the beat.

Two last habits help on every project. Save the project with a version number before each major change, such as KT_Main_v03. And render a 5-second test of the busiest section before you commit to a full render, so you catch blur, aliasing or timing problems while they are cheap to fix.

Before you render

What frame rate should I use for kinetic typography?

Match the rest of your video. This guide uses 30 fps because 120 BPM then lands on 15 frames per beat. If the rest of your channel is 24 fps, pick a tempo that divides cleanly, such as 120 BPM at 24 fps for 12 frames per beat.

How long should each word stay on screen?

Give each card a hold that grows with its word count, then add the entrance and exit. A two-word card therefore needs more total time than a one-word card. Give slow music or unfamiliar words more time.

Is After Effects or CapCut better for a first attempt?

CapCut gets you to a readable result faster because the presets handle the easing. After Effects takes longer but gives you per-character control, expressions and reusable scripts. If you only need one quote card, start in CapCut. If you want a system you can reuse for years, learn After Effects.

Can I make kinetic typography for free?

Yes, with limits. CapCut has a Free tier at US$0 that covers basic editing and templates, though export limits and features vary by account and region. Adobe reportedly offers a 7-day After Effects trial through Creative Cloud, and the paid After Effects plan is listed at US$22.99 per month on an annual plan billed monthly.

How do I sync text to music?

Find the tempo, convert beats to frames and place each in point on a beat marker. At 120 BPM and 30 fps, every beat is 15 frames. Nudge cards 2 or 3 frames early if they feel late.

What export settings should I use for upload?

Export a master first, then encode H.264 MP4 at yuv420p with CRF 16 to 18 and AAC audio at 192k, and verify the result with ffprobe. These are working defaults. Check the target platform’s own specs page for size, length and bitrate limits before you upload.

How do I make a vertical version?

Build a new 1080×1920 composition, bring in the text layers, shorten lines and split phrases over two or three lines. Keep type inside the safe area for the platform. A center crop works only as a quick fallback.

More from the Vipid blog

Make it with Vipid

Ines Calder

Titles & Motion Editor · Vipid Team

Ines Calder is the Titles & Motion Editor at Vipid, covering lower thirds, title sequences, kinetic typography and logo animation across After Effects, Premiere Pro, DaVinci Resolve and Final Cut Pro. She writes her guides in frames and safe areas so they hold up on a phone as well as a TV, and every template she lists carries its editor version, plugin needs and licence.

All articles by Ines Calder ›   How we check tools ›

Keep reading

Animated Logo Formats [2026]: 5 Compared by Use
Logo Animation

Animated Logo Formats [2026]: 5 Compared by Use

Ines Calder·3 Nov 2026
Auto Captions in 5 Editors [2026]: $0 vs $22.99/mo
Lower Thirds & Titles

Auto Captions in 5 Editors [2026]: $0 vs $22.99/mo

Ines Calder·2 Nov 2026
How to Make Lower Thirds [2026]: 10 Steps, 20 Min
Lower Thirds & Titles

How to Make Lower Thirds [2026]: 10 Steps, 20 Min

Ines Calder·30 Oct 2026

Blog

Intros & Templates
Titles & Motion
Streaming
Editing & Export
AI Video

Vipid

About Vipid
Themes
News archive 2011–2016
Vipid Team

Editorial

Editorial policy
How we check tools
Corrections

Legal

Privacy policy
Terms of service
Making video intros since 2010.
The Vipid blog covers the tools behind them.