diff --git a/front/src/config/i18n/de.json b/front/src/config/i18n/de.json
index 5699ffef2a..f0afb1eebc 100644
--- a/front/src/config/i18n/de.json
+++ b/front/src/config/i18n/de.json
@@ -2021,6 +2021,7 @@
         "description": "Diese Aktion lässt Gladys auf dem ausgewählten Lautsprecher sprechen.",
         "needGladysPlus": "Erfordert Gladys Plus, da die Text-to-Speech-APIs kostenpflichtig sind.",
         "deviceLabel": "Lautsprecher",
+        "volumeLabel": "Volumen",
         "textLabel": "Nachricht zum Sprechen auf dem Lautsprecher",
         "variablesExplanation": "Um eine Variable einzufügen, gib \"{{\" ein. Hinweis: Du musst vor diesem Block eine Variable in einer \"Letzten Zustand abrufen\"-Aktion definiert haben."
       }
diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json
index 79fdb14478..c77eddbbbd 100644
--- a/front/src/config/i18n/en.json
+++ b/front/src/config/i18n/en.json
@@ -2021,6 +2021,7 @@
         "description": "This action will make Gladys speak on the selected speaker.",
         "needGladysPlus": "Requires Gladys Plus as Text-To-Speech APIs are paid.",
         "deviceLabel": "Speaker",
+        "volumeLabel": "Volume",
         "textLabel": "Message to speak on the speaker",
         "variablesExplanation": "To inject a variable, type '{{ '. Note: You must have defined a variable beforehand in a 'Retrieve Last State' action placed before this message block."
       }
diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json
index 0ba3a52b4a..56ed687d54 100644
--- a/front/src/config/i18n/fr.json
+++ b/front/src/config/i18n/fr.json
@@ -2021,6 +2021,7 @@
         "description": "Cette action fera parler Gladys sur l'enceinte sélectionnée.",
         "needGladysPlus": "Nécessite Gladys Plus car les API de \"Text To Speech\" sont payantes.",
         "deviceLabel": "Enceinte",
+        "volumeLabel": "Volume",
         "textLabel": "Message à dire sur l'enceinte",
         "variablesExplanation": "Pour injecter une variable, tapez '{{ '. Attention, vous devez avoir défini une variable auparavant dans une action 'Récupérer le dernier état' placé avant ce bloc message."
       }
diff --git a/front/src/routes/scene/edit-scene/actions/PlayNotification.jsx b/front/src/routes/scene/edit-scene/actions/PlayNotification.jsx
index 96cb7eff9c..07d3bec503 100644
--- a/front/src/routes/scene/edit-scene/actions/PlayNotification.jsx
+++ b/front/src/routes/scene/edit-scene/actions/PlayNotification.jsx
@@ -26,6 +26,9 @@ class PlayNotification extends Component {
       console.error(e);
     }
   };
+  updateVolume = e => {
+    this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'volume', e.target.value);
+  };
   updateText = text => {
     this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'text', text);
   };
@@ -84,6 +87,24 @@ class PlayNotification extends Component {
             onChange={this.handleDeviceChange}
           />
         </div>
+        <div class="form-group">
+          <label class="form-label">
+            <Text id="editScene.actionsCard.playNotification.volumeLabel" />
+            <span class="form-required">
+              <Text id="global.requiredField" />
+            </span>
+          </label>
+          <input type="text" class="form-control" value={props.action.volume} disabled />
+          <input
+            type="range"
+            value={props.action.volume}
+            onChange={this.updateVolume}
+            class="form-control custom-range"
+            step="1"
+            min={0}
+            max={100}
+          />
+        </div>
         <div class="form-group">
           <label class="form-label">
             <Text id="editScene.actionsCard.playNotification.textLabel" />{' '}
diff --git a/server/lib/device/device.setValue.js b/server/lib/device/device.setValue.js
index dc472c2078..b2d97cca3f 100644
--- a/server/lib/device/device.setValue.js
+++ b/server/lib/device/device.setValue.js
@@ -7,10 +7,11 @@ const { NotFoundError } = require('../../utils/coreErrors');
  * @param {object} device - The device to control.
  * @param {object} deviceFeature - The deviceFeature to control.
  * @param {string|number} value - The new state to set.
+ * @param {object} options - Optional configs.
  * @example
  * device.setValue(device, deviceFeature);
  */
-async function setValue(device, deviceFeature, value) {
+async function setValue(device, deviceFeature, value, options = {}) {
   const service = this.serviceManager.getService(device.service.name);
   if (service === null) {
     throw new NotFoundError(`Service ${device.service.name} was not found.`);
@@ -18,7 +19,7 @@ async function setValue(device, deviceFeature, value) {
   if (typeof get(service, 'device.setValue') !== 'function') {
     throw new NotFoundError(`Function device.setValue in service ${device.service.name} does not exist.`);
   }
-  await service.device.setValue(device, deviceFeature, value);
+  await service.device.setValue(device, deviceFeature, value, options);
   // If device has feedback, the feedback will be sent and saved
   // If value is a string, no need to save it
   // @ts-ignore
diff --git a/server/lib/scene/scene.actions.js b/server/lib/scene/scene.actions.js
index 6f214b803c..30dbe20346 100644
--- a/server/lib/scene/scene.actions.js
+++ b/server/lib/scene/scene.actions.js
@@ -587,7 +587,7 @@ const actionsFunc = {
     // Get TTS URL
     const { url } = await self.gateway.getTTSApiUrl({ text: messageWithVariables });
     // Play TTS Notification on device
-    await self.device.setValue(device, deviceFeature, url);
+    await self.device.setValue(device, deviceFeature, url, { volume: action.volume });
   },
   [ACTIONS.SMS.SEND]: async (self, action, scope) => {
     const freeMobileService = self.service.getService('free-mobile');
diff --git a/server/models/scene.js b/server/models/scene.js
index 7c91a90c7b..e3f1ad617f 100644
--- a/server/models/scene.js
+++ b/server/models/scene.js
@@ -65,6 +65,10 @@ const actionSchema = Joi.array().items(
       message: Joi.string().allow(''),
       blinking_time: Joi.number(),
       blinking_speed: Joi.string().valid('slow', 'medium', 'fast'),
+      volume: Joi.number()
+        .integer()
+        .max(100)
+        .min(0),
     }),
   ),
 );
diff --git a/server/services/airplay/lib/airplay.setValue.js b/server/services/airplay/lib/airplay.setValue.js
index e534c53d2d..1923aca9dc 100644
--- a/server/services/airplay/lib/airplay.setValue.js
+++ b/server/services/airplay/lib/airplay.setValue.js
@@ -6,10 +6,11 @@ const logger = require('../../../utils/logger');
  * @param {object} device - Updated Gladys device.
  * @param {object} deviceFeature - Updated Gladys device feature.
  * @param {string|number} value - The new device feature value.
+ * @param {object} options - Optional configs.
  * @example
- * setValue(device, deviceFeature, 0);
+ * setValue(device, deviceFeature, 0, 30);
  */
-async function setValue(device, deviceFeature, value) {
+async function setValue(device, deviceFeature, value, options) {
   const deviceName = device.external_id.split(':')[1];
   const ipAddress = this.deviceIpAddresses.get(deviceName);
   if (!ipAddress) {
@@ -19,7 +20,7 @@ async function setValue(device, deviceFeature, value) {
   if (deviceFeature.type === DEVICE_FEATURE_TYPES.MUSIC.PLAY_NOTIFICATION) {
     const client = new this.Airtunes();
     const airplayDevice = client.add(ipAddress, {
-      volume: 70,
+      volume: options?.volume || 70,
     });
     let decodeProcess;
 
diff --git a/server/services/google-cast/lib/google_cast.setValue.js b/server/services/google-cast/lib/google_cast.setValue.js
index 9224d8de11..ee787918fc 100644
--- a/server/services/google-cast/lib/google_cast.setValue.js
+++ b/server/services/google-cast/lib/google_cast.setValue.js
@@ -1,3 +1,5 @@
+const { promisify } = require('util');
+
 const { DEVICE_FEATURE_TYPES } = require('../../../utils/constants');
 const logger = require('../../../utils/logger');
 /**
@@ -5,10 +7,11 @@ const logger = require('../../../utils/logger');
  * @param {object} device - Updated Gladys device.
  * @param {object} deviceFeature - Updated Gladys device feature.
  * @param {string|number} value - The new device feature value.
+ * @param {object} options - Optional configs.
  * @example
  * setValue(device, deviceFeature, 0);
  */
-async function setValue(device, deviceFeature, value) {
+async function setValue(device, deviceFeature, value, options) {
   const deviceName = device.external_id.split(':')[1];
   const ipAddress = this.deviceIpAddresses.get(deviceName);
   if (!ipAddress) {
@@ -19,8 +22,16 @@ async function setValue(device, deviceFeature, value) {
     const { Client, DefaultMediaReceiver } = this.googleCastLib;
     const client = new Client();
 
-    client.connect(ipAddress, () => {
+    client.connect(ipAddress, async () => {
       logger.debug('Google Cast Connected, launching app ...');
+      const getVolume = promisify(client.getVolume.bind(client));
+      const setVolume = promisify(client.setVolume.bind(client));
+
+      const { level } = await getVolume();
+
+      if (options.volume) {
+        await setVolume({ level: options.volume / 100 });
+      }
 
       client.launch(DefaultMediaReceiver, (err, player) => {
         const media = {
@@ -38,8 +49,11 @@ async function setValue(device, deviceFeature, value) {
           },
         };
 
-        player.on('status', (status) => {
+        player.on('status', async (status) => {
           logger.debug('status broadcast playerState=%s', status.playerState);
+          if (status.idleReason === 'FINISHED') {
+            await setVolume({ level });
+          }
         });
 
         logger.debug('app "%s" launched, loading media %s ...', player.session.displayName, media.contentId);
diff --git a/server/services/sonos/lib/sonos.setValue.js b/server/services/sonos/lib/sonos.setValue.js
index d24064f7f5..0243448407 100644
--- a/server/services/sonos/lib/sonos.setValue.js
+++ b/server/services/sonos/lib/sonos.setValue.js
@@ -4,10 +4,11 @@ const { DEVICE_FEATURE_TYPES } = require('../../../utils/constants');
  * @param {object} device - Updated Gladys device.
  * @param {object} deviceFeature - Updated Gladys device feature.
  * @param {string|number} value - The new device feature value.
+ * @param {object} options - Optional configs.
  * @example
  * setValue(device, deviceFeature, 0);
  */
-async function setValue(device, deviceFeature, value) {
+async function setValue(device, deviceFeature, value, options) {
   const deviceUuid = device.external_id.split(':')[1];
   const sonosDevice = this.manager.Devices.find((d) => d.uuid === deviceUuid);
   if (deviceFeature.type === DEVICE_FEATURE_TYPES.MUSIC.PLAY) {
@@ -30,7 +31,7 @@ async function setValue(device, deviceFeature, value) {
     await sonosDevice.PlayNotification({
       trackUri: value,
       onlyWhenPlaying: false,
-      volume: 45, // Set the volume for the notification (and revert back afterwards)
+      volume: options?.volume || 45, // Set the volume for the notification (and revert back afterwards)
       timeout: 20, // If the events don't work (to see when it stops playing) or if you turned on a stream,
       // it will revert back after this amount of seconds.
       delayMs: 700, // Pause between commands in ms, (when sonos fails to play sort notification sounds).
diff --git a/server/test/services/airplay/lib/airplay.setValue.test.js b/server/test/services/airplay/lib/airplay.setValue.test.js
index eeb91d02f0..848b4fe509 100644
--- a/server/test/services/airplay/lib/airplay.setValue.test.js
+++ b/server/test/services/airplay/lib/airplay.setValue.test.js
@@ -88,12 +88,18 @@ describe('AirplayHandler.setValue', () => {
     await airplayHandler.setValue(device, device.features[0], 'http://play-url.com');
     sinon.assert.calledOnce(pipe);
   });
+  it('should talk on speaker with custom volume', async () => {
+    airplayHandler.scanTimeout = 1;
+    const devices = await airplayHandler.scan();
+    const device = devices[0];
+    await airplayHandler.setValue(device, device.features[0], 'http://play-url.com', { volume: 30 });
+  });
   it('should return device not found', async () => {
     airplayHandler.scanTimeout = 1;
     const device = {
       external_id: 'airplay:toto',
     };
-    const promise = airplayHandler.setValue(device, {}, 'http://play-url.com');
+    const promise = airplayHandler.setValue(device, {}, 'http://play-url.com', { volume: 30 });
     await assert.isRejected(promise, 'Device not found on network');
   });
 });
diff --git a/server/test/services/google-cast/lib/google_cast.setValue.test.js b/server/test/services/google-cast/lib/google_cast.setValue.test.js
index 0059dd0ab3..36b28aa24a 100644
--- a/server/test/services/google-cast/lib/google_cast.setValue.test.js
+++ b/server/test/services/google-cast/lib/google_cast.setValue.test.js
@@ -37,6 +37,16 @@ class GoogleCastClient {
     cb({ message: 'this is an error' });
   }
 
+  // eslint-disable-next-line class-methods-use-this
+  getVolume(cb) {
+    cb(null, { level: 1 });
+  }
+
+  // eslint-disable-next-line class-methods-use-this
+  setVolume(volume, cb) {
+    cb(null, 30);
+  }
+
   // eslint-disable-next-line class-methods-use-this
   close() {}
 }
@@ -80,14 +90,14 @@ describe('GoogleCastHandler.setValue', () => {
     googleCastHandler.scanTimeout = 1;
     const devices = await googleCastHandler.scan();
     const device = devices[0];
-    await googleCastHandler.setValue(device, device.features[0], 'http://play-url.com');
+    await googleCastHandler.setValue(device, device.features[0], 'http://play-url.com', { volume: 30 });
   });
   it('should return device not found', async () => {
     googleCastHandler.scanTimeout = 1;
     const device = {
       external_id: 'google_cast:toto',
     };
-    const promise = googleCastHandler.setValue(device, {}, 'http://play-url.com');
+    const promise = googleCastHandler.setValue(device, {}, 'http://play-url.com', { volume: 30 });
     await assert.isRejected(promise, 'Device not found on network');
   });
 });
diff --git a/server/test/services/sonos/lib/sonos.setValue.test.js b/server/test/services/sonos/lib/sonos.setValue.test.js
index b1e332a53f..4fef0f080c 100644
--- a/server/test/services/sonos/lib/sonos.setValue.test.js
+++ b/server/test/services/sonos/lib/sonos.setValue.test.js
@@ -197,4 +197,31 @@ describe('SonosHandler.setValue', () => {
       delayMs: 700,
     });
   });
+  it('should play notification on Sonos and change volume', async () => {
+    const device = {
+      name: 'My sonos',
+      external_id: 'sonos:test-uuid',
+      service_id: 'ffa13430-df93-488a-9733-5c540e9558e0',
+      should_poll: false,
+    };
+    const deviceFeature = {
+      name: 'My sonos - Play notification',
+      external_id: 'sonos:test-uuid:play-notification',
+      category: 'music',
+      type: 'play_notification',
+      min: 1,
+      max: 1,
+      keep_history: false,
+      read_only: false,
+      has_feedback: false,
+    };
+    await sonosHandler.setValue(device, deviceFeature, 'http://test.com', { volume: 30 });
+    assert.calledWith(devicePlayNotification, {
+      onlyWhenPlaying: false,
+      timeout: 20,
+      trackUri: 'http://test.com',
+      volume: 30,
+      delayMs: 700,
+    });
+  });
 });