To add camera live video to an existing SaaS, do not rebuild identity, tenancy, or the site tree. Add one authorized BFF route: confirm the signed-in user may view that camera, obtain accessToken on the server, mint a short-lived kitToken (getKitToken), and mount ImouPlayer on the screen you already own. Optionally return HLS from bindDeviceLive if you already standardized on an HLS client. Never put appSecret or accessToken in the browser. Live is an embed behind your ACL—not a second product.
Overview: Video Monitoring.
This is a retrofit, not a greenfield platform
Greenfield “integrate video monitoring into SaaS” articles start at create-app and invent tenants. You already have tenants, sites, roles, and a UI. The cameras are the new object. The risk is scope creep: rewriting auth, duplicating device trees in a side admin, or deep-linking users into a consumer app “until we have time.”
A retrofit that ships looks like this:
Existing: Login → Site page → Assets tab
Add: Live tab / Camera detail
New code: POST /api/cameras/:id/live-session (ACL + mint)
ImouPlayer on that route only
Everything else (billing, tickets, maps) stays yours. Imou Open Platform supplies cloud live (HLS / FLV / RTMP family where the APIs apply) and ImouPlayer for interactive web. PTZ, playback, and two-way talk stay device-dependent—add chrome later, behind capability checks.
Product constraints you should write down first
| Constraint | Retrofit implication |
|---|---|
| You already have sessions | Reuse them. Do not create an Imou login for end users. |
| You already have ACL | Camera view is another permission (or reuse site:read). Enforce on the BFF before OpenAPI play calls. |
| You already have a site model | Store deviceId / channelId as fields on Site / Asset. Do not make OpenAPI the UX tree. |
| You already have a design system | ImouPlayer is a viewport. Your nav, headers, and empty states stay. |
| You have bandwidth and quota | Default SD (streamId = 1); on-demand mint; destroy on leave. |
| Compliance / audit | Log “who watched which camera when” in your audit table using your user id. |
If a camera is not bound to the developer application, the retrofit stops at inventory. Binding is an ops step, not a React component.
BFF route design
One endpoint is enough for the first release.
POST /api/cameras/:cameraId/live-session
Auth: existing SaaS session
Responsibilities:
- Resolve
cameraIdin your database todeviceId+channelId+tenantId/siteId. - Authorize: user belongs to tenant; role may view this site’s cameras.
- Use cached server
accessToken(accessToken docs). - Call
getKitToken(orbindDeviceLiveon an HLS branch). - Return only play material:
{ kitToken, expiresAt, streamId }or{ hlsUrl, expiresAt }.
Do not:
- Accept
deviceIdfrom the client without mapping through your DB (IDOR). - Return
accessToken. - Call OpenAPI if ACL failed (avoid extra quota and timing oracles).
- Prefetch sessions for every camera on a 40-row site list.
Cache kitToken ~1 hour server-side; validity is about ~2 hours. For a Live tab that stays open, expose expiresAt so the SPA can refresh.
HLS / RTMP when the SaaS already has a media stack
If Video.js / hls.js is already in the product, bindDeviceLive is a valid retrofit: same ACL, different payload. If a media server already speaks RTMP, createDeviceRtmpLive is the protocol adapter—not the default for a browser Live tab. Interactive controls (talk, PTZ in-player) still point at ImouPlayer + kitToken.
Same ACL gate
├─ getKitToken → ImouPlayer (default Live tab)
├─ bindDeviceLive → HLS URL (existing HLS widget)
└─ createDeviceRtmpLive → RTMP (pipeline / encoder)
UI mount (smallest change)
Pick one surface:
-
Camera detail — one player, HD (
streamId = 0) is reasonable. - Site Live tab — one or few slots; SD default; open on click.
Do not start with a 16-tile HD wall. That is a later dashboard project (slots, concurrency caps, destroy). For retrofit, one working tile behind ACL beats an impressive grid that 403s half the cells.
Mount rules:
- Render the player container only on the Live route.
- Fetch
live-sessionwhen the user opens that route (or clicks Play), not when the site list mounts. - Destroy on navigate-away.
- Empty state: “No camera bound” vs “No permission” vs “Quota / device offline”—do not collapse all failures into “camera broken.”
- Hide PTZ / talk / playback until you know the device supports them.
JS SDK: JavaScript development. HLS: bindDeviceLive.
Inventory without boiling the ocean
You need IDs in your DB. A cron or admin “sync devices” that calls listDeviceDetailsByPage (pageSize 1–50) and matches serials to sites is enough. Operators bind cameras in Open Platform; your CSM or onboarding maps them to sites. The Live tab only reads your mapping.
Do not block the first Live tab on a perfect CMDB. A spreadsheet import of siteId → deviceId ships. Automate sync once three customers complain about drift.
Rollout sequence that respects an existing roadmap
Existing SaaS teams fail this feature by bundling NVR, analytics, and a video wall into “the camera epic.” Split releases:
-
Internal dogfood — one bound lab camera, one tenant, ImouPlayer on camera detail. Prove
kitToken≠accessToken. - Design-partner site — real ACL, SD default, destroy on leave, audit log of views.
- GA Live tab — empty states, quota runbook, hide PTZ/talk until capability flags exist.
- Optional HLS widget — only if a product surface already demands a URL player.
-
Wall / multi-slot — separate epic: visible tiles, concurrency cap,
streamId = 1.
Each step is reversible. None requires rewriting login.
What “done” looks like for v1
- A user who can open Site A cannot mint a session for Site B’s camera (two-tenant test).
- Player initializes only after
live-session200. - Refresh after ~1 hour still plays (BFF remint).
- Closing the tab stops the session from the UI side (destroy). Residual cloud quota behavior follows platform rules; you still avoid leaking players in the SPA.
- Support has a runbook: unbound vs 403 vs quota vs wrong token type.
If v1 includes a public “share live link” without expiry and ACL, you did not retrofit—you opened a hole. Gate shares like you gate the tab.
Security checklist for reviewers
- [ ]
appSecretnot in frontend CI artifacts - [ ]
accessTokennever in browser network tab on the player call - [ ] Live URL /
kitTokennot written to third-party analytics - [ ] Tenant isolation tested with two accounts
- [ ] Player destroyed on SPA unmount
- [ ] HTTPS in production
Limits
Live-view quota applies. Capabilities depend on device and subscribed services. This international path is OpenAPI + SDK + cloud live—not a national-standard GB ingest story. Consumer-app deep links are a demo, not a retrofit.
Imou Open Platform is cloud video and AIoT oriented: APIs, SDKs, and components so ISVs can add live into products they already run. Register at https://open.imoulife.com and start from Video Monitoring.
Top comments (0)