Hệ thống webinar "giả live": video stream từ Bunny phát theo lịch cố định, người xem không pause/tua được, chat theo timeline, trang đăng ký + phòng chờ, email nhắc lịch, multi-user + affiliate, đồng bộ Google Sheet.
Sản phẩm của Nguyễn Hữu Thi — Amanvita Group.
- 🎬 Stream như live thật — phát theo lịch, chống tua/pause, vào trễ xem từ giữa
- 🗓️ Đăng ký theo ca — trang đăng ký riêng, phòng chờ countdown, tự vào phòng đúng giờ
- 💬 Chat theo timeline — kịch bản chat tự chạy, có hiệu ứng "đang nhập", AI sinh kịch bản
- 🎁 CTA đúng khoảnh khắc — nút ưu đãi hiện đúng giây đã định
- 📧 Email tự động (SendGrid) — xác nhận + nhắc 24h/1h/15p
- 🎨 Tùy biến giao diện — banner trên/dưới, kích thước video, theme sáng/tối, phụ đề đa ngôn ngữ
- 📊 Analytics — retention theo phút, tỷ lệ tham dự, click CTA
- 👥 Multi-user + Affiliate — mỗi user quản lý webinar riêng, link giới thiệu
- 🔗 Đồng bộ Google Sheet — ghi đăng ký + người bấm CTA qua Apps Script
- 🤖 AI (Claude) — sinh kịch bản chat từ transcript
npm install
ADMIN_PASSWORD=matkhau-cua-anh PORT=3300 node server.js| Biến | Bắt buộc | Mô tả |
|---|---|---|
PORT |
— | Mặc định 3300 |
ADMIN_PASSWORD |
✅ khi deploy | Mật khẩu super-admin. Nếu để trống, app tự sinh mật khẩu ngẫu nhiên và in ra log khi khởi động |
TZ |
— | Mặc định Asia/Ho_Chi_Minh — lịch phát tính theo giờ này |
BASE_URL |
✅ khi deploy | URL public của site, dùng trong link email (vd https://webinar.domain.com) |
SENDGRID_API_KEY |
— | Bật email xác nhận + nhắc lịch. Thiếu thì app vẫn chạy, chỉ log skip |
SENDGRID_FROM_EMAIL |
— | Email gửi (phải là verified sender trong SendGrid) |
SENDGRID_FROM_NAME |
— | Tên hiển thị người gửi |
ANTHROPIC_API_KEY |
— | Bật tính năng AI sinh kịch bản chat trong admin |
- Xác nhận ngay khi đăng ký (kèm link xem riêng)
- Nhắc lịch: 24 giờ / 1 giờ / 15 phút trước giờ phát (scheduler chạy mỗi phút; người đăng ký sát giờ không bị dội cả 3 email)
- Email là best-effort: lỗi SendGrid không bao giờ làm hỏng flow đăng ký
Trong admin → Tạo/Sửa webinar → khung "🤖 Sinh kịch bản bằng AI": dán transcript hoặc outline video, chọn số tin nhắn → AI (Claude Opus 4.8) tạo chat giả bám sát nội dung từng phút, tên người Việt tự nhiên. Kiểm tra rồi bấm Lưu.
Tab 📊 Analytics trong admin: số đăng ký, tỷ lệ tham dự, thời gian xem trung bình, click CTA, và biểu đồ retention theo phút (drop-off). Dữ liệu thu từ trang xem: sự kiện join + heartbeat mỗi 60 giây + click CTA.
- Trang quản trị:
http://localhost:3300/admin.html(mật khẩu super-admin đặt qua envADMIN_PASSWORD; nếu chưa đặt, xem log khởi động để lấy mật khẩu tạm) - Trang đăng ký:
http://localhost:3300/w/<slug> - Trang xem: link riêng có token, sinh ra khi đăng ký
- Slug — đường dẫn trang đăng ký, ví dụ
khoa-hoc-ai→/w/khoa-hoc-ai - Video URL — vào Bunny Stream → chọn video → copy HLS Playlist URL (dạng
https://vz-xxx.b-cdn.net/VIDEO_ID/playlist.m3u8). Loạihlskhuyên dùng (kiểm soát hoàn toàn, chống tua tuyệt đối). Loạiiframedùng link embed của Bunny. - Thời lượng (giây) — đúng độ dài video.
- Lịch phát hàng ngày — ví dụ
09:00, 14:00, 20:00. Người đăng ký chọn 1 trong 6 ca sắp tới. - Kịch bản chat — JSON:
[{"t":15,"name":"Lan","text":"Chào mọi người"}],t= giây thứ mấy trong video. - CTA — nhãn + link + giây xuất hiện.
- Vị trí video tính theo giờ server:
offset = now - giờ_ca. Vào trễ 10 phút thì xem từ phút 10. - Mỗi 3 giây client tự so vị trí video với giờ server, lệch >5s là kéo về — pause/tua đều vô hiệu.
- Số người xem giả dao động theo đường cong (tăng giữa buổi) + nhiễu ngẫu nhiên, base chỉnh trong admin.
- Chat giả bắn theo timestamp; vào trễ vẫn thấy 10 tin gần nhất. Chat thật của người xem lưu DB, xem ở tab "Chat người xem".
# /etc/systemd/system/webinar.service
[Unit]
Description=Webinar App
After=network.target
[Service]
WorkingDirectory=/opt/webinar-app
ExecStart=/usr/bin/node server.js
Environment=PORT=3300
Environment=ADMIN_PASSWORD=DOI_MAT_KHAU_NAY
Environment=BASE_URL=https://webinar.your-domain.com
Environment=SENDGRID_API_KEY=SG.xxx
Environment=SENDGRID_FROM_EMAIL=hello@your-domain.com
Environment=SENDGRID_FROM_NAME=Webinar
Environment=ANTHROPIC_API_KEY=sk-ant-xxx
Restart=always
[Install]
WantedBy=multi-user.targetDB là SQLite tại data/webinar.db — backup chỉ cần copy file.
- Zalo ZNS / SMS reminder
- Webhook bắn sự kiện sang n8n/CRM
- Replay có thời hạn sau buổi live
- A/B test landing page
Phát hành theo giấy phép MIT — bạn được tự do sao chép, sửa đổi, sử dụng (kể cả mục đích thương mại), với điều kiện giữ nguyên dòng bản quyền dưới đây trong mọi bản sao:
Copyright (c) 2026 Nguyễn Hữu Thi — Amanvita Group
© 2026 Nguyễn Hữu Thi — Amanvita Group. Bảo lưu ghi nhận tác giả.