Motion · Ticker

Dải ticker thị trường

Dải ticker cuộn liền mạch với logo, giá và mức thay đổi — chứng khoán, crypto hay bất kỳ con số nào. Dải 1920×160, lặp 10 giây.

1920×16012:130 fps10s · 300 frameGiấy phép: CC0#ticker#stocks#crypto#finance#loop

Nguồn: gimgs ↗ · CC0

0.00s / 10sMở player ↗

Khi nào dùng

Dải tin tài chính ở đáy video, nền lặp cho bản tin thị trường, header dashboard. Đầu ra là dải 1920×160: chồng lên footage 1080p bằng ffmpeg overlay=0:920.

Cách chỉnh

  • Điền items bằng dữ liệu thật — giá và mức thay đổi là chuỗi thuần nên định dạng tuỳ ý (€1.234,56, +0,8 %, ▲ 2,4%). change bắt đầu bằng - sẽ tô màu down.
  • Logo: cổ phiếu → https://gimgs.net/stock/{slug tradingview}.svg (apple, microsoft, nvidia…; tra slug qua /api/stock-search?q=), crypto → /crypto/{ticker}.svg, thương hiệu → /brand-logo/{slug}.svg. Bỏ logo để ẩn vòng tròn.
  • 5–8 mục là vừa; danh sách được nhân đôi bên trong nên lặp liền mạch với mọi số lượng.
  • Tốc độ: dải đi nửa chiều dài trong duration (10 s). Nhiều mục = nhanh hơn. Sửa window.motion.duration trong source nếu muốn chậm hơn.

Không đổi

window.motion, kích thước #stage, vòng lặp translateX(-50%) của dải (nhờ nó mà frame 0 và frame cuối khớp nhau).

Mọi thứ trên trang này đều có bản máy đọc. Đưa agent link JSON, hoặc thêm MCP server gimgs rồi bảo nó tìm motion template.

  1. Tải JSON — trong đó có prompt, schema tham số và toàn bộ source.
  2. Điền params (bắt đầu từ default_params) rồi mã hoá base64url vào ?p=.
  3. Với mỗi frame mở player với ?t=<giây>, chờ data-motion-ready, chụp đúng kích thước gốc, rồi ghép PNG bằng ffmpeg.
curl -s https://gimgs.net/motion/market-ticker.json
https://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 "Dải ticker thị trường".
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.

JSON · Markdown · llms.txt

4,025 chars · CC0Mở template gốc ↗
<!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>
  1. Collect quotes
    tool: any market data API
    Format numbers as strings.
  2. Resolve logos
    tool: gimgs /api/stock-search?q=apple → logoid
    → https://gimgs.net/stock/{logoid}.svg
  3. Render loop
    frames 0…299 at t=i/30 → ffmpeg -framerate 30 -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p ticker.mp4
  4. 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
paramtypedefaultdescription
itemsarray[{"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
bgstring · color"#0b0c10"Strip background
upstring · color"#22c55e"Positive change colour
downstring · color"#ef4444"Negative change colour

?p=eyJpdGVtcyI6W3sic3ltYm9sIjoiQlRDIiwibmFtZSI6IkJpdGNvaW4iLCJwcmljZSI6IiQxMTIsNDMwIiwiY2hhbmdlIjoiKzIuNCUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvY3J5cHRvL2J0Yy5zdmcifSx7InN5bWJvbCI6IkVUSCIsIm5hbWUiOiJFdGhlcmV1bSIsInByaWNlIjoiJDQsMTIwIiwiY2hhbmdlIjoiLTAuOCUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvY3J5cHRvL2V0aC5zdmcifSx7InN5bWJvbCI6IkFBUEwiLCJuYW1lIjoiQXBwbGUiLCJwcmljZSI6IiQyNDguMTAiLCJjaGFuZ2UiOiIrMS4xJSIsImxvZ28iOiJodHRwczovL2dpbWdzLm5ldC9zdG9jay9hcHBsZS5zdmcifSx7InN5bWJvbCI6Ik5WREEiLCJuYW1lIjoiTlZJRElBIiwicHJpY2UiOiIkMTgxLjIwIiwiY2hhbmdlIjoiKzMuNiUiLCJsb2dvIjoiaHR0cHM6Ly9naW1ncy5uZXQvc3RvY2svbnZpZGlhLnN2ZyJ9LHsic3ltYm9sIjoiVFNMQSIsIm5hbWUiOiJUZXNsYSIsInByaWNlIjoiJDQxMi4wMCIsImNoYW5nZSI6Ii0xLjklIiwibG9nbyI6Imh0dHBzOi8vZ2ltZ3MubmV0L3N0b2NrL3Rlc2xhLnN2ZyJ9XSwiYmciOiIjMGIwYzEwIiwidXAiOiIjMjJjNTVlIiwiZG93biI6IiNlZjQ0NDQifQ