How to integrate IP camera into web application? Use a SPA + BFF split: the browser hosts ImouPlayer (or your HLS client); your Backend-for-Frontend holds appSecret, obtains accessToken, authorizes the signed-in user against your ACL, then returns only a short-lived kitToken from getKitToken (or an HLS URL from bindDeviceLive). Never put accessToken or appSecret in the SPA.
Why it matters
Most modern web products are single-page apps. The failure mode is not “missing a camera SDK”—it is calling OpenAPI from the browser with developer secrets, or initializing ImouPlayer with accessToken. A BFF keeps secrets and OpenAPI traffic on the server, while the SPA stays responsible for routing, layout, and player lifecycle. This FAQ focuses on that architecture—not on Wasm hosting edge cases.
Product page: Video Monitoring.
Recommended architecture
SPA (React/Vue/etc.)
│ session cookie / JWT to your domain
│ ImouPlayer with kitToken only
▼
BFF (your API)
│ ACL: tenant / site / role / camera
│ accessToken (cached) → getKitToken / bindDeviceLive / createDeviceRtmpLive
▼
Imou OpenAPI → devices & streams
| Layer | Owns | Must not own |
|---|---|---|
| SPA | UI, player mount/destroy, UX errors |
appSecret, accessToken, cross-tenant camera lists |
| BFF | Secrets, OpenAPI, ACL gate, token cache | End-user password stores for Imou consumer accounts |
| Imou Open Platform | Device connectivity, live/play credentials, entitlements | Your multi-tenant product ACL |
Why SPA + BFF (not SPA → OpenAPI)
SPAs are excellent at composition and routing. They are poor secret vaults. If the SPA can call OpenAPI with appSecret or a long-lived accessToken, any XSS or leaked build artifact becomes a fleet-wide incident. The BFF pattern is not ceremony—it is how you keep developer credentials and end-user sessions in different trust domains.
A second reason is product ACL. OpenAPI knows what your developer application can access. It does not know your customer’s org chart. Putting authorization on the BFF next to your existing session middleware is the natural place to enforce tenant/site/role before minting play credentials.
Keep inventory and live minting as separate BFF routes when possible: list endpoints read your synced DB; live-session endpoints talk to Imou only after ACL. That split keeps camera pickers fast and prevents list pages from consuming live-view resources.
Steps
Create an application and bind devices on open.imoulife.com. Confirm cameras appear to OpenAPI via
listDeviceDetailsByPage(pageSize1–50), then map them into your SaaS site/tenant tables.Add a BFF live-session endpoint. Example shape:
POST /api/cameras/:id/live-session. Require your web session. Reject with 403 before any Imou call if the user cannot view that camera.Obtain
accessTokenon the BFF usingaccessToken. Cache server-side. Rotate per platform guidance. This token never leaves the BFF.-
Mint the play credential after ACL.
- Interactive web →
getKitToken→ return{ kitToken, streamId, expiresAt } - Custom HLS →
bindDeviceLive - RTMP media path →
createDeviceRtmpLive
- Interactive web →
Initialize the player in the SPA. Load ImouPlayer assets per JS SDK / Resource download. Pass
kitTokenonly. PreferstreamId = 1(SD) for dashboards; use0(HD) for a focused view.Manage lifecycle in the SPA. Create the player when the live route mounts; destroy on navigation or camera switch. Refresh via the BFF before
kitTokenexpiry (~2 hours TTL; ~1 hour BFF cache is a practical pattern).Optional inventory endpoint. Serve camera pickers from your DB (synced earlier), not by minting live credentials for every list row.
Illustrative BFF contract
POST /api/cameras/:cameraId/live-session
requireSession()
requireCanViewCamera(user, cameraId) // SaaS ACL
accessToken = getCachedAccessToken() // appId/appSecret on server
kitToken = getKitToken(...)
return { kitToken, streamId: 1, expiresAt }
SPA responsibilities after that:
- Call the endpoint only when the user opens Live
-
ImouPlayer.init({ kitToken, ... })— neveraccessToken - Destroy the player on leave
- On 401/403 from BFF, show your product’s permission UX—not Imou console errors
When to choose HLS or RTMP from the same BFF
Use the same ACL gate, different last mile:
- ImouPlayer — interactive monitoring in the SPA (default)
-
HLS (
bindDeviceLive) — you already standardize on an HLS client or need a gated URL surface -
RTMP (
createDeviceRtmpLive) — a media pipeline expects RTMP; do not force RTMP into a normal browser dashboard
Live URLs are sensitive: anyone who obtains them may view the stream. Issue them only through authenticated BFF routes.
Day-one acceptance criteria
- The SPA never stores
appSecretoraccessTokenin env bundles, localStorage, or client logs. - Opening Live calls one BFF endpoint; that endpoint is the only place using
accessTokenfor play minting. - ImouPlayer initializes with
kitToken; switching cameras destroys the previous player first. - Default quality is SD (
streamId = 1) unless the route is an explicit HD inspection view. - Expired
kitTokentriggers a BFF refresh path, not an infinite black screen. - 403 from ACL returns your product’s permission copy—operators should not debug Imou console errors for “wrong role.”
Ship that for a single camera route before building a multi-camera wall. The wall reuses the same BFF contract with slot IDs.
Limits and pitfalls
- Calling OpenAPI from the SPA with
appSecretis a security incident, not a shortcut. - Feeding
accessTokento ImouPlayer commonly yields a black screen (kitToken≠accessToken). - Sharing one unscoped BFF cache across tenants can leak play credentials—key by tenant + camera.
- Prefetching live sessions for an entire site list wastes quota; watch My Resources.
- Talk, PTZ, and playback controls should appear only when device and subscribed services support them.
- This international path does not center GB28181; use the documented OpenAPI/SDK methods above.
Register at https://open.imoulife.com — Imou Open Platform is cloud video and AIoT focused, with APIs, SDKs, and low-code components to help vendors and developers ship web video apps faster. Explore Video Monitoring.
Top comments (0)