Hướng dẫn

Tạo overlay TikTok LIVE

Tạo overlay browser source tương thích OBS, hiển thị chat trực tiếp, thông báo quà tặng và số người xem theo thời gian thực từ bất kỳ phiên TikTok LIVE nào.

Bạn sẽ tạo được gì

Một overlay chạy trên trình duyệt, dùng được với OBS, Streamlabs hoặc bất kỳ phần mềm nào hỗ trợ browser source. Overlay hiển thị:

  • Tin nhắn chat trực tiếp theo thời gian thực
  • Thông báo quà tặng có hiệu ứng kèm giá trị kim cương
  • Số người xem hiện tại
  • Khung chat cuộn kèm avatar người dùng

Chuẩn bị

  • Đã cài Node.js 18+
  • Một API key TikTools miễn phí - lấy tại đây
  • OBS Studio (hoặc phần mềm phát sóng bất kỳ có Browser Source)

Bước 1: Thiết lập dự án

mkdir tiktok-overlay && cd tiktok-overlay
npm init -y
npm install @tiktool/live express

Bước 2: Tạo server

Tạo server.mjs - file này kết nối tới TikTok và phát sự kiện qua Server-Sent Events (SSE) tới overlay trên trình duyệt:

import express from 'express'
import { TikTokLive } from '@tiktool/live'

const app = express()
const clients = new Set()

// Serve the overlay HTML
app.get('/', (req, res) => {
  res.sendFile('overlay.html', { root: '.' })
})

// SSE endpoint for real-time events
app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    Connection: 'keep-alive',
  })
  clients.add(res)
  req.on('close', () => clients.delete(res))
})

function broadcast(event, data) {
  for (const client of clients) {
    client.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`)
  }
}

// Connect to TikTok LIVE
const tiktok = new TikTokLive({
  uniqueId: process.env.STREAMER || 'tv_asahi_news',
  apiKey: process.env.TIKTOOL_API_KEY
})

tiktok.on('chat', (e) => broadcast('chat', {
  user: e.nickname, comment: e.comment, avatar: e.profilePictureUrl
}))

tiktok.on('gift', (e) => broadcast('gift', {
  user: e.nickname, gift: e.giftName, diamonds: e.diamondCount
}))

tiktok.on('viewer_count', (e) => broadcast('viewers', {
  count: e.viewerCount
}))

await tiktok.connect()
app.listen(3333, () => console.log('Overlay: http://localhost:3333'))

Bước 3: Tạo HTML cho overlay

Tạo overlay.html - đây là thứ OBS sẽ hiển thị dưới dạng browser source:

<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Inter', sans-serif;
      background: transparent;
      overflow: hidden;
    }

    .chat-feed {
      position: fixed; bottom: 20px; left: 20px;
      width: 360px; max-height: 400px;
      display: flex; flex-direction: column-reverse;
      gap: 6px; overflow: hidden;
    }

    .chat-msg {
      background: rgba(0, 0, 0, 0.6);
      border-radius: 8px; padding: 8px 12px;
      color: #fff; font-size: 14px;
      animation: slideIn 0.3s ease;
    }

    .chat-msg .user { color: #fff; font-weight: 600; }

    .gift-alert {
      position: fixed; top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      background: rgba(0, 0, 0, 0.8);
      border: 2px solid var(--border-primary);
      border-radius: 16px; padding: 24px 40px;
      text-align: center; color: #fff;
      animation: popIn 0.5s ease;
      display: none;
    }

    .gift-alert.show { display: block; }
    .gift-alert .gift-name { font-size: 28px; font-weight: 800; }
    .gift-alert .gift-user { font-size: 16px; color: #94a3b8; }
    .gift-alert .gift-diamonds { font-size: 18px; color: #fff; }

    .viewer-count {
      position: fixed; top: 20px; right: 20px;
      background: rgba(0, 0, 0, 0.6);
      border-radius: 8px; padding: 8px 16px;
      color: #fff; font-size: 14px; font-weight: 600;
    }

    @keyframes slideIn {
      from { opacity: 0; transform: translateY(10px); }
      to { opacity: 1; transform: translateY(0); }
    }

    @keyframes popIn {
      0% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
      100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    }
  </style>
</head>
<body>
  <div class="chat-feed" id="chat"></div>
  <div class="gift-alert" id="gift">
    <div class="gift-name" id="gift-name"></div>
    <div class="gift-user" id="gift-user"></div>
    <div class="gift-diamonds" id="gift-diamonds"></div>
  </div>
  <div class="viewer-count" id="viewers">👁 0</div>

  <script>
    const chat = document.getElementById('chat')
    const gift = document.getElementById('gift')
    const src = new EventSource('/events')

    src.addEventListener('chat', (e) => {
      const d = JSON.parse(e.data)
      const el = document.createElement('div')
      el.className = 'chat-msg'
      el.innerHTML = `<span class="user">${d.user}</span> ${d.comment}`
      chat.prepend(el)
      if (chat.children.length > 50) chat.lastChild.remove()
    })

    src.addEventListener('gift', (e) => {
      const d = JSON.parse(e.data)
      document.getElementById('gift-name').textContent = `🎁 ${d.gift}`
      document.getElementById('gift-user').textContent = `from ${d.user}`
      document.getElementById('gift-diamonds').textContent = `${d.diamonds} 💎`
      gift.classList.add('show')
      setTimeout(() => gift.classList.remove('show'), 4000)
    })

    src.addEventListener('viewers', (e) => {
      const d = JSON.parse(e.data)
      document.getElementById('viewers').textContent = `👁 ${d.count.toLocaleString()}`
    })
  </script>
</body>
</html>

Bước 4: Chạy & thêm vào OBS

TIKTOOL_API_KEY=your_key STREAMER=target_username node server.mjs

Sau đó trong OBS:

  • Thêm một Nguồn trình duyệt mới
  • Đặt URL là http://localhost:3333
  • Đặt chiều rộng 1920 và chiều cao 1080
  • Tick vào "Shutdown source when not visible"

Ý tưởng tùy biến

  • Giao diện riêng - đổi màu, font và bố cục cho hợp với thương hiệu kênh của bạn
  • Hiệu ứng âm thanh - phát âm thanh khi có quà bằng Web Audio API
  • Ảnh động GIF - hiển thị GIF động cho từng món quà cụ thể
  • Thanh mục tiêu - thêm thanh tiến độ mục tiêu donate/quà tặng
  • Bục top người tặng - hiển thị top 3 người tặng quà theo thời gian thực