Skip to content

feat: add keystroke captions and overlays for recorded videos#719

Open
pkazmier wants to merge 5 commits into
charmbracelet:mainfrom
pkazmier:caption-overlay
Open

feat: add keystroke captions and overlays for recorded videos#719
pkazmier wants to merge 5 commits into
charmbracelet:mainfrom
pkazmier:caption-overlay

Conversation

@pkazmier
Copy link
Copy Markdown

@pkazmier pkazmier commented Mar 10, 2026

Introduces a caption system that burns keystroke overlays into video output using ASS subtitles via ffmpeg. Captions are enabled / disabled via CaptionOn and CaptionOff commands. Captions are configured via Set commands (CaptionFont, CaptionFontSize, CaptionKeyStyle, CaptionAlignment, etc.) and support "vim" and "icon" key rendering styles, customizable colors/positioning, and controls for max keys shown as well as an inactivity timeout.

Caption Settings

CaptionFont

Set CaptionFont "JetBrains Mono"
CaptionOn

set-caption-font-jetbrains

Set CaptionFont "IBM Plex Mono"
CaptionOn

set-caption-font-ibmplex

CaptionFontSize

Set CaptionFontSize 18
CaptionOn

set-caption-font-size-18

Set CaptionFontSize 26
CaptionOn

set-caption-font-size-26

CaptionMaxKeys

Set CaptionMaxKeys 5
CaptionOn

set-caption-max-keys-5

Set CaptionMaxKeys 15
CaptionOn

set-caption-max-keys-15

CaptionInactivityTimer

Set CaptionInactivityTimer 900ms
CaptionOn

set-caption-inactivity-timer-900

Set CaptionInactivityTimer 1200ms
CaptionOn

set-caption-inactivity-timer-1200

CaptionFontColor

Set CaptionFontColor "#FF893E"
CaptionOn

set-caption-font-color

CaptionHighlightColor

Set CaptionHighlightColor "#77FFEF"
CaptionOn

set-caption-highlight-color

CaptionKeyStyle

Set CaptionKeyStyle "icon"
CaptionOn

set-caption

Set CaptionKeyStyle "vim"
CaptionOn

set-caption-key-style

CaptionBoxColor

Set CaptionBoxColor "#777777"
CaptionOn

set-caption-box-color

CaptionBoxOpacity

Set CaptionBoxOpacity 0
CaptionOn

set-caption-box-opacity-0

Set CaptionBoxOpacity 0.25
CaptionOn

set-caption-box-opacity-25

Set CaptionBoxOpacity 0.75
CaptionOn

set-caption-box-opacity-75

CaptionBoxPadding

Set CaptionBoxPadding 3
CaptionOn

set-caption-box-padding-3

Set CaptionBoxPadding 15
CaptionOn

set-caption-box-padding-15

CaptionAlignment

Set CaptionAlignment "bottom-right"
CaptionOn

set-caption-alignment-bottom-right

I have demos for all of the positions as well: top-left, top-center, top-right, middle-left, middle-center, middle-right, bottom-left, bottom-center, and bottom-right.

CaptionMargin

Set CaptionAlignment "bottom-right"
Set CaptionPadding 10
Set CaptionMarginVertical 10
Set CaptionMarginRight 10
CaptionOn

set-caption-margin

@pkazmier pkazmier requested a review from a team as a code owner March 10, 2026 00:23
@pkazmier pkazmier requested review from aymanbagabas and raphamorim and removed request for a team March 10, 2026 00:23
@pkazmier
Copy link
Copy Markdown
Author

I’m more than happy to update the README as well, but before doing so, I wanted to wait to see if there was interest. It took almost 4 hours to just write the demos and PR text itself.

@pkazmier pkazmier mentioned this pull request Mar 10, 2026
Introduces a caption system that burns keystroke overlays into video
output using ASS subtitles via ffmpeg. Captions are configured through
the tape DSL with Set commands (CaptionFont, CaptionFontSize,
CaptionStyle, CaptionAlignment, etc.) and support "vim" (plain text) and
"icon" (requires a nerd font) key rendering styles, customizable
colors/positioning, and an inactivity timeout.
@pkazmier pkazmier force-pushed the caption-overlay branch 2 times, most recently from 62b8ac8 to f288da1 Compare March 10, 2026 15:56
@pkazmier
Copy link
Copy Markdown
Author

pkazmier commented Mar 10, 2026

I've also incorporated an Overlay command (similar to #716), but the implementation uses the same ASS subtitle features as the keystroke captioning, so it's a consistent look and feel to the captioning of keypresses. Likewise, the configuration of such has many of the same configuration options:

// OverlayOptions holds configuration for text overlays.
type OverlayOptions struct {
	Font           string
	FontSize       int
	Alignment      CaptionAlignment
	FontColor      string // #RRGGBB hex
	BoxColor       string // #RRGGBB hex
	BoxOpacity     float64
	BoxPadding     int
	MarginLeft     int
	MarginRight    int
	MarginVertical int
}

Demo

Overlay

Set OverlayAlignment "top-right"
CaptionOn

# Set up line editing to demo control keys
Hide
Type "bindkey -e"
Enter
Ctrl+l
Show

Type "echo Hello, Planet"
Sleep 0.5s
Enter
Sleep 2s
Overlay@10s "Demo of Command Line Editing"
Sleep 1s
Ctrl+p
Sleep 1.5s
Ctrl+w
Sleep 1.1s
Type "World"
Enter
Sleep 2s

set-caption-with-overlay

Overlay with Multiline

Overlay@10s "Let's now edit\Nthe prior command\Nto show the world!"

set-caption-with-overlay-multiline

Overlay Title Tucked into Corner

Set OverlayAlignment "top-right"
Set OverlayBoxColor "#ffffff"
Set OverlayBoxOpacity 1
Set OverlayFontColor "#000000"
Set OverlayMarginRight 10
Set OverlayMarginVertical 10
CaptionOn
...

set-caption-with-overlay-title

Overlay without Captions

Of course you can use Overlays without captions:

Set OverlayAlignment "top-right"
Set OverlayBoxColor "#ffffff"
Set OverlayBoxOpacity 1
Set OverlayFontColor "#000000"
Set OverlayAlignment "bottom-right"
Set OverlayMarginRight 10
Set OverlayMarginVertical 10

set-caption-with-overlay-title

@pkazmier pkazmier changed the title feat: add keystroke caption overlay for recorded videos feat: add keystroke captions and overlays for recorded videos Mar 10, 2026
Introduce a new `Overlay[@duration] "text"` tape command that displays
styled text overlays at specific points during playback, independent of
keystroke captions. Includes configurable Set options for font, color,
alignment, margins, box opacity/padding, and multiline support via \N.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@domenkozar
Copy link
Copy Markdown

Can Captions be turn off and on between other commands?

@pkazmier
Copy link
Copy Markdown
Author

Can Captions be turn off and on between other commands?

Currently, they are disabled in Hide blocks and re-enabled in Show blocks. But I could create a CaptionShow and CaptionHide command that does the same if you think it would be useful.

@pkazmier
Copy link
Copy Markdown
Author

Can Captions be turn off and on between other commands?

I've just updated my PR, which adds CaptionOn and CaptionOff commands. This allows users fine grained control over when to use and not use captions. As before, captioning is off by default and is is disabled in Hide / Show blocks. I've removed the old Set Caption true global setting in favor of the new commands.

Here is a demo showing selective captioning as well as an overlay title:

Set OverlayAlignment "top-right"
Set OverlayBoxColor "#ffffff"
Set OverlayBoxOpacity 1
Set OverlayFontColor "#000000"
Set OverlayMarginRight 10
Set OverlayMarginVertical 10

Overlay@100s "Selective Captioning"

CaptionOn
Type "echo captions are enabled"
Enter
Sleep 2s

CaptionOff
Type "echo captions are disabled"
Enter
Sleep 2s

CaptionOn
Type "echo captions are re-enabled"
Sleep 2s

set-caption-toggle-captions

@pkazmier
Copy link
Copy Markdown
Author

pkazmier commented Mar 11, 2026

Comments for the maintainers:

  • Captions are enabled via CaptionOn. By default, they are disabled.
  • Captions are disabled via CaptionOff.
  • Captions are disabled during Hide / Show blocks.
  • Overlay titles are added via Overlay[@5s] "place your text here". Without time specification, default is 3 seconds.
  • The implementation of captions and overlay titles uses ASS v4+ subtitle specification, which requires ffmpeg to be compiled with libass library only if the tape file uses captions or overlays.
  • I did not update the README in the PR (yet). I wanted to get feedback before doing so. Would you like me to include all of the demos I showcased in this PR?
  • I used Claud Opus 4.6 to assist in the development of this feature.

Thanks for your consideration.

This change eliminates the global "Set Caption true" setting. This was
used to enable captions, but it was global. Feedback from another user
suggested it would be nice to be able to enable and disable captioning
selectively. Thus this change.
@pkazmier
Copy link
Copy Markdown
Author

pkazmier commented Mar 11, 2026

If this gets merged, I have another one almost ready to go that adds audio capabilities. Teaser:

Set CaptionAudio "thock"
Set CaptionAudioVolume 0.15
Set OverlayFontColor "#c6a0f6"
Set OverlayBoxOpacity 0

CaptionOn

Overlay@4s "Keypress Audio Demo"
Type "You should hear audio as this is captioned."
Sleep 2s
Ctrl+u

Overlay@4s "Audio Overlay Demo"
Set AudioVolume 1.0
Audio examples/settings/audio-overlay-demo.m4a
Type "You can play arbitrary audio files in the video."
Sleep 2s
set-caption-with-audio-overlay-title.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants