Skip to content

Conversation

kekkokk
Copy link

@kekkokk kekkokk commented Oct 12, 2025

Actual need

I have several cameras connected to my frigate instance and I want them to visible in birdseye only when motion occurs (eg. Home alarm trigger and I want to display in my echo shows only the relevant video).
The problem is that when I restream the birdeye video to other system (eg. scrypted, or simply ffplay), the stream is extremely slow to attach (talking about 30/40 seconds). Not a problem for ffplay but for other more sensible devices like Alexa this ends up in an error.
Digging through the code seems that frigate is not pushing frames when in idle, thus resulting in a missing keyframe to start an RTSP feed.

Proposed change

birdseye: add idle_heartbeat_fps config option to periodically resend last frame

This adds an optional idle heartbeat mechanism to Birdseye. When enabled by setting the idle_heartbeat_fps config variable to a value > 0, Birdseye periodically re-sends the last composed frame when idle (no motion or no active frame updates). This helps downstream consumers such as go2rtc or smart display integrations to attach faster and maintain a low-latency stream during idle periods.

Documentation: added section in docs/configuration/restream.md.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code
  • Documentation Update

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • UI changes including text have used i18n keys and have been added to the en locale.
  • The code has been formatted using Ruff (ruff format frigate)

Copy link

netlify bot commented Oct 12, 2025

Deploy Preview for frigate-docs ready!

Name Link
🔨 Latest commit ce9dd7d
🔍 Latest deploy log https://app.netlify.com/projects/frigate-docs/deploys/68ec160e57820c0008945744
😎 Deploy Preview https://deploy-preview-20453--frigate-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Collaborator

@NickM-27 NickM-27 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The heartbeat idea seems fine in general. This should definitely be a config option though, Frigate does not use env variables for config options like this.

I don't think ffmpeg changes make sense. The birdseye restream command is already configurable in go2rtc config if you want it to be, most users shouldn't be changing that though.

@kekkokk kekkokk force-pushed the idle-heartbeat-birdseye branch from 03c9691 to 3eb8cc8 Compare October 12, 2025 20:43
@kekkokk
Copy link
Author

kekkokk commented Oct 12, 2025

Thanks for the quick feedback guys!

I (force, ops) pushed the changes requested.
Let me know if you prefer a clean branch.

…n idle)

birdseye: add optional idle heartbeat and FFmpeg tuning envs (default off)

This adds an optional configuration field `birdseye.idle_heartbeat_fps` to
enable a lightweight idle heartbeat mechanism in Birdseye. When set to a value
greater than 0, Birdseye periodically re-sends the last composed frame during
idle periods (no motion or active updates).

This helps downstream consumers such as go2rtc, Alexa, or Scrypted to attach
faster and maintain a low-latency RTSP stream when the system is idle.

Key details:
- Config-based (`birdseye.idle_heartbeat_fps`), default `0` (disabled).
- Uses existing Birdseye rendering pipeline; minimal performance impact.
- Does not alter behavior when unset.

Documentation: added tip section in docs/configuration/restream.md.
@kekkokk kekkokk force-pushed the idle-heartbeat-birdseye branch from 3eb8cc8 to 7789260 Compare October 12, 2025 20:50
Comment on lines +801 to +803
self.idle_fps = float(self.config.birdseye.idle_heartbeat_fps or 0.0)
self.idle_fps = max(0.0, self.idle_fps)
self._idle_interval: Optional[float] = (1.0 / self.idle_fps) if self.idle_fps > 0 else None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems redundant. We know it will be a valid float, with a default of 0.0

self.broadcaster.start()


# Start heartbeat loop only if enabled
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a thread for this, we should be able to just add a last_update check, and if the last update was older than the idle_heartbeat it should manually update with the same frame that was already sent.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but from my understanding this code runs only when we receive an update.
the purpose is to overcome this limit with a timed thread

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's not the case. Birdseye will always get updates even if there is no motion or objects. It just won't send an update in the case that no cameras match the criteria to be displayed. That's the part that just needs a check to resend the blank image anyway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants