diff --git a/src/conference.cpp b/src/conference.cpp
index 3d6774eb8a77c3987758f33e85d73539b4cf8c3d..8828fee81687a100bd5ead202e1c79a8f5cc1ce3 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -115,7 +115,7 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
             // Handle participants showing their video
             for (const auto& info : infos) {
                 std::string uri {};
-                bool isLocalMuted = false;
+                bool isLocalMuted = false, isPeerRecording = false;
                 std::string deviceId {};
                 auto active = false;
                 if (!info.callId.empty()) {
@@ -123,6 +123,7 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
                     if (auto call = std::dynamic_pointer_cast<SIPCall>(getCall(callId))) {
                         uri = call->getPeerNumber();
                         isLocalMuted = call->isPeerMuted();
+                        isPeerRecording = call->isPeerRecording();
                         if (auto* transport = call->getTransport())
                             deviceId = transport->deviceId();
                     }
@@ -146,7 +147,8 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
                                                           isModeratorMuted,
                                                           isModerator,
                                                           isHandRaised,
-                                                          isVoiceActive});
+                                                          isVoiceActive,
+                                                          isPeerRecording});
                 } else {
                     auto isModeratorMuted = false;
                     // If not local
@@ -165,6 +167,7 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
                                 getCall(streamInfo.callId))) {
                             uri = call->getPeerNumber();
                             isLocalMuted = call->isPeerMuted();
+                            isPeerRecording = call->isPeerRecording();
                             if (auto* transport = call->getTransport())
                                 deviceId = transport->deviceId();
                         }
@@ -180,6 +183,7 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
                         peerId = "host"sv;
                         deviceId = acc->currentDeviceId();
                         isLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO);
+                        isPeerRecording = shared->isRecording();
                     }
                     auto isHandRaised = shared->isHandRaised(deviceId);
                     auto isVoiceActive = shared->isVoiceActive(streamId);
@@ -196,7 +200,8 @@ Conference::Conference(const std::shared_ptr<Account>& account, bool attachHost)
                                                           isModeratorMuted,
                                                           isModerator,
                                                           isHandRaised,
-                                                          isVoiceActive});
+                                                          isVoiceActive,
+                                                          isPeerRecording});
                 }
             }
             if (auto videoMixer = shared->videoMixer_) {
@@ -659,9 +664,7 @@ Conference::addParticipant(const std::string& participant_id)
 {
     JAMI_DBG("Adding call %s to conference %s", participant_id.c_str(), id_.c_str());
 
-    jami_tracepoint(conference_add_participant,
-                    id_.c_str(),
-                    participant_id.c_str());
+    jami_tracepoint(conference_add_participant, id_.c_str(), participant_id.c_str());
 
     {
         std::lock_guard<std::mutex> lk(participantsMtx_);
@@ -1036,7 +1039,9 @@ Conference::toggleRecording()
     // Notify each participant
     foreachCall([&](auto call) { call->updateRecState(newState); });
 
-    return Recordable::toggleRecording();
+    auto res = Recordable::toggleRecording();
+    updateRecording();
+    return res;
 }
 
 std::string
@@ -1453,6 +1458,21 @@ Conference::muteParticipant(const std::string& participant_id, const bool& state
         muteCall(call->getCallId(), state);
 }
 
+void
+Conference::updateRecording()
+{
+    std::lock_guard<std::mutex> lk(confInfoMutex_);
+    for (auto& info : confInfo_) {
+        if (info.uri.empty()) {
+            info.recording = isRecording();
+        } else if (auto call = getCallWith(std::string(string_remove_suffix(info.uri, '@')),
+                                           info.device)) {
+            info.recording = call->isPeerRecording();
+        }
+    }
+    sendConferenceInfos();
+}
+
 void
 Conference::updateMuted()
 {
@@ -1763,4 +1783,19 @@ Conference::getRemoteId(const std::shared_ptr<jami::Call>& call) const
     return {};
 }
 
+void
+Conference::stopRecording()
+{
+    Recordable::stopRecording();
+    updateRecording();
+}
+
+bool
+Conference::startRecording(const std::string& path)
+{
+    auto res = Recordable::startRecording(path);
+    updateRecording();
+    return res;
+}
+
 } // namespace jami
diff --git a/src/conference.h b/src/conference.h
index 481ceb7ff8bafcd0d32008412acb0090333935c3..d50f6bc12d211671ae8e20e04e7bf0360bb4d745 100644
--- a/src/conference.h
+++ b/src/conference.h
@@ -76,6 +76,7 @@ struct ParticipantInfo
     bool isModerator {false};
     bool handRaised {false};
     bool voiceActivity {false};
+    bool recording {false};
 
     void fromJson(const Json::Value& v)
     {
@@ -93,6 +94,7 @@ struct ParticipantInfo
         isModerator = v["isModerator"].asBool();
         handRaised = v["handRaised"].asBool();
         voiceActivity = v["voiceActivity"].asBool();
+        recording = v["recording"].asBool();
     }
 
     Json::Value toJson() const
@@ -112,6 +114,7 @@ struct ParticipantInfo
         val["isModerator"] = isModerator;
         val["handRaised"] = handRaised;
         val["voiceActivity"] = voiceActivity;
+        val["recording"] = recording;
         return val;
     }
 
@@ -130,7 +133,8 @@ struct ParticipantInfo
                 {"audioModeratorMuted", audioModeratorMuted ? "true" : "false"},
                 {"isModerator", isModerator ? "true" : "false"},
                 {"handRaised", handRaised ? "true" : "false"},
-                {"voiceActivity", voiceActivity ? "true" : "false"}};
+                {"voiceActivity", voiceActivity ? "true" : "false"},
+                {"recording", recording ? "true" : "false"}};
     }
 
     friend bool operator==(const ParticipantInfo& p1, const ParticipantInfo& p2)
@@ -141,7 +145,7 @@ struct ParticipantInfo
                and p1.audioLocalMuted == p2.audioLocalMuted
                and p1.audioModeratorMuted == p2.audioModeratorMuted
                and p1.isModerator == p2.isModerator and p1.handRaised == p2.handRaised
-               and p1.voiceActivity == p2.voiceActivity;
+               and p1.voiceActivity == p2.voiceActivity and p1.recording == p2.recording;
     }
 
     friend bool operator!=(const ParticipantInfo& p1, const ParticipantInfo& p2)
@@ -374,6 +378,7 @@ public:
                     const std::string& streamId,
                     const bool& state);
     void updateMuted();
+    void updateRecording();
 
     void updateVoiceActivity();
 
@@ -390,6 +395,10 @@ public:
      */
     std::vector<DRing::MediaMap> currentMediaList() const;
 
+    // Update layout if recording changes
+    void stopRecording() override;
+    bool startRecording(const std::string& path) override;
+
 private:
     std::weak_ptr<Conference> weak()
     {
diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index 0e865d2b97296fe5d454e4a5702ce087bc7ef0c2..3742b6bb2b7e4af553e1f115575e47ff03ce93d3 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -505,6 +505,9 @@ MediaEncoder::encode(AVFrame* frame, int streamIdx)
     pkt.data = nullptr; // packet data will be allocated by the encoder
     pkt.size = 0;
 
+    if (!encoderCtx)
+        return -1;
+
     ret = avcodec_send_frame(encoderCtx, frame);
     if (ret < 0)
         return -1;
diff --git a/src/media/recordable.h b/src/media/recordable.h
index 8fa1a32b11c9956ef2bd757af6f3c8b459038a7c..1665c8f2cfefca41d69a4137b37306bd39219962 100644
--- a/src/media/recordable.h
+++ b/src/media/recordable.h
@@ -60,7 +60,7 @@ public:
     /**
      * Start recording
      */
-    bool startRecording(const std::string& path);
+    virtual bool startRecording(const std::string& path);
 
     /**
      * Return the file path for this recording
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 0aa586832c1f79d637e9e9f59f04864dab2c09c6..ea12dea0c148b00a86f93dae1b4bfaf0f0bdfbce 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -3489,6 +3489,8 @@ SIPCall::peerRecording(bool state)
         emitSignal<DRing::CallSignal::RemoteRecordingChanged>(id, getPeerNumber(), false);
     }
     peerRecording_ = state;
+    if (auto conf = conf_.lock())
+        conf->updateRecording();
 }
 
 void
diff --git a/test/unitTest/call/conference.cpp b/test/unitTest/call/conference.cpp
index a8fad525f3f94d442ad1bb46d5185965953837a5..f35b6b137fc38022d0377f6c9ad2ab15bacad228 100644
--- a/test/unitTest/call/conference.cpp
+++ b/test/unitTest/call/conference.cpp
@@ -49,6 +49,7 @@ struct CallData
     std::atomic_bool moderatorMuted {false};
     std::atomic_bool raisedHand {false};
     std::atomic_bool active {false};
+    std::atomic_bool recording {false};
 
     void reset()
     {
@@ -60,6 +61,7 @@ struct CallData
         moderatorMuted = false;
         active = false;
         raisedHand = false;
+        recording = false;
     }
 };
 
@@ -96,6 +98,7 @@ private:
     void testAudioConferenceConfInfo();
     void testHostAddRmSecondVideo();
     void testParticipantAddRmSecondVideo();
+    void testPropagateRecording();
 
     CPPUNIT_TEST_SUITE(ConferenceTest);
     CPPUNIT_TEST(testGetConference);
@@ -115,10 +118,12 @@ private:
     CPPUNIT_TEST(testAudioConferenceConfInfo);
     CPPUNIT_TEST(testHostAddRmSecondVideo);
     CPPUNIT_TEST(testParticipantAddRmSecondVideo);
+    CPPUNIT_TEST(testPropagateRecording);
     CPPUNIT_TEST_SUITE_END();
 
     // Common parts
     std::string aliceId;
+    std::atomic_bool hostRecording {false};
     std::string bobId;
     std::string carlaId;
     std::string daviId;
@@ -155,6 +160,7 @@ ConferenceTest::setUp()
     daviCall.reset();
     confId = {};
     confChanged = false;
+    hostRecording = false;
 }
 
 void
@@ -236,22 +242,27 @@ ConferenceTest::registerSignalHandlers()
             for (const auto& infos : participantsInfos) {
                 if (infos.at("uri").find(bobUri) != std::string::npos) {
                     bobCall.active = infos.at("active") == "true";
+                    bobCall.recording = infos.at("recording") == "true";
                     bobCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
                     bobCall.raisedHand = infos.at("handRaised") == "true";
                     bobCall.device = infos.at("device");
                     bobCall.streamId = infos.at("sinkId");
                 } else if (infos.at("uri").find(carlaUri) != std::string::npos) {
                     carlaCall.active = infos.at("active") == "true";
+                    carlaCall.recording = infos.at("recording") == "true";
                     carlaCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
                     carlaCall.raisedHand = infos.at("handRaised") == "true";
                     carlaCall.device = infos.at("device");
                     carlaCall.streamId = infos.at("sinkId");
                 } else if (infos.at("uri").find(daviUri) != std::string::npos) {
                     daviCall.active = infos.at("active") == "true";
+                    daviCall.recording = infos.at("recording") == "true";
                     daviCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
                     daviCall.raisedHand = infos.at("handRaised") == "true";
                     daviCall.device = infos.at("device");
                     daviCall.streamId = infos.at("sinkId");
+                } else if (infos.at("uri").find(aliceUri) != std::string::npos) {
+                    hostRecording = infos.at("recording") == "true";
                 }
             }
             cv.notify_one();
@@ -883,6 +894,31 @@ ConferenceTest::testParticipantAddRmSecondVideo()
     DRing::unregisterSignalHandlers();
 }
 
+void
+ConferenceTest::testPropagateRecording()
+{
+    registerSignalHandlers();
+
+    startConference();
+
+    JAMI_INFO("Play with recording state");
+    DRing::toggleRecording(bobId, bobCall.callId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return bobCall.recording.load(); }));
+
+    DRing::toggleRecording(bobId, bobCall.callId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return !bobCall.recording.load(); }));
+
+    DRing::toggleRecording(aliceId, confId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return hostRecording.load(); }));
+
+    DRing::toggleRecording(aliceId, confId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return !hostRecording.load(); }));
+
+    hangupConference();
+
+    DRing::unregisterSignalHandlers();
+}
+
 } // namespace test
 } // namespace jami