Skip to content

Đặc tả: Livestream Feature

Module: livestreamweb (port 8086) + batch + firebaselistener Status: Production

1. Tổng quan

Feature livestream cung cấp APIs cho viewer xem và tương tác với streamer qua Agora video, quản lý gift aggregation qua Redis/ActiveMQ pipeline, và đồng bộ realtime data với Firebase RTDB.

2. Phạm vi

In-scope - REST APIs (livestreamweb module)

LivestreamController (/api/livestream)

Endpoint Method Mô tả
/ GET Lấy danh sách livestream (paginated, với filters)
/viewer-get-livestream/{id} GET Chi tiết livestream + Agora info + Firebase data
/get-by-user-id GET Streamer lấy livestream của mình
/{id} GET Get livestream by ID
/get-agora-info-by-channel-name/{channelName} GET Sub channel Agora info
/get-agora-info-by-opponent-id/{id} GET Agora info của đối thủ
/push-opponent/{id} PUT Streamer mời đối thủ vào livestream
/remove-opponent/{id} PUT Xóa đối thủ khỏi livestream
/room-sync-register/{id} PUT Viewer đăng ký sync room
/sync-register/{id} PUT Sync register v2
/room-sync-cancel/{id} PUT Viewer cancel sync room
/sync-room-info/{id} PUT Sync room info
/sync-user-info PUT Sync user info
/user-sync-balance/{id} PUT Sync user balance cho livestream
/top-sync-viewers/{id} GET Top viewers theo total sync
/agora/app-id GET Lấy Agora App ID
/authorize-firebase-uid PUT Authorize/deauthorize Firebase UID

LivestreamGiftController (/api/livestream-gift)

Endpoint Method Mô tả
(gift sending endpoints) POST Gửi gift cho streamer

In-scope - Async pipeline

  • Gift aggregation: Redis counter → GiftAggregationJob (every 5s) → ActiveMQ → JMSLivestreamViewerGiftFirebaseUpdateListener → Firebase
  • Firebase listeners (module firebaselistener): commands, event_types, livestream_events, yell_points_history

Out-of-scope

Mục Lý do
Agora SDK integration setup SDK-level config
Firebase project setup Infrastructure
Streamer management (KYC) Admin domain

3. User stories

ID Role Story Acceptance
LIVE-US-01 Viewer Xem livestream list → click vào → nhận Agora token → xem video Agora token hợp lệ, channel connected
LIVE-US-02 Streamer Mở app → nhận Agora publisher token + OBS settings Token với ROLE_PUBLISHER
LIVE-US-03 Viewer Gửi gift → B-Coin trừ ngay, streamer counter tăng (real-time Firebase) Counter Firebase updated
LIVE-US-04 Viewer Burst gift trong 5 giây → Redis aggregate → 1 batch message per streamer Không race condition balance
LIVE-US-05 Viewer Đăng ký sync room → xem game realtime của streamer Sync data available
LIVE-US-06 Streamer Mời opponent vào Agora channel Opponent sub-token generated

4. Functional requirements

ID Requirement Chi tiết
LIVE-F-01 Agora token - viewer generateToken(channel, uid, ROLE_SUBSCRIBER), uid từ userService.getCurrentUserIndex(userId)
LIVE-F-02 Agora token - streamer 4 UIDs: camera, screen, view, voice. ROLE_SUBSCRIBER (streamer subscribes multiple feeds)
LIVE-F-03 OBS settings getObsSetting: token với ROLE_PUBLISHER + appId
LIVE-F-04 Firebase data getLivestreamDataByChildNodes(id) fetch viewer count, gifts, etc. với caching
LIVE-F-05 Streamer points leaderboardLivestreamStreamerMonthlyService.getTotalPointsInMonth() inject vào response
LIVE-F-06 Gift aggregation Redis key: livestream:pending_gifts:{streamerId}, INCRBY per gift
LIVE-F-07 Gift batch GiftAggregationJob fixedDelay=5000ms, GETSET atomic, send với JMSXGroupID=streamerId
LIVE-F-08 Sequential per streamer JMSXGroupID=streamerId đảm bảo message order per streamer
LIVE-F-09 Room sync roomSyncRegisterCommandHandler.handleCore() + roomSyncCancelCommandHandler.handleCore()
LIVE-F-10 Firebase ban check Async fire-and-forget check getBannedLivestreamsByUserIdAsync() (non-blocking)

5. Business rules

  • Agora UID format:
  • Camera: userIndex (raw)
  • Screen: UID_SCREEN_PREFIX + userIndex
  • View: UID_VIEW_PREFIX + UID_SCREEN
  • Voice: UID_VOICE_PREFIX + UID_SCREEN
  • Sub-camera (viewer): UID_SUB_CAMERA_PREFIX + userIndex
  • Gift aggregation fixedDelay: ${jobs.gift-aggregation.fixedDelay} (default 5000ms).
  • Streamer points: tổng tháng hiện tại từ leaderboard_livestream_streamer_monthly.
  • viewer-get-livestream/{id} endpoint có performance logging chi tiết (LOGGER.error level → review nên dùng level thấp hơn).

6. Data contracts

Response - ViewerGetLivestreamResp

{
  "id": "<livestreamId>",
  "title": "<title>",
  "streamer_id": "<userId>",
  "channel_name": "BTH_Live_<streamerEmail>",
  "status": "NEW | STREAMING | ENDED",
  "agora": {
    "uid": 12345,
    "token": "<agoraToken>",
    "channel_name": "BTH_Live_..."
  },
  "livestream_viewer": {
    "total_bcoins": 5000,
    "streamer_points": 1200,
    "wish_orb": { "current": 30, "max": 100 }
  }
}

Response - StreamerGetLiveStreamRes

{
  "id": "<livestreamId>",
  "agora_streamer": {
    "uid_camera": 100,
    "uid_screen": 1000100,
    "uid_view": 2000100,
    "uid_vtube": 3000100,
    "token_camera": "...",
    "token_screen": "...",
    "token_view": "...",
    "token_voice": "...",
    "channel_name": "BTH_Live_..."
  },
  "obs_setting": {
    "token_host": "<publisherToken>",
    "app_id": "<agoraAppId>"
  }
}

Gift aggregation message (LivestreamGiftAggregateMessageDto)

{
  "streamer_id": "<streamerId>",
  "total_bcoin_value": 500,
  "timestamp": "2024-01-01T00:00:00Z"
}

7. Acceptance criteria

  • [ ] viewer-get-livestream/{id} trả đúng Agora token viewer + Firebase data
  • [ ] Streamer endpoint trả 4 Agora tokens đúng role/uid
  • [ ] Gift burst 100 requests trong 5s → Redis aggregate → 1 JMS message per streamer
  • [ ] Hai streamer nhận gift đồng thời → parallel processing (khác JMSXGroupID)
  • [ ] Cùng streamer → sequential processing (cùng JMSXGroupID)
  • [ ] Firebase counters update đúng sau gift JMS processed
  • [ ] Ban check async không block viewer-get-livestream response time
  • [ ] OBS setting token có ROLE_PUBLISHER, viewer token có ROLE_SUBSCRIBER

8. Constraints

  • Agora credentials cached (@Cacheable) để tránh DB call per request.
  • viewer-get-livestream có performance log toàn bộ steps (log level LOGGER.error đang dùng cho debug → cần cleanup).
  • getBannedLivestreamsByUserIdAsync() là fire-and-forget, không affect main response.

9. Code references

livestreamweb/
  controllers/livestream/LivestreamController.java
  controllers/livestream_gift/LivestreamGiftController.java
  services/agora/AgoraTokenService.java

batch/
  job/livestream/GiftAggregationJob.java
  jms/JMSLivestreamViewerGiftFirebaseUpdateListener.java

firebaselistener/
  listener/FirebaseCommandListener.java
  listener/FirebaseEventTypesListener.java
  listener/FirebaseLivestreamEventListener.java
  listener/FirebaseLivestreamsYellPointListener.java

application-core/
  service/livestream/LivestreamService.java
  service/livestream_firebase/LivestreamFirebaseService.java
  firebase/command/handler/RoomSyncRegisterCommandHandler.java
  firebase/command/handler/RoomSyncCancelCommandHandler.java