Configuring StreamUP ProText
by StreamUP
Version: 0.0.4
A text source for OBS that actually lets you style things. Bold, colours, gradients, animations, live countdowns, Google Fonts. All rendered natively inside OBS. No browser sources. No external services. Just type tags, get styled text.
If you've ever tried to make good-looking text overlays in OBS, you know the pain. This fixes that.
Requires OBS 31.0 or newer
Used to be called StreamUP BBCode?
Same plugin, new name. Existing BBCode sources in your scenes keep working exactly as they were, they just show up as ProText now. Streamer.bot actions using the old WebSocket vendor name carry on untouched too.
How the tags work
ProText uses simple square-bracket tags, the same style you might know from forum BBCode.
[b]this is bold[/b]Opening tag, your text, closing tag. That's it.
You can nest them too. Want bold red text? Just wrap one inside the other.
[b][color=#ff4444]Bold and red[/color][/b]Add an animation and it comes to life.
[rainbow speed=2]Colourful streaming text[/rainbow]Adding the Source
- In your scene, click + under Sources
- Select StreamUP ProText from the list
- Hit Open Editor and type your text with tags
The properties panel is deliberately small: Open Editor, Restart Animations, Media Cache, and Send Feedback. Everything else lives in the editor.
ProText Editor
Click Open Editor in the source properties. This opens a standalone editor that's a lot easier to work with than a small text box, and everything you change shows in OBS live.
What you get:
- Syntax highlighting that colour-codes your tags, variables, and presets
- Tag autocomplete. Type
[and a list of every tag pops up, filtering as you type. Pick one and it drops in the full tag with sensible defaults, closing tag included, cursor ready in the middle. Type[/and it lists just the tags you still have open, innermost first. Enter or Tab to accept, Esc to dismiss. - Live tag windows. Double-click a tag in your text and its window opens. Every slider drag, every colour change shows in OBS in real time. Done keeps it, Cancel backs the whole thing out.
- Toolbar with buttons for bold, italic, underline, font, colour, size, plus undo, redo, and a replay button for one-shot effects
- Sidebar rail with one button per tag category: Format, Colours, Styling, Animations, Effects, Special. Search looks across everything regardless of which section you're in.
- Style page with every per-source setting: font, default colour, antialiasing, custom size, padding, line spacing
- Presets section with one card per preset and an Apply button, plus a Manage Presets window for add, edit, delete, import, and export
- Variables section to view, add, edit, and delete your global variables without leaving the editor
- Our own colour picker for
[color],[bg], and[highlight], and a gradient designer with draggable stops for[gradient] - Font picker covering your local fonts plus the full Google Fonts catalog, roughly 1900 families with category filters
- Find and Replace with Ctrl+F
The editor is its own window with its own taskbar entry. It survives closing the source properties, and so does the tag reference, so you can keep both open while you work.
Quick Example
Hello [b]World[/b]!
[color=#ff0000]Red[/color] [i]italic[/i]
[wave amp=30 freq=4]Wavy[/wave]
[rainbow speed=2]Rainbow[/rainbow]Bold, colour, a wave animation, and rainbow cycling. All in one source.
Tags
81 tags across 8 categories. Here's all of them.
TIP
The previews below use the exact same animation maths as the plugin. What you see here is what you get in OBS.
Formatting
Bold, Italic, Underline, Strikethrough
The basics. Wrap your text and it does what you'd expect.
[b]Bold text[/b]
[i]Italic text[/i]
[u]Underlined[/u]
[s]Struck through[/s]Font Family
Change the font for a section of text. Uses any font installed on your system.
[font=Georgia]Georgia font[/font]
[font=Impact]Impact font[/font]Font Size
Set the size in pixels. Range is 1 to 500. There are also [big] and [small] shortcuts.
[size=72]Big text[/size]
[size=12]Small text[/size]
[big]1.5x bigger[/big]
[small]0.67x smaller[/small]Subscript and Superscript
H[sub]2[/sub]O
E=mc[sup]2[/sup]Monospace
[code]fixed-width text[/code]
[tt]same thing[/tt]Drop Cap
Makes the first character large, spanning multiple lines. Good for story intros or title cards.
[dropcap]Once upon a time...[/dropcap]
[dropcap lines=4]Text[/dropcap]
[dropcap dir=up]Raised cap instead[/dropcap]| Parameter | Default | What It Does |
|---|---|---|
lines | 3 | How many lines the dropped cap spans |
dir | down | up flips it into a raised cap: the big letter sits on the first line's baseline and rises above it, no wrap-around |
Google Fonts
Use any Google Font, the full catalog of roughly 1900 families. The plugin downloads and caches them automatically the first time.
[gfont=Lobster]Fancy text[/gfont]
[gfont=Permanent Marker]Marker text[/gfont]No setup needed. Just type the font name, or browse the editor's font picker, it covers the whole catalog with category filters and live previews.
INFO
Roughly 1900 Google Fonts are available. The plugin downloads and caches them automatically on first use, into a cache shared with the StreamUP Chat plugin.
Colours
Named Colours
Over 140 colour names are supported. Case doesn't matter, underscores and hyphens are optional.
[color=red]Red text[/color]
[color=dodgerblue]Blue text[/color]
[color=coral]Coral text[/color][colour] works too. Proper spelling.
Click to expand full color list
| Color | Hex | Color | Hex |
|---|---|---|---|
aliceblue | #F0F8FF | antiquewhite | #FAEBD7 |
aqua | #00FFFF | aquamarine | #7FFFD4 |
azure | #F0FFFF | beige | #F5F5DC |
bisque | #FFE4C4 | black | #000000 |
blanchedalmond | #FFEBCD | blue | #0000FF |
blueviolet | #8A2BE2 | brown | #A52A2A |
burlywood | #DEB887 | cadetblue | #5F9EA0 |
chartreuse | #7FFF00 | chocolate | #D2691E |
coral | #FF7F50 | cornflowerblue | #6495ED |
cornsilk | #FFF8DC | crimson | #DC143C |
cyan | #00FFFF | darkblue | #00008B |
darkcyan | #008B8B | darkgoldenrod | #B8860B |
darkgray | #A9A9A9 | darkgreen | #006400 |
darkkhaki | #BDB76B | darkmagenta | #8B008B |
darkolivegreen | #556B2F | darkorange | #FF8C00 |
darkorchid | #9932CC | darkred | #8B0000 |
darksalmon | #E9967A | darkseagreen | #8FBC8F |
darkslateblue | #483D8B | darkslategray | #2F4F4F |
darkturquoise | #00CED1 | darkviolet | #9400D3 |
deeppink | #FF1493 | deepskyblue | #00BFFF |
dimgray | #696969 | dodgerblue | #1E90FF |
firebrick | #B22222 | floralwhite | #FFFAF0 |
forestgreen | #228B22 | fuchsia | #FF00FF |
gainsboro | #DCDCDC | ghostwhite | #F8F8FF |
gold | #FFD700 | goldenrod | #DAA520 |
gray | #BEBEBE | green | #00FF00 |
greenyellow | #ADFF2F | honeydew | #F0FFF0 |
hotpink | #FF69B4 | indianred | #CD5C5C |
indigo | #4B0082 | ivory | #FFFFF0 |
khaki | #F0E68C | lavender | #E6E6FA |
lavenderblush | #FFF0F5 | lawngreen | #7CFC00 |
lemonchiffon | #FFFACD | lightblue | #ADD8E6 |
lightcoral | #F08080 | lightcyan | #E0FFFF |
lightgoldenrod | #FAFAD2 | lightgray | #D3D3D3 |
lightgreen | #90EE90 | lightpink | #FFB6C1 |
lightsalmon | #FFA07A | lightseagreen | #20B2AA |
lightskyblue | #87CEFA | lightslategray | #778899 |
lightsteelblue | #B0C4DE | lightyellow | #FFFFE0 |
lime | #00FF00 | limegreen | #32CD32 |
linen | #FAF0E6 | magenta | #FF00FF |
maroon | #B03060 | mediumaquamarine | #66CDAA |
mediumblue | #0000CD | mediumorchid | #BA55D3 |
mediumpurple | #9370DB | mediumseagreen | #3CB371 |
mediumslateblue | #7B68EE | mediumspringgreen | #00FA9A |
mediumturquoise | #48D1CC | mediumvioletred | #C71585 |
midnightblue | #191970 | mintcream | #F5FFFA |
mistyrose | #FFE4E1 | moccasin | #FFE4B5 |
navajowhite | #FFDEAD | navy | #000080 |
navyblue | #000080 | oldlace | #FDF5E6 |
olive | #808000 | olivedrab | #6B8E23 |
orange | #FFA500 | orangered | #FF4500 |
orchid | #DA70D6 | palegoldenrod | #EEE8AA |
palegreen | #98FB98 | paleturquoise | #AFEEEE |
palevioletred | #DB7093 | papayawhip | #FFEFD5 |
peachpuff | #FFDAB9 | peru | #CD853F |
pink | #FFC0CB | plum | #DDA0DD |
powderblue | #B0E0E6 | purple | #A020F0 |
rebeccapurple | #663399 | red | #FF0000 |
rosybrown | #BC8F8F | royalblue | #4169E1 |
saddlebrown | #8B4513 | salmon | #FA8072 |
sandybrown | #F4A460 | seagreen | #2E8B57 |
seashell | #FFF5EE | sienna | #A0522D |
silver | #C0C0C0 | skyblue | #87CEEB |
slateblue | #6A5ACD | slategray | #708090 |
snow | #FFFAFA | springgreen | #00FF7F |
steelblue | #4682B4 | tan | #D2B48C |
teal | #008080 | thistle | #D8BFD8 |
tomato | #FF6347 | turquoise | #40E0D0 |
violet | #EE82EE | webgray | #808080 |
webgreen | #008000 | webmaroon | #800000 |
webpurple | #800080 | wheat | #F5DEB3 |
white | #FFFFFF | whitesmoke | #F5F5F5 |
yellow | #FFFF00 | yellowgreen | #9ACD32 |
Hex Colours
Use #RGB or #RRGGBB format.
[color=#FF6B00]Orange[/color]
[color=#00ff88]Mint[/color]Opacity
Set how transparent text is. 0.0 is invisible, 1.0 is fully visible.
[opacity=0.5]Half visible[/opacity]
[opacity=0.25]Very faded[/opacity]Background Highlight
Add a coloured background behind your text. Works with colour names or hex values.
[bg=yellow]Highlighted[/bg]
[bg=#FF6B6B]Red background[/bg]
[highlight=#6bcb77]Green highlight[/highlight]Gradient
Colour gradient across your text. Supports horizontal, vertical, and multi-stop gradients.
Double-click [gradient] in the editor's Colours section and you get a proper gradient designer: a live gradient bar you click to add stops, drag to move them, with a colour picker for whichever stop is selected. The source updates as you tweak. The tag syntax below is what it writes for you.
[gradient from=red to=blue]Gradient text[/gradient]
[gradient from=red to=blue dir=vertical]Vertical[/gradient]
[gradient stops="red 0%,gold 50%,blue 100%"]Multi-stop[/gradient]Multi-stop gradients show on static text. Animated tags blend between the two end colours.
| Parameter | What It Does |
|---|---|
from | Starting colour (name or hex) |
to | Ending colour |
dir | horizontal (default) or vertical |
stops | Multi-stop colours: "red 0%,gold 50%,blue 100%" |
Styling
Outline
Stroke around each character. Good for making text readable over busy backgrounds.
[outline color=black size=3]Outlined text[/outline]| Parameter | Default | What It Does |
|---|---|---|
color | black | Outline colour |
size | 2 | Thickness in pixels (1-20) |
Shadow
Drop shadow behind text. Adjust the colour and offset.
[shadow color=black x=3 y=3]Shadowed text[/shadow]| Parameter | Default | What It Does |
|---|---|---|
color | gray | Shadow colour |
x | 2 | Horizontal offset (pixels) |
y | 2 | Vertical offset (pixels) |
Glow
Soft halo around text. Great for neon-style effects.
[glow color=gold size=8]Glowing text[/glow]| Parameter | What It Does |
|---|---|
color | Glow colour |
size | Glow radius in pixels (1-30) |
Letter Spacing
Extra space between characters.
[spacing=10]Spaced out text[/spacing]Text Alignment
Align text left, centre, or right within the source width.
[align=center]Centred text[/align]
[center]Shortcut[/center]
[left]Left[/left]
[right]Right[/right]
[justify]Justified[/justify]Indent
Push text in from the left edge. Default is 40 pixels.
[indent=60]Indented text[/indent]40px indent
80px indent
Horizontal Rule
A simple divider line across the full width.
Text above
[hr]
Text below
[hr thickness=6 color=gold]| Parameter | Default | What It Does |
|---|---|---|
thickness | 2 | Line thickness in pixels |
color | text colour | Line colour |
Text below
Box
Put a border around text. Add rounded corners, padding, whatever you need.
[box border=2 color=white padding=10]Boxed text[/box]
[box border=2 color=gold radius=10 padding=10]Rounded box[/box]| Parameter | Default | What It Does |
|---|---|---|
border | 2 | Border thickness in pixels |
color | white | Border colour |
padding | 10 | Space between the text and the border (inside) |
margin | 0 | Space outside the border, in pixels. Stops the box butting up against whatever sits next to it |
radius | 0 | Corner rounding in pixels. Crank it up and the box becomes a proper pill, it caps itself at half the box height so it never distorts |
Blur
Blurs the text. Higher number means blurrier. Range 1-20.
[blur=3]Blurry text[/blur]Texture
Fills your text shape with an image file. Point it at a local image path.
[texture image=wood.jpg]Textured[/texture]
[texture image=wood.jpg mode=tile scale=50]Tiled at half size[/texture]| Parameter | Default | What It Does |
|---|---|---|
image | Image file path | |
mode | stretch | stretch squashes to the text box, fit preserves aspect and contains, fill preserves aspect and crops to cover, tile repeats at natural size |
scale | 100 | Percent scale of the source image for tile, fit, and fill |
Textures apply to static text only. Animated tags take a different render path.
Mask
Clips text to a mask image based on luminance. White areas show the text, black areas hide it, greys are partial.
[mask image=shape.png]Masked text[/mask]Masks apply to static text only, same as textures.
Word Wrap
Forces a specific wrap mode. You rarely need this. With Custom Size turned on, the plugin auto-wraps text and emotes at the source boundary, preferring word boundaries and falling back to character breaks. Only reach for [wrap] if you want to override the default word-first behaviour with char mode.
[wrap=word]Long text that wraps at word boundaries[/wrap]
[wrap=char]Wraps mid-character if needed[/wrap]Animations
All animations run per-character with a staggered offset, so they ripple across the text naturally.
Wave
Characters float up and down in a sine wave pattern.
[wave amp=50 freq=5]Wavy text[/wave]| Parameter | Default | What It Does |
|---|---|---|
amp | 50 | Wave height. 50 moves characters about 10px up and down |
freq | 5 | Wobble rate in radians per second. 6.3 = one full wave per second |
Bounce
Characters hop up and down. Think bouncing ball.
[bounce amp=20 freq=3]Bouncy text[/bounce]| Parameter | Default | What It Does |
|---|---|---|
amp | 20 | Hop height in pixels |
freq | 1 | Hops per second (Hz) |
Shake
Random jitter on each character. Good for "danger" or "error" text.
[shake rate=20 intensity=5]Shaky text[/shake]| Parameter | Default | What It Does |
|---|---|---|
rate | 20 | Jitter rate in radians per second. 6.3 = one full cycle per second |
intensity | 5 | How far it moves in pixels |
The old level parameter still works as an alias for intensity, so existing sources carry on as they were.
Pulse
Characters grow and shrink rhythmically.
[pulse freq=1 intensity=0.5 ease=-2]Pulsing text[/pulse]| Parameter | Default | What It Does |
|---|---|---|
freq | 1 | Pulses per second (Hz) |
intensity | 0.5 | Pulse depth, 0.0 to 1.0. Text shrinks to (1 - intensity) of full size, so 0.5 dips to half size and 0.2 gives a subtle breathe |
ease | -2 | Easing curve (negative = smooth in-out) |
Tornado
Characters orbit in circles around their position.
[tornado radius=10 freq=1]Spinning text[/tornado]| Parameter | Default | What It Does |
|---|---|---|
radius | 10 | Circle size in pixels |
freq | 1 | Orbits per second |
Rainbow
Characters cycle through rainbow colours. Each character is offset so it looks like a moving gradient.
[rainbow speed=1]Rainbow text[/rainbow]| Parameter | Default | What It Does |
|---|---|---|
speed | 1 | Colour cycle rate. 1 = a full trip round the colour wheel every 3.6 seconds |
Rotate
Each character spins on its own axis.
[rotate speed=45]Spinning[/rotate]| Parameter | Default | What It Does |
|---|---|---|
speed | 45 | Degrees per second. Negative spins anti-clockwise |
Blink
Characters blink on and off. Classic.
[blink freq=2]Blinking text[/blink]| Parameter | Default | What It Does |
|---|---|---|
freq | 2 | Blinks per second |
Flip
Characters squish and mirror on an axis. All characters flip together.
[flip axis=x speed=1]Flipping text[/flip]
[flip axis=y speed=1]Flipping text[/flip]| Parameter | Default | What It Does |
|---|---|---|
axis | x | Flip axis: x, y, or both (squashes on both at once) |
angle | 0 | Tilt the flip axis in degrees. angle=45 flips diagonally |
speed | 1 | Flips per second. Decimals work, 0.25 is one flip every 4 seconds |
Metallic
A shiny metallic sheen that sweeps across text. Looks best with a gold or silver base colour.
[metallic speed=2]Metallic text[/metallic]
[metallic speed=2][color=gold]Gold sheen[/color][/metallic]| Parameter | Default | What It Does |
|---|---|---|
speed | 2 | Sheen rate. 2 = one sweep every 1.5 seconds (a sweep takes 3 ÷ speed seconds) |
Effects
These are one-shot or ongoing visual effects. Some loop, some play once.
Typewriter
Characters appear one at a time, like someone is typing them. Optional blinking cursor, line or block style.
[typewriter speed=8 cursor=1 loop=1]Typing text[/typewriter]
[typewriter speed=8 cursor=3]Block cursor[/typewriter]| Parameter | Default | What It Does |
|---|---|---|
speed | 8 | Characters revealed per second |
cursor | 0 | Cursor style, see below |
loop | 0 | Seconds to wait before restarting (0 = play once) |
Cursor styles:
| Value | Style |
|---|---|
0 | No cursor |
1 | Line cursor | while typing |
2 | Line cursor that keeps blinking after typing finishes |
3 | Block cursor █ while typing |
4 | Block cursor that keeps blinking after typing finishes |
Hacker
Characters scramble through random letters before revealing the real text, left to right.
[hacker speed=4 loop=2]Decoding text[/hacker]| Parameter | Default | What It Does |
|---|---|---|
speed | 4 | Characters revealed per second |
loop | 2 | Seconds to wait before restarting (0 = no loop) |
Glitch
Random characters get temporarily replaced with junk. Looks like corrupted data.
[glitch rate=5 intensity=1]Glitchy text[/glitch]| Parameter | Default | What It Does |
|---|---|---|
rate | 5 | Glitch events per second |
intensity | 1 | How much text gets corrupted (0.0 to 1.0) |
Fade
Text gradually fades out from a starting point.
[fade start=0 length=12]Fading text[/fade]| Parameter | Default | What It Does |
|---|---|---|
start | 0 | Character position where fade begins |
length | 12 | How many characters it fades across |
Slide
Text slides in from off-screen and settles into place.
[slide dir=left speed=80]Sliding in[/slide]| Parameter | Default | What It Does |
|---|---|---|
dir | left | Which edge the text slides in from. dir=right starts off the right side and travels left into place |
speed | 80 | How quickly it settles. The slide is eased, so it is not a fixed px/sec. Rough guide: about 90% settled after 180 ÷ speed seconds, so speed=80 lands in just over 2 seconds |
Zoom
Text scales in from small to full size (or any range you set).
[zoom from=0 to=1 speed=2]Zoom in[/zoom]| Parameter | Default | What It Does |
|---|---|---|
from | 0 | Starting scale (0 = invisible) |
to | 1 | Final scale (1 = normal) |
speed | 2 | Zoom rate. The zoom completes in 1 ÷ speed seconds, so speed=2 finishes in half a second |
Scroll / Marquee
Scrolling text that moves horizontally. Like a news ticker.
[scroll speed=80]Breaking news: text goes here[/scroll]
[marquee speed=60]Same thing, different name[/marquee]| Parameter | Default | What It Does |
|---|---|---|
speed | 80 | Scroll speed in pixels per second |
Credits
Scrolls all content upward like movie end credits. Set your source to Custom Size in the Layout settings to define the visible window, and the text scrolls up through it.
[credits speed=50]
[center][size=48][b]THE END[/b][/size][/n]
[/n]
Producer[/n]
[color=gold]StreamUP[/color][/n]
[/n]
Special Thanks[/n]
[color=gold]Everyone watching[/color][/center]
[/credits]| Parameter | Default | What It Does |
|---|---|---|
speed | 50 | Scroll speed in pixels per second |
loop | true | Loop back to the start when done (true or false) |
Content starts below the viewport and scrolls up through it. Works with any tags inside. Colours, alignment, animations, all of it.
Set loop=false if you want it to stop at the end instead of looping back.
TIP
For a classic credits look, use [center] to centre-align everything and add [/n] newlines between sections.
Curve
Places text along a curved arc. Good for logos or decorative headers.
[curve radius=200 angle=180]Curved text[/curve]| Parameter | Default | What It Does |
|---|---|---|
radius | 200 | How big the arc is (pixels) |
angle | 180 | How far around the arc text goes (degrees) |
Matrix
Characters cycle through random symbols like the Matrix digital rain effect.
[matrix speed=10]Decode this[/matrix]| Parameter | Default | What It Does |
|---|---|---|
speed | 10 | How fast characters cycle |
Fire
Text flickers with warm fire colours.
[fire intensity=0.5]Burning text[/fire]| Parameter | Default | What It Does |
|---|---|---|
intensity | 0.5 | Fire strength (0.0 to 1.0) |
Electric
Sparks and displacement. Characters jitter with electric energy.
[electric freq=10 intensity=5]Zapping text[/electric]| Parameter | Default | What It Does |
|---|---|---|
freq | 10 | Sparks per second |
intensity | 5 | How far characters jump in pixels |
Dynamic Content
These tags update in real time. Countdowns count, clocks tick, variables change when you tell them to.
Countdown
Live countdown timer from a number of seconds. Displays as MM:SS.
[countdown=120]Counts down from 300 seconds (5 minutes) in real time.
Counter
Animated number that counts from one value to another over a set duration.
[counter from=0 to=1000 duration=5]
[counter from=0 to=99.9 duration=3 decimals=1]| Parameter | Default | What It Does |
|---|---|---|
from | 0 | Starting number |
to | 100 | Ending number |
duration | 5 | How many seconds to count over |
decimals | 0 | Decimal places to show |
Clock
Live system clock. Uses Qt time format strings. Supports timezones via the tz parameter using IANA timezone names.
[clock format="HH:mm:ss"]
[clock format="hh:mm AP"]
[clock format="HH:mm" tz="America/New_York"]
[clock format="HH:mm:ss" tz="Europe/London"]
[clock format="HH:mm" tz="Asia/Tokyo"]
[clock=HH:mm:ss tz=UTC]| Parameter | Default | Description |
|---|---|---|
format | HH:mm:ss | Time format string |
tz | (system) | IANA timezone name (e.g. America/New_York, Europe/London, UTC) |
Common formats: HH = 24h hours, hh = 12h hours, mm = minutes, ss = seconds, AP = AM/PM.
When tz is omitted, the clock uses your system's local timezone. Use any standard IANA timezone identifier -- you can find the full list at Wikipedia: List of tz database time zones.
Date
Live date display with named presets so you don't have to remember format strings. Uses the same rendering as [clock] under the hood.
[date]
[date=long]
[date=us]
[date=full tz=America/New_York]| Preset | Format | Example |
|---|---|---|
| (default) | yyyy-MM-dd | 2026-03-30 |
short | M/d/yy | 3/30/26 |
long | MMMM d, yyyy | March 30, 2026 |
iso | yyyy-MM-dd | 2026-03-30 |
us | MM/dd/yyyy | 03/30/2026 |
eu / uk | dd/MM/yyyy | 30/03/2026 |
written | ddd, MMM d yyyy | Mon, Mar 30 2026 |
full | dddd, MMMM d, yyyy | Monday, March 30, 2026 |
day | dddd | Monday |
month | MMMM yyyy | March 2026 |
year | yyyy | 2026 |
You can also pass a custom Qt date format string instead of a preset name. The tz parameter works here too, same as [clock].
Time
Live time display with named presets for 12-hour, 24-hour, and other common formats.
[time]
[time=12h]
[time=hours]
[time=military]
[time=12h tz=Europe/London]| Preset | Format | Example |
|---|---|---|
| (default) | HH:mm:ss | 14:30:45 |
12h / 12 | h:mm AP | 2:30 PM |
24h / 24 | HH:mm:ss | 14:30:45 |
short | h:mm AP | 2:30 PM |
long | h:mm:ss AP | 2:30:45 PM |
hours | HH:mm | 14:30 |
military | HHmm | 1430 |
minimal | h:mm | 2:30 |
seconds | HH:mm:ss | 14:30:45 |
Same deal as [date]. Named presets or custom format strings, with optional tz for timezone.
Time Since
Shows how long it's been since a given date or timestamp. Updates live every second. Good for stream uptime, event timers, "account age" displays, that sort of thing.
[timesince=2024-01-15 format=hms]
[timesince=January 15, 2024 format=clock]
[timesince date=1/15/2024 format=short]
[timesince epoch=1705320000 format=long]You can use pretty much any date format you want. ISO dates, written dates, US slash format, European dot format, whatever feels natural. A raw Unix epoch still works too if that's your thing. The format parameter controls how the elapsed time looks.
Accepted date formats:
2024-01-15or2024-01-15 12:00:00(ISO)January 15, 2024orJan 15, 2024(written)15 January 2024or15 Jan 20241/15/2024or01/15/2024(US slash)2024/01/15(year-first slash)15.01.2024(European dot)15-01-2024(European dash)1705320000(Unix epoch)
All of these work with or without a time component (e.g. Jan 15, 2024 2:30 PM).
| Preset | Example Output | What It Shows |
|---|---|---|
hms (default) | 2h 15m 30s | Hours, minutes, seconds. Auto-hides zero days/hours |
hm | 2h 15m | Same but no seconds |
clock | 02:15:30 | Digital clock style with zero-padding |
short | 2 hours ago | Biggest unit only, casual |
long | 2 hours, 15 minutes, 30 seconds | Full breakdown |
compact | 2:15:30 | Minimal, no labels |
days | 45d 2h 15m | Always shows days |
If the timestamp is far enough back, days are included automatically. The output scales to whatever makes sense for the duration.
Combine it with styling like anything else:
Stream uptime: [color=lime][timesince=2026-04-01T12:00:00 format=clock][/color]Random Words
Picks a random word from your list. Actually random, and it never shows the same word twice in a row.
[random words="Hello,Hi,Hey,Yo" speed=2]| Parameter | What It Does |
|---|---|
words | Comma-separated list of words to pick from |
speed | Word changes per second (default 2) |
Sequence
Same idea, but cycles through the list in order instead of picking randomly. First to last, then back round. Use this for countdowns, rotating messages, anything where order matters.
[sequence words="3,2,1,GO" speed=1]| Parameter | What It Does |
|---|---|
words | Comma-separated list of words, shown in order |
speed | Word changes per second (default 2) |
TIP
[random] used to behave like [sequence]. If you were relying on the old in-order cycling, swap your tag to [sequence] and it works exactly as before.
Variables
Placeholder that gets replaced when you set a value via WebSocket or the Variable Viewer. Useful for alerts, notifications, scoreboards, anything triggered by stream events.
Welcome [var=username] to the stream!Shows as {username} until a value is set. Variables are global, so setting one updates it across all ProText sources. They persist across OBS restarts.
Variable values support ProText tags. Set a variable to [b][color=red]Andi[/color][/b] and it renders as bold red text, not literal tags.
See the Variable Viewer section for managing variables in the UI, or the WebSocket section for setting them programmatically.
Inline Image
Display an image inline with your text.
[img src=C:/images/logo.png width=32 height=32]Emote Tags
Four provider tags pull emotes straight into your text by name. Twitch, 7TV, BetterTTV, and FrankerFaceZ all supported.
Twitch Emotes
[twitchemote=Kappa]
[twitchemote name=fallen643Bonk]
[twitchemote name=argickJam channel=argick]Works with global emotes, sub emotes, bit emotes, and channel emotes. If you know which channel owns the emote, pass channel= for a faster lookup. If you don't, the plugin figures it out on its own.
7TV
[7tv=PagMan]
[7tv name=peepoSit channel=forsen]BetterTTV
[bttv=KEKW]
[bttv name=monkaHmm channel=sodapoppin]FrankerFaceZ
[ffz=monkaS]
[ffz name=ZULUL channel=xqc]Sizing
Emotes render inline at text height by default. Override with size, width, or height if you want them bigger.
[twitchemote=Kappa size=64]
[7tv name=PagMan width=96 height=96]Badges
Twitch badges work through their own tag.
[badge=subscriber]
[badge name=moderator]See the Emotes section further down for how resolution, caching, and rate limits work under the hood.
Special Tags
Style Presets
Apply a saved preset by name. The editor's Presets section is the picker: one card per preset, hit Apply and the tag drops in at your cursor. Creating and editing happens in the Manage Presets window, opened from the bottom of the picker.
[use=alert]Warning text[/use]Save a preset called "alert" with tags like [color=red][b][shake], then use it anywhere with [use=alert]. Saves a lot of typing. Here's what a preset like that would look like:
The manager also does Import and Export, so you can back your presets up as JSON or share a preset pack with someone.
Presets can nest up to 10 levels deep and are shared across all ProText sources. A preset that references itself gets skipped with a warning rather than looping forever.
No Parse
Show ProText tags as plain text instead of rendering them.
[noparse][b]this stays as text[/b][/noparse]
[plain][i]same thing[/i][/plain]Without noparse, [b]text[/b] renders as:
With noparse, the tags are displayed literally as [b]bold text[/b] instead of being rendered.
Reset
Closes all open tags and goes back to default styling. Two ways to write it.
[b][color=red]Styled text[reset]Back to normal
[b]Bold[/all]Not boldEverything after [reset] or [/all] returns to default font, colour, and size.
Newline
Force a line break without pressing Enter.
Line 1[/n]Line 2Line 2
Combining Tags
You can stack as many tags as you want. Nest them inside each other and they all apply.
[rainbow][wave]Rainbow Wave[/wave][/rainbow]
[b][color=gold][metallic speed=2]Gold Sheen[/metallic][/color][/b]
[fire][shake rate=10 level=2]Fiery Shake[/shake][/fire]
[electric][color=#89b4fa]Electric Blue[/color][/electric]
[rainbow][bounce]Rainbow Bounce[/bounce][/rainbow]The order doesn't usually matter, but effects that move characters (wave, bounce, shake) should generally go on the outside, and colour/styling tags on the inside.
Global Tags
The Global Tags tab in the editor wraps all your text automatically. Type your opening tags and the closing tags are added for you.
Put [rainbow][wave] in Global Tags, and your entire text gets wrapped in [rainbow][wave]...[/wave][/rainbow].
This is useful when other tools (like WebSocket) are supplying the text content. You can apply effects without touching the text itself.
Emotes
Drop any Twitch, 7TV, BetterTTV, or FrankerFaceZ emote straight into your text by name. The plugin does the resolution work for you, caches aggressively, and plays nice with the upstream APIs.
How resolution works
Resolution runs in a background thread so the UI never blocks. For each emote the plugin walks a journey, stopping at the first hit.
- In-memory cache (hit: zero network)
- Persistent disk cache —
emote_urls.jsonsurvives OBS restarts - Local scan of every cached channel set — any emote belonging to a channel you've already fetched resolves for free
- Channel hint from the tag if you passed one
- rootonline.de exact-name search (Twitch only, returns the emote ID directly)
- ivr.fi direct lookup (Twitch only)
- Prefix fallback — extracts the emote prefix, searches Twitch GQL for the owning channel, fetches that channel's set
Once a channel has been fetched once, every future emote from it resolves locally.
Caching
- Channel emote sets cached for 7 days. Emote sets change rarely, so re-fetching every time is wasteful. Delete the relevant file in the emote cache folder to force a refresh.
- URL cache persists across restarts. Once an emote is resolved, it never gets looked up again.
- Atomic cache writes. If OBS crashes mid-save the file stays intact.
Rate limit behaviour
The plugin is polite to upstream APIs. Imagine 1000 streamers running it at the same time. It shouldn't hammer anything.
- Per-provider rate limiting. Every API has its own mutex, minimum request spacing, and 429 cooldown.
- Honours
Retry-After. If an API tells us to back off, we back off. - User-Agent identifies the plugin.
StreamUP-ProText/<version>so operators can contact or block us cleanly. - Duplicate dedupe. The same emote referenced 30 times in one text triggers one resolution, not 30.
| Provider | Min spacing | Why |
|---|---|---|
| ivr.fi | 500ms | Cloudflare-limited |
| rootonline.de | 1000ms | Personal server, gentlest |
| gql.twitch.tv | 500ms | Twitch official |
| 7tv.io | 200ms | 5000 req / 30s limit |
| api.betterttv.net | 200ms | Cloudflare-cached |
| api.frankerfacez.com | 300ms | Cloudflare-backed |
Cache locations
Everything lives in the shared StreamUP media cache, so ProText and the StreamUP Chat plugin download things once between them:
- Windows:
%LOCALAPPDATA%\obs-studio\cache\streamup\emotes\(fonts instreamup\fonts\) - Linux:
~/.cache/obs-studio/streamup/emotes/ - macOS:
~/Library/Caches/obs-studio/streamup/emotes/
You rarely need to touch the folder by hand. The Media Cache button in the source properties opens a window showing what's cached and how big it is, with clear buttons per category. If you do want to dig in: delete individual ivr_*.json files to refresh specific channels, delete emote_urls.json to force every emote to re-resolve, or wipe the whole folder to start fresh.
Auto-wrap for Custom Size
Turn on Custom Size in the properties and long emote spams wrap to the next line automatically. Images wrap as atomic units. Text splits at word boundaries first, character boundaries if there's nowhere else to break. No [wrap] tag needed.
Variables
The Variables section in the editor sidebar is where you manage all your global [var=name] variables in one place.
You can:
- See all variables and their current values at a glance
- Add new variables with name and value fields
- Insert a variable into your text with a click
- Delete variables you no longer need
Duplicate variable names are blocked. If you try to rename a variable to something that already exists, it won't save.
Variables persist across OBS restarts. They're saved to your plugin config directory automatically whenever you make a change.
TIP
Variable values support full ProText styling. Set a variable to [b][color=gold]VIP[/color][/b] and every [var=rank] in your text renders as bold gold "VIP". Useful for styled alerts without touching the source text.
Settings Reference
Source Properties
The properties panel is deliberately small. Four buttons:
- Open Editor - The ProText editor. Text, tags, styling, presets, variables, all of it.
- Restart Animations - Replays every animation and effect from the start. Handy for previewing one-shot effects like
[typewriter]while you tweak settings, since they only play once per activation. Also in the editor toolbar as a play button. - Media Cache - See everything StreamUP has downloaded (emotes, badges, fonts) and clear it to free up space. The cache is shared with the StreamUP Chat plugin.
- Send Feedback - Feature requests and bug reports, straight to us.
Editor Style Page
Per-source settings live on the editor's Style page:
- Font - Base font, size, and style. The picker covers local fonts and the full Google Fonts catalog, roughly 1900 families.
- Default Colour - Base text colour when no
[color]tag is active (default: white) - Antialiasing - Smooth text edges (on by default)
- Reset effects on activate - Restarts animations when the source becomes visible (on by default)
- Custom Size - Fixed width and height. Turning this on enables automatic word and emote wrapping so long content fits within the bounds.
- Auto Padding - Calculates padding automatically (on by default), or set left, right, top, bottom yourself
- Line Spacing - Extra space between lines. Negative overlaps them.
Text and Global Tags are the editor's two tabs: Standard is the text rendered on screen, Global Tags wraps everything automatically.
WebSocket
The plugin registers as a WebSocket vendor called streamup-protext using the obs-websocket 5.x API. This lets you control ProText sources from Streamer.Bot, scripts, or anything that connects to OBS WebSocket.
Legacy vendor name
The old streamup-bbcode vendor name is still registered and handles every request identically, so existing Streamer.bot setups keep working with no changes. New integrations should use streamup-protext.
set_text
Update the text on a source.
| Parameter | Required | What It Does |
|---|---|---|
sourceName | Yes | Name of your ProText source in OBS |
text | Yes | The new ProText text to display |
get_text
Get the current text from a source.
| Parameter | Required | What It Does |
|---|---|---|
sourceName | Yes | Name of your ProText source |
Returns text in the response.
set_global_tags
Update the global tags on a source.
| Parameter | Required | What It Does |
|---|---|---|
sourceName | Yes | Name of your ProText source |
tags | Yes | ProText tags to wrap everything in |
get_global_tags
Get the current global tags.
| Parameter | Required | What It Does |
|---|---|---|
sourceName | Yes | Name of your ProText source |
Returns tags in the response.
set_variable
Set a global variable. This is what powers [var=name] tags. The value is applied to all ProText sources that use that variable.
| Parameter | Required | What It Does |
|---|---|---|
name | Yes | Variable name (matches [var=name]) |
value | No | Value to display (empty clears the variable) |
get_variable
Get the current value of a global variable.
| Parameter | Required | What It Does |
|---|---|---|
name | Yes | Variable name to look up |
Returns value in the response.
reset_effects
Replays every animation and effect on a source from the start. Same as the Restart Animations button. Useful for re-triggering a one-shot [typewriter] or [slide] from a stream event.
| Parameter | Required | What It Does |
|---|---|---|
sourceName | Yes | Name of your ProText source |
Streamer.Bot Example
// Set text on a ProText source
CPH.ObsSendRaw("CallVendorRequest",
"{\"vendorName\":\"streamup-protext\"," +
"\"requestType\":\"set_text\"," +
"\"requestData\":{" +
"\"sourceName\":\"My ProText Source\"," +
"\"text\":\"[b]Hello[/b] [color=red]World[/color]\"" +
"}}", 0);
// Set a global variable (updates all ProText sources using [var=username])
CPH.ObsSendRaw("CallVendorRequest",
"{\"vendorName\":\"streamup-protext\"," +
"\"requestType\":\"set_variable\"," +
"\"requestData\":{" +
"\"name\":\"username\"," +
"\"value\":\"Andi\"" +
"}}", 0);
// Replay animations from the start
CPH.ObsSendRaw("CallVendorRequest",
"{\"vendorName\":\"streamup-protext\"," +
"\"requestType\":\"reset_effects\"," +
"\"requestData\":{" +
"\"sourceName\":\"My ProText Source\"" +
"}}", 0);Tips
Use the editor. Everything is in there: syntax highlighting, live tag windows, tag browser, styling, presets, variables. Open Editor in the source properties.
Nest tags freely. Bold, red, bouncing text is just [b][color=red][bounce]text[/bounce][/color][/b].
Use Global Tags for consistency. If every source should be the same font and colour, set it once in Global Tags instead of repeating it everywhere.
Save presets for things you reuse. If you keep typing [outline color=black size=2][shadow color=#000 x=2 y=2] on everything, save it as a preset and just use [use=my-style].
Copy tags from the reference. Right-click any tag in the Tag Reference sidebar to copy it. There are also "Copy Tag" and "Copy Syntax" buttons in the detail panel on the right.
Refresh on Active resets animations. Typewriter plays from the start every time you switch to a scene. Turn it off if you want animations to keep running in the background.