diff --git a/daemon/src/media/video/sinkclient.cpp b/daemon/src/media/video/sinkclient.cpp
index 68cb81fe7e57ac4da65934d1b7e1d253ef275048..defbc5209d0a651c27f06d3c57ee4ada2ebb05f1 100644
--- a/daemon/src/media/video/sinkclient.cpp
+++ b/daemon/src/media/video/sinkclient.cpp
@@ -284,6 +284,10 @@ SinkClient::stop() noexcept
 #endif // !HAVE_SHM
 
 SinkClient::SinkClient(const std::string& id) : id_ {id}
+#ifdef DEBUG_FPS
+    , frameCount_(0u)
+    , lastFrameDebug_(std::chrono::system_clock::now())
+#endif
 {}
 
 void
@@ -292,6 +296,17 @@ SinkClient::update(Observable<std::shared_ptr<VideoFrame>>* /*obs*/,
 {
     auto f = frame_p; // keep a local reference during rendering
 
+#ifdef DEBUG_FPS
+    auto currentTime = std::chrono::system_clock::now();
+    const std::chrono::duration<double> seconds = currentTime - lastFrameDebug_;
+    ++frameCount_;
+    if (seconds.count() > 1) {
+        RING_DBG("%s: FPS %f", id_.c_str(), frameCount_ / seconds.count());
+        frameCount_ = 0;
+        lastFrameDebug_ = currentTime;
+    }
+#endif
+
 #if HAVE_SHM
     shm_->render_frame(*f.get());
 #endif
diff --git a/daemon/src/media/video/sinkclient.h b/daemon/src/media/video/sinkclient.h
index 24f6d0bfab80bd88501a02f46202617ac118b433..048945346b01ac45b1911c56fd6c01eebdbfa9f9 100644
--- a/daemon/src/media/video/sinkclient.h
+++ b/daemon/src/media/video/sinkclient.h
@@ -80,6 +80,11 @@ class SinkClient : public VideoFramePassiveReader
         std::function<void(unsigned char*)> target_;
         std::vector<unsigned char> targetData_;
 
+#ifdef DEBUG_FPS
+        unsigned frameCount_;
+        std::chrono::time_point<std::chrono::system_clock> lastFrameDebug_;
+#endif
+
 #if HAVE_SHM
         // using shared_ptr and not unique_ptr as ShmHolder is forwared only
         std::shared_ptr<ShmHolder> shm_;