Motion · Ticker
Market ticker strip
Seamless scrolling ticker of symbols with logo, price and change — stocks, crypto or anything with a number. 1920×160 strip, 10 s loop.
Source: gimgs ↗ · CC0
When to use
A finance/news strip at the bottom of a video, a looping background for a market update, a dashboard header. The output is a 1920×160 strip: overlay it on 1080p footage with ffmpeg overlay=0:920.
How to adapt
- Fill
itemswith real data — prices and changes are plain strings so format them however the audience expects (€1.234,56,+0.8 %,▲ 2.4%). Anything whosechangestarts with-is coloureddown. - Logos: stock →
https://gimgs.net/stock/{tradingview slug}.svg(apple, microsoft, nvidia…; use/api/stock-search?q=to find the slug), crypto →/crypto/{ticker}.svg, brands →/brand-logo/{slug}.svg. Omitlogoto hide the circle. - 5–8 items fill the width nicely; the list is duplicated internally so the loop is seamless at any count.
- Speed: the rail travels half its width in
duration(10 s). More items = faster. Changewindow.motion.durationin the source for a slower loop.
Do not change
window.motion, #stage size, the rail's translateX(-50%) loop (that is what makes frame 0 and the last frame line up).
Everything on this page is also machine-readable. Point your agent at the JSON, or add the gimgs MCP server and ask it to search motion templates.
- Fetch the JSON — it contains the prompt, the param schema and the full source.
- Fill the params (start from default_params) and encode them as base64url in ?p=.
- For each frame open the player with ?t=<seconds>, wait for data-motion-ready, screenshot at the native size, then join the PNGs with ffmpeg.
curl -s https://gimgs.net/motion/market-ticker.jsonhttps://gimgs.net/motion/market-ticker/play?p=…&t=<seconds>claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("market-ticker")Prompt
Use the gimgs.net motion template "Market ticker strip". Spec JSON (prompt + params schema + full HTML source): https://gimgs.net/motion/market-ticker.json Raw template: https://gimgs.net/motion/market-ticker/template.html Player for frame capture: https://gimgs.net/motion/market-ticker/play?p=<base64url JSON params>&t=<seconds> (1920x160, 30 fps, 10s) 1. Read the JSON and follow its "prompt" section. 2. Fill the params (start from default_params) for: <describe what you want>. 3. Render: open the player at t = i/fps for i in 0..299 in headless Chromium (viewport 1920x160, wait for document.documentElement.dataset.motionReady === "1"), screenshot each frame, then ffmpeg -framerate 30 -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4 4. If you need to change the design, edit the HTML but keep window.motion and #stage so the same renderer works.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Market ticker strip</title>
<style>
@font-face{font-family:'IBM Plex Mono';font-weight:400 500;font-display:block;src:url(https://gimgs.net/fonts/plexmono-500-latin.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Sans';font-weight:400 600;font-display:block;src:url(https://gimgs.net/fonts/plexsans-400-latin.woff2) format('woff2')}
html,body{margin:0;background:#000}
#stage{position:relative;width:1920px;height:160px;overflow:hidden;background:var(--bg,#0b0c10);color:#fff;font-family:'IBM Plex Sans',system-ui,sans-serif}
.rail{position:absolute;top:0;left:0;height:100%;display:flex;align-items:center;white-space:nowrap;
animation:scroll var(--dur,10s) linear both}
@keyframes scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.it{display:inline-flex;align-items:center;gap:22px;padding:0 48px;height:100%;border-right:1px solid rgba(255,255,255,.08)}
.it img{width:64px;height:64px;border-radius:50%;background:#fff;object-fit:contain;padding:6px;box-sizing:border-box}
.sym{font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:500;font-size:40px;letter-spacing:.02em}
.nm{font-size:22px;color:rgba(255,255,255,.55);margin-top:2px}
.px{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:40px;margin-left:12px}
.chg{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:28px;padding:6px 14px;border-radius:8px;font-weight:500}
.up{color:var(--up,#22c55e);background:color-mix(in srgb,var(--up,#22c55e) 16%,transparent)}
.dn{color:var(--dn,#ef4444);background:color-mix(in srgb,var(--dn,#ef4444) 16%,transparent)}
.fade{position:absolute;top:0;bottom:0;width:180px;pointer-events:none}
.fade.l{left:0;background:linear-gradient(90deg,var(--bg,#0b0c10),transparent)}
.fade.r{right:0;background:linear-gradient(-90deg,var(--bg,#0b0c10),transparent)}
</style>
</head>
<body>
<div id="stage">
<div class="rail" id="rail"></div>
<div class="fade l"></div><div class="fade r"></div>
</div>
<script>
window.motion = {
width: 1920, height: 160, fps: 30, duration: 10,
params: {
items: [
{ symbol: "BTC", name: "Bitcoin", price: "$112,430", change: "+2.4%", logo: "https://gimgs.net/crypto/btc.svg" },
{ symbol: "ETH", name: "Ethereum", price: "$4,120", change: "-0.8%", logo: "https://gimgs.net/crypto/eth.svg" },
{ symbol: "AAPL", name: "Apple", price: "$248.10", change: "+1.1%", logo: "https://gimgs.net/stock/apple.svg" },
{ symbol: "NVDA", name: "NVIDIA", price: "$181.20", change: "+3.6%", logo: "https://gimgs.net/stock/nvidia.svg" },
{ symbol: "TSLA", name: "Tesla", price: "$412.00", change: "-1.9%", logo: "https://gimgs.net/stock/tesla.svg" }
],
bg: "#0b0c10", up: "#22c55e", down: "#ef4444"
},
apply: function (p) {
var s = document.getElementById("stage");
s.style.setProperty("--bg", p.bg); s.style.setProperty("--up", p.up); s.style.setProperty("--dn", p.down);
var rail = document.getElementById("rail");
while (rail.firstChild) rail.removeChild(rail.firstChild);
var items = Array.isArray(p.items) ? p.items : [];
function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; }
// the list is rendered twice so a translateX(-50%) loop is seamless
for (var r = 0; r < 2; r++) items.forEach(function (it) {
var d = el("div", "it");
if (it.logo) { var img = el("img"); img.src = it.logo; img.alt = ""; d.appendChild(img); }
var t = el("div"); t.appendChild(el("div", "sym", it.symbol || "")); t.appendChild(el("div", "nm", it.name || "")); d.appendChild(t);
d.appendChild(el("div", "px", it.price || ""));
var c = String(it.change || ""); d.appendChild(el("div", "chg " + (c.trim().charAt(0) === "-" ? "dn" : "up"), c));
rail.appendChild(d);
});
s.style.setProperty("--dur", window.motion.duration + "s");
}
};
</script>
</body>
</html>
- Collect quotestool: any market data APIFormat numbers as strings.
- Resolve logostool: gimgs /api/stock-search?q=apple → logoid→ https://gimgs.net/stock/{logoid}.svg
- Render loop
frames 0…299 at t=i/30 → ffmpeg -framerate 30 -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p ticker.mp4 - Overlay
ffmpeg -i video.mp4 -stream_loop -1 -i ticker.mp4 -filter_complex "[1]format=yuva420p[t];[0][t]overlay=0:920:shortest=1" out.mp4
| param | type | default | description |
|---|---|---|---|
items | array | [{"symbol":"BTC","name":"Bitcoin","price":"$112,430","change":"+2.4%","logo":"https://gimgs.net/crypto/btc.svg"},{"symbol":"ETH","name":"Ethereum","price":"$4,120","change":"-0.8%","logo":"https://gimgs.net/crypto/eth.svg"},{"symbol":"AAPL","name":"Apple","price":"$248.10","change":"+1.1%","logo":"https://gimgs.net/stock/apple.svg"},{"symbol":"NVDA","name":"NVIDIA","price":"$181.20","change":"+3.6%","logo":"https://gimgs.net/stock/nvidia.svg"},{"symbol":"TSLA","name":"Tesla","price":"$412.00","change":"-1.9%","logo":"https://gimgs.net/stock/tesla.svg"}] | Ticker items in order. Each: {symbol, name, price, change, logo}. change starting with '-' is red. logo: https://gimgs.net/stock/{tradingview-slug}.svg, /crypto/{ticker}.svg or /brand-logo/{slug}.svg |
bg | string · color | "#0b0c10" | Strip background |
up | string · color | "#22c55e" | Positive change colour |
down | string · color | "#ef4444" | Negative change colour |
?p=eyJpdGVtcyI6W3sic3ltYm9sIjoiQlRDIiwibmFtZSI6IkJpdGNvaW4iLCJwcmljZSI6IiQxMTIsNDMwIiwiY2hhbmdlIjoiKzIuNCUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvY3J5cHRvL2J0Yy5zdmcifSx7InN5bWJvbCI6IkVUSCIsIm5hbWUiOiJFdGhlcmV1bSIsInByaWNlIjoiJDQsMTIwIiwiY2hhbmdlIjoiLTAuOCUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvY3J5cHRvL2V0aC5zdmcifSx7InN5bWJvbCI6IkFBUEwiLCJuYW1lIjoiQXBwbGUiLCJwcmljZSI6IiQyNDguMTAiLCJjaGFuZ2UiOiIrMS4xJSIsImxvZ28iOiJodHRwczovL2dpbWdzLm5ldC9zdG9jay9hcHBsZS5zdmcifSx7InN5bWJvbCI6Ik5WREEiLCJuYW1lIjoiTlZJRElBIiwicHJpY2UiOiIkMTgxLjIwIiwiY2hhbmdlIjoiKzMuNiUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvc3RvY2svbnZpZGlhLnN2ZyJ9LHsic3ltYm9sIjoiVFNMQSIsIm5hbWUiOiJUZXNsYSIsInByaWNlIjoiJDQxMi4wMCIsImNoYW5nZSI6Ii0xLjklIiwibG9nbyI6Imh0dHBzOi8vZ2ltZ3MubmV0L3N0b2NrL3Rlc2xhLnN2ZyJ9XSwiYmciOiIjMGIwYzEwIiwidXAiOiIjMjJjNTVlIiwiZG93biI6IiNlZjQ0NDQifQ