diff --git a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
index e0fbf321e6238fae0561b83a2556e5d4e06c2109..5e82844e77a41e5146ae54c67a4e900658fac6e0 100644
--- a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
@@ -7,6 +7,7 @@ import handleMeetingLocksChange from './handlers/meetingLockChange';
 import handleUserLockChange from './handlers/userLockChange';
 import handleRecordingStatusChange from './handlers/recordingStatusChange';
 import handleRecordingTimerChange from './handlers/recordingTimerChange';
+import handleTimeRemainingUpdate from './handlers/timeRemainingUpdate';
 import handleChangeWebcamOnlyModerator from './handlers/webcamOnlyModerator';
 
 RedisPubSub.on('MeetingCreatedEvtMsg', handleMeetingCreation);
@@ -18,3 +19,4 @@ RedisPubSub.on('UserLockedInMeetingEvtMsg', handleUserLockChange);
 RedisPubSub.on('RecordingStatusChangedEvtMsg', handleRecordingStatusChange);
 RedisPubSub.on('UpdateRecordingTimerEvtMsg', handleRecordingTimerChange);
 RedisPubSub.on('WebcamsOnlyForModeratorChangedEvtMsg', handleChangeWebcamOnlyModerator);
+RedisPubSub.on('MeetingTimeRemainingUpdateEvtMsg', handleTimeRemainingUpdate);
diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js
index c0fe2430c4ddfe5caf55f01166ac827538666e75..024bf29a26ba8d2e1925c8f6d7d12342687a97d6 100644
--- a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js
+++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js
@@ -3,6 +3,8 @@ import addMeeting from '../modifiers/addMeeting';
 
 export default function handleMeetingCreation({ body }) {
   const meeting = body.props;
+  const durationInSecods = (meeting.durationProps.duration * 60);
+  meeting.durationProps.timeRemaining = durationInSecods;
   check(meeting, Object);
 
   return addMeeting(meeting);
diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js
new file mode 100644
index 0000000000000000000000000000000000000000..619b52d74a33756cc1580c593ea3233f841f98f0
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/timeRemainingUpdate.js
@@ -0,0 +1,30 @@
+import { check } from 'meteor/check';
+import Meetings from '/imports/api/meetings';
+import Logger from '/imports/startup/server/logger';
+
+export default function handleTimeRemainingUpdate({ body }, meetingId) {
+  check(meetingId, String);
+
+  check(body, {
+    timeLeftInSec: Number,
+  });
+  const { timeLeftInSec } = body;
+
+  const selector = {
+    meetingId,
+  };
+
+  const modifier = {
+    $set: {
+      'durationProps.timeRemaining': timeLeftInSec,
+    },
+  };
+
+  const cb = (err) => {
+    if (err) {
+      Logger.error(`Changing recording time: ${err}`);
+    }
+  };
+
+  return Meetings.upsert(selector, modifier, cb);
+}
diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js
index f8011fd0d32225429338b6252eefd78af4307bc8..ba0bf11748d28f3c41431aec6bfbc7313184bf5d 100644
--- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js
+++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js
@@ -36,6 +36,7 @@ export default function addMeeting(meeting) {
       userInactivityInspectTimerInMinutes: Number,
       userInactivityThresholdInMinutes: Number,
       userActivitySignResponseDelayInMinutes: Number,
+      timeRemaining: Number,
     },
     welcomeProp: {
       welcomeMsg: String,
diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx
index 422ce26f2ae11fdfd3b3c20e94d9db511b7a0764..bcbb2cacc88da92a881a97b025e9486032de3fec 100644
--- a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-remaining-time/container.jsx
@@ -77,7 +77,9 @@ const startCounter = (sec, set, get, interval) => {
 };
 
 
-export default injectIntl(withTracker(({ breakoutRoom, intl, messageDuration }) => {
+export default injectIntl(withTracker(({
+  breakoutRoom, intl, messageDuration, timeEndedMessage,
+}) => {
   const data = {};
   if (breakoutRoom) {
     const roomRemainingTime = breakoutRoom.timeRemaining;
@@ -94,13 +96,13 @@ export default injectIntl(withTracker(({ breakoutRoom, intl, messageDuration })
     clearInterval(timeRemainingInterval);
   }
 
-  if (timeRemaining) {
+  if (timeRemaining >= 0) {
     if (timeRemaining > 0) {
       const time = getTimeRemaining();
       data.message = intl.formatMessage(messageDuration, { 0: humanizeSeconds(time) });
     } else {
       clearInterval(timeRemainingInterval);
-      data.message = intl.formatMessage(intlMessages.breakoutWillClose);
+      data.message = intl.formatMessage(timeEndedMessage || intlMessages.breakoutWillClose);
     }
   } else if (breakoutRoom) {
     data.message = intl.formatMessage(intlMessages.calculatingBreakoutTimeRemaining);
diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
index 3ed8f4afef2ecc69440aea6a2234fe8506d739a1..c833284b0ab6def4904582b79f6b6abe68cd84f1 100644
--- a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx
@@ -9,7 +9,6 @@ const COLORS = [
 ];
 
 const propTypes = {
-  children: PropTypes.string.isRequired,
   color: PropTypes.oneOf(COLORS),
 };
 
@@ -18,14 +17,14 @@ const defaultProps = {
 };
 
 const NotificationsBar = (props) => {
-  const { color } = props;
+  const { color, children } = props;
 
   return (
     <div
       role="alert"
       className={cx(styles.notificationsBar, styles[color])}
     >
-      {props.children}
+      {children}
     </div>
   );
 };
diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx
index 063e720d58965837a24f241a2d4fbcf54dc65e12..b47463231debaace78d196f8e87f6cb597d4ec8f 100644
--- a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx
@@ -4,8 +4,10 @@ import React from 'react';
 import { defineMessages, injectIntl } from 'react-intl';
 import _ from 'lodash';
 import Auth from '/imports/ui/services/auth';
+import Meetings from '/imports/api/meetings';
 import humanizeSeconds from '/imports/utils/humanizeSeconds';
 import NavBarService from '../nav-bar/service';
+import BreakoutRemainingTime from '/imports/ui/components/breakout-room/breakout-remaining-time/container';
 
 import NotificationsBar from './component';
 
@@ -43,6 +45,14 @@ const intlMessages = defineMessages({
     id: 'app.calculatingBreakoutTimeRemaining',
     description: 'Message that tells that the remaining time is being calculated',
   },
+  meetingTimeRemaining: {
+    id: 'app.meeting.meetingTimeRemaining',
+    description: 'Message that tells how much time is remaining for the meeting',
+  },
+  meetingWillClose: {
+    id: 'app.meeting.meetingTimeHasEnded',
+    description: 'Message that tells time has ended and meeting will close',
+  },
 });
 
 const NotificationsBarContainer = (props) => {
@@ -60,22 +70,14 @@ const NotificationsBarContainer = (props) => {
 };
 
 let retrySeconds = 0;
-let timeRemaining = 0;
 const retrySecondsDep = new Tracker.Dependency();
-const timeRemainingDep = new Tracker.Dependency();
 let retryInterval = null;
-let timeRemainingInterval = null;
 
 const getRetrySeconds = () => {
   retrySecondsDep.depend();
   return retrySeconds;
 };
 
-const getTimeRemaining = () => {
-  timeRemainingDep.depend();
-  return timeRemaining;
-};
-
 const setRetrySeconds = (sec = 0) => {
   if (sec !== retrySeconds) {
     retrySeconds = sec;
@@ -83,13 +85,6 @@ const setRetrySeconds = (sec = 0) => {
   }
 };
 
-const setTimeRemaining = (sec = 0) => {
-  if (sec !== timeRemaining) {
-    timeRemaining = sec;
-    timeRemainingDep.changed();
-  }
-};
-
 const startCounter = (sec, set, get, interval) => {
   clearInterval(interval);
   set(sec);
@@ -137,37 +132,36 @@ export default injectIntl(withTracker(({ intl }) => {
     const currentBreakout = breakouts.find(b => b.breakoutId === meetingId);
 
     if (currentBreakout) {
-      const roomRemainingTime = currentBreakout.timeRemaining;
-
-      if (!timeRemainingInterval && roomRemainingTime) {
-        timeRemainingInterval = startCounter(
-          roomRemainingTime,
-          setTimeRemaining,
-          getTimeRemaining,
-          timeRemainingInterval,
-        );
-      }
-    } else if (timeRemainingInterval) {
-      clearInterval(timeRemainingInterval);
+      data.message = (
+        <BreakoutRemainingTime
+          breakoutRoom={currentBreakout}
+          messageDuration={intlMessages.breakoutTimeRemaining}
+          timeEndedMessage={intlMessages.breakoutWillClose}
+        />
+      );
     }
+  }
 
-    timeRemaining = getTimeRemaining();
 
-    if (timeRemaining) {
-      if (timeRemaining > 0) {
-        data.message = intl.formatMessage(
-          intlMessages.breakoutTimeRemaining,
-          { 0: humanizeSeconds(timeRemaining) },
-        );
-      } else {
-        clearInterval(timeRemainingInterval);
-        data.message = intl.formatMessage(intlMessages.breakoutWillClose);
-      }
-    } else if (currentBreakout) {
-      data.message = intl.formatMessage(intlMessages.calculatingBreakoutTimeRemaining);
+  const Meeting = Meetings.findOne({ meetingId: Auth.meetingID });
+
+  if (Meeting) {
+    const { timeRemaining } = Meeting.durationProps;
+    const { isBreakout } = Meeting.meetingProp;
+    const underThirtyMin = timeRemaining && timeRemaining <= (30 * 60);
+
+    if (underThirtyMin && !isBreakout) {
+      data.message = (
+        <BreakoutRemainingTime
+          breakoutRoom={Meeting.durationProps}
+          messageDuration={intlMessages.meetingTimeRemaining}
+          timeEndedMessage={intlMessages.meetingWillClose}
+        />
+      );
     }
   }
 
+
   data.color = 'primary';
   return data;
 })(NotificationsBarContainer));
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index 93c91b147b31556fe037d69f046b127176f4c759..c5237c604c4e1e2e720eb4711acf51512d699519 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -59,6 +59,8 @@
     "app.media.screenshare.end": "Screenshare has ended",
     "app.media.screenshare.safariNotSupported": "Screenshare is currently not supported by Safari. Please, use Firefox or Google Chrome.",
     "app.meeting.ended": "This session has ended",
+    "app.meeting.meetingTimeRemaining": "Meeting time remaining: {0}",
+    "app.meeting.meetingTimeHasEnded": "Time ended. Meeting will close soon",
     "app.meeting.endedMessage": "You will be forwarded back to the home screen",
     "app.presentation.presentationToolbar.prevSlideLabel": "Previous slide",
     "app.presentation.presentationToolbar.prevSlideDesc": "Change the presentation to the previous slide",