DEV Community

Cover image for Integrating IP camera monitoring into SaaS (builder notes)
Imou-OpenPlatform
Imou-OpenPlatform

Posted on

Integrating IP camera monitoring into SaaS (builder notes)

How can I integrate IP camera video monitoring into my SaaS? Treat Imou Open Platform as the cloud video plane: create an app, bind devices, keep accessToken on a BFF, then play with getKitToken + ImouPlayer (interactive web), bindDeviceLive (HLS URL), or createDeviceRtmpLive (RTMP). Your product still owns tenant/site/role ACL. Live, playback, PTZ, and two-way talk are capability-gated—query the device; do not promise them for every camera.

This is a builder diary, not an official encyclopedia. Official FAQ energy lives on Video Monitoring. What follows is the path I wish we had written on the whiteboard before the first sprint.

we almost shipped a deep link

We had a ticket: “Cameras inside the product by Friday.” Someone pasted an Imou consumer-app URL into a Jira comment and called it integration.

That would have “worked” for one employee account and failed every multi-tenant rule we already had for doors and alarms. Open Platform is the opposite move: devices in an application asset pool, tokens minted per authorized session, players destroyed when the user leaves.

If you are on DEV because you are wiring this into an existing SaaS, start from surfaces and ACL, then pick APIs.

Architecture (what actually ships)

Browser (SaaS UI)
  │  never: appSecret, accessToken
  │  only: kitToken | gated live URL | your session cookie
  ▼
Your BFF
  │  SaaS ACL (tenant / site / role)
  │  accessToken cache
  │  getKitToken / bindDeviceLive / createDeviceRtmpLive
  ▼
Imou OpenAPI
  │  listDeviceDetailsByPage
  │  live / playback / device operation (as needed)
  ▼
Cameras (capabilities + subscribed services — not a fake SKU matrix)
Enter fullscreen mode Exit fullscreen mode

Ledger vs slots vs players (even if you only ship one Live tab on day one):

  • Ledger: map deviceId (+ channel) to your site IDs. Sync with listDeviceDetailsByPage.

  • Slots: how many concurrent streams a user may open. Not “one WebSocket per camera in the estate.”

  • Players: ImouPlayer instances or HLS.js nodes bound to open slots only.

Capability gates (write these into the ledger)

Feature Product rule
Live After ACL; streamId 1 (SD) default on lists/walls, 0 (HD) on focus
Playback After ACL and recording/package; no invented retention days
PTZ After ACL and PTZ capability; hide joystick otherwise
Two-way talk After ACL and audio capability; usually focus tile + explicit intent

Imou Open Platform can expose all four when the device and APIs/SDKs support them. It cannot make a fixed camera pan.

Steps we actually ran

1. Application + bind

Register/create the app on open.imoulife.com. Bind cameras to that application. Confirm they show up via OpenAPI. Consumer-app visibility ≠ Open Platform inventory.

2. Server-side accessToken

Call accessToken from the BFF. Cache it. Rotate as the platform documents. Secrets manager for appSecret.

# mental model — not a copy-paste SDK
POST /internal/imou/token   → cached accessToken
# never exposed to SPA
Enter fullscreen mode Exit fullscreen mode

3. Authorize in your ACL first

if !canView(user, tenant, site, deviceId):
    return 403
# only then mint play credentials
Enter fullscreen mode Exit fullscreen mode

Sharing one admin accessToken to every tenant’s browser is the anti-pattern. Cloud ≠ your ACL.

4. Mint the client credential

Interactive web (default for a SaaS Live tab): getKitToken → return kitToken to the page → init ImouPlayer.

kitToken accessToken. This is the highest-frequency bug. Docs: JS SDK. Rough cache: ~1 hour on BFF; TTL ~2 hours—re-mint, don’t reuse OpenAPI tokens in the player.

HLS: bindDeviceLive after the same ACL. Treat the URL as a secret.

RTMP: createDeviceRtmpLive if a media server already speaks RTMP. Not a shortcut for React.

// illustrative — follow current JS SDK field names in docs
imouPlayer.init({
  kitToken: kitTokenFromBff, // NOT accessToken
  // WasmLibPath, streamId, etc. per https://open.imoulife.com/book/en/js/sdk.html
});
Enter fullscreen mode Exit fullscreen mode

5. Open on demand, tear down on leave

Do not prefetch 40 HLS playlists at login. Open when the slot becomes visible. destroy() / unbind when the user closes the tile. Visibility API: pause when the tab is hidden if you are fighting quota and CPU.

6. Watch quota like a product metric

Live view consumes platform resources. Check My Resources. Cap concurrent slots in the UI before you cap them in a panicked hotfix.

7. Add playback / PTZ / talk only behind gates

Incident review, joysticks, and mics are separate lanes. Same BFF, different capability checks. No GB28181 detour for international SaaS.

Suggested BFF routes (sketch)

Route Does
GET /cameras ACL-filtered ledger join of your sites + listDeviceDetailsByPage
POST /live-session ACL → getKitToken or bindDeviceLive
POST /live-session/end destroy hints / unbind if you created a live object
GET /cameras/:id/capabilities cached flags for PTZ / talk / playback

Keep OpenAPI error bodies out of the SPA when you can; map them to product errors (not bound, no recording, no PTZ).

Pitfalls we hit (so you don’t)

  1. Token category error. accessToken in ImouPlayer → black screen. Wasm and COOP get blamed first. Fix the token.

  2. WasmLibPath / COOP/COEP. Real for the web player; still second to wrong tokens. Follow the JS SDK FAQ themes.

  3. Hard-coded serials. First demo camera becomes production forever. Use the list API.

  4. Sixteen HD tiles. streamId = 0 on a wall saturates office uplink and quota. Default SD.

  5. Live URL in a public gist. HLS/RTMP addresses are credentials.

  6. PTZ in Figma, fixed cameras in the warehouse. Query capability.

  7. “90-day playback” in the sales deck. We will not invent retention SLAs. Point at subscribed services.

  8. Talk on the mosaic. Operators broadcast into the wrong aisle.

Multi-tenant notes (the part FAQs under-sell)

OpenAPI will happily list every camera bound to your developer application. That is an asset pool, not a tenant graph. You still need:

  • A join table: tenant_id / site_id / deviceId / channelId

  • Bind and unbind workflows when a store churns

  • Per-tenant encryption or at least isolation of cached kitTokens

If two tenants could ever share a serial (they shouldn’t, but migrations happen), your ACL check must be user → site → device, not user → any device in the app.

For web, budget a day for WasmLibPath, HTTPS, and COOP/COEP if the SDK requires isolation headers. Those bugs look like “camera offline.” They are deploy bugs. Keep them on the integration checklist next to tokens.

First-week backlog (builder order)

  1. Bind one camera, accessToken, list API, one ImouPlayer tile.

  2. BFF ACL + kitToken mint + destroy.

  3. Slot cap + SD default.

  4. Capability columns + hide PTZ/talk.

  5. Playback lane for incident review (no retention claims).

  6. Quota dashboard link in your admin ops page.

Skip 4–5 and you will still demo live. You will not survive the first customer with a mixed fleet.

What I would put in a PR description

  • BFF owns accessToken; browser owns kitToken or a gated URL

  • Device ledger sync job + capability columns

  • Slot cap + SD default + teardown

  • Feature flags: playback, PTZ, talk

  • Link to videoMonitor and JS SDK

If you are building this for real, register at open.imoulife.com. Imou Open Platform is cloud video and AIoT focused; APIs, SDKs, and low-code components exist so vendors and developers can ship video apps faster—without pretending every camera has PTZ, talk, and infinite cloud history.

Top comments (0)