diff --git a/modules/gui/macosx/playlist/VLCPlayerController.h b/modules/gui/macosx/playlist/VLCPlayerController.h
index 7ae1c11254feeb049f124c39422f5a0148a29518..dd1f1f38d8fa32942dbab6e5689508dce27e3de3 100644
--- a/modules/gui/macosx/playlist/VLCPlayerController.h
+++ b/modules/gui/macosx/playlist/VLCPlayerController.h
@@ -29,6 +29,9 @@ NS_ASSUME_NONNULL_BEGIN
 @class VLCTrackMetaData;
 @class VLCProgramMetaData;
 
+extern NSString *VLCPlayerElementaryStreamID;
+extern NSString *VLCTick;
+
 /**
  * Listen to VLCPlayerCurrentMediaItemChanged to notified if the current media item changes for the player
  * @note the affected player object will be the object of the notification
@@ -159,6 +162,13 @@ extern NSString *VLCPlayerAudioDelayChanged;
  */
 extern NSString *VLCPlayerSubtitlesDelayChanged;
 
+/**
+ * Listen to VLCPlayerDelayChangedForSpecificElementaryStream to be notified if the delay of a specific elementary stream changes
+ * @note the affected player object will be the object of the notification
+ * @return the notification's userInfo dictionary will hold key/value pairs for VLCPlayerElementaryStreamID and VLCTick to describe the changes
+ */
+extern NSString *VLCPlayerDelayChangedForSpecificElementaryStream;
+
 /**
  * Listen to VLCPlayerSubtitlesFPSChanged to be notified if the subtitles FPS of the current media changes
  * @note the affected player object will be the object of the notification
@@ -627,6 +637,22 @@ extern const CGFloat VLCVolumeDefault;
  */
 @property (readwrite, nonatomic) vlc_tick_t subtitlesDelay;
 
+/**
+ * fetch the delay for a specific track identified through its elementary stream ID
+ * @return the delay for the track or INT64_MAX if none is set
+ */
+- (vlc_tick_t)delayForElementaryStreamID:(vlc_es_id_t *)esID;
+
+/**
+ * set the delay of a specific track identified through its elementary stream ID
+ * @warning Setting the delay of one specific track will override previous and future changes of delay made through generic calls
+ * @param delay the delay as a valid time or INT64_MAX to reset to the default for the ES category
+ * @param esID the ID for the elementary stream
+ * @param relative use an absolute or relative whence to describe the time
+ * @return VLC_SUCCESS on success
+ */
+- (int)setDelay:(vlc_tick_t)delay forElementaryStreamID:(vlc_es_id_t *)esID relativeWhence:(BOOL)relative;
+
 /**
  * the subtitles fps to correct mismatch between video and text
  * the default value shall be 1.0
diff --git a/modules/gui/macosx/playlist/VLCPlayerController.m b/modules/gui/macosx/playlist/VLCPlayerController.m
index 5c966aacd56ba35b8157d749c85cece56d1328bd..ca310e0bc6d1d32468deac00a8020b527b8808b0 100644
--- a/modules/gui/macosx/playlist/VLCPlayerController.m
+++ b/modules/gui/macosx/playlist/VLCPlayerController.m
@@ -35,6 +35,8 @@
 
 #import <MediaPlayer/MediaPlayer.h>
 
+NSString *VLCPlayerElementaryStreamID = @"VLCPlayerElementaryStreamID";
+NSString *VLCTick = @"VLCTick";
 NSString *VLCPlayerCurrentMediaItemChanged = @"VLCPlayerCurrentMediaItemChanged";
 NSString *VLCPlayerMetadataChangedForCurrentMedia = @"VLCPlayerMetadataChangedForCurrentMedia";
 NSString *VLCPlayerStateChanged = @"VLCPlayerStateChanged";
@@ -57,6 +59,7 @@ NSString *VLCPlayerTeletextPageChanged = @"VLCPlayerTeletextPageChanged";
 NSString *VLCPlayerTeletextTransparencyChanged = @"VLCPlayerTeletextTransparencyChanged";
 NSString *VLCPlayerAudioDelayChanged = @"VLCPlayerAudioDelayChanged";
 NSString *VLCPlayerSubtitlesDelayChanged = @"VLCPlayerSubtitlesDelayChanged";
+NSString *VLCPlayerDelayChangedForSpecificElementaryStream = @"VLCPlayerDelayChangedForSpecificElementaryStream";
 NSString *VLCPlayerSubtitlesFPSChanged = @"VLCPlayerSubtitlesFPSChanged";
 NSString *VLCPlayerSubtitleTextScalingFactorChanged = @"VLCPlayerSubtitleTextScalingFactorChanged";
 NSString *VLCPlayerRecordingChanged = @"VLCPlayerRecordingChanged";
@@ -111,6 +114,7 @@ const CGFloat VLCVolumeDefault = 1.;
 - (void)audioDelayChanged:(vlc_tick_t)audioDelay;
 - (void)rendererChanged:(vlc_renderer_item_t *)newRendererItem;
 - (void)subtitlesDelayChanged:(vlc_tick_t)subtitlesDelay;
+- (void)delayChanged:(vlc_tick_t)trackDelay forTrack:(vlc_es_id_t *)esID;
 - (void)subtitlesFPSChanged:(float)subtitlesFPS;
 - (void)recordingChanged:(BOOL)recording;
 - (void)inputStatsUpdated:(VLCInputStats *)inputStats;
@@ -372,6 +376,18 @@ static void cb_player_track_selection_changed(vlc_player_t *p_player,
     });
 }
 
+static void cb_player_track_delay_changed(vlc_player_t *p_player,
+                                          vlc_es_id_t *es_id,
+                                          vlc_tick_t delay,
+                                          void *p_data)
+{
+    VLC_UNUSED(p_player);
+    dispatch_async(dispatch_get_main_queue(), ^{
+        VLCPlayerController *playerController = (__bridge VLCPlayerController *)p_data;
+        [playerController delayChanged:delay forTrack:es_id];
+    });
+}
+
 static void cb_player_program_list_changed(vlc_player_t *p_player,
                                            enum vlc_player_list_action action,
                                            const struct vlc_player_program *prgm,
@@ -462,6 +478,7 @@ static const struct vlc_player_cbs player_callbacks = {
     cb_player_length_changed,
     cb_player_track_list_changed,
     cb_player_track_selection_changed,
+    cb_player_track_delay_changed,
     cb_player_program_list_changed,
     cb_player_program_selection_changed,
     cb_player_titles_changed,
@@ -1280,6 +1297,31 @@ static const struct vlc_player_aout_cbs player_aout_callbacks = {
     vlc_player_Unlock(_p_player);
 }
 
+- (void)delayChanged:(vlc_tick_t)trackDelay forTrack:(vlc_es_id_t *)esID
+{
+    [_defaultNotificationCenter postNotificationName:VLCPlayerDelayChangedForSpecificElementaryStream
+                                              object:self
+                                            userInfo:@{ VLCPlayerElementaryStreamID : [NSValue valueWithPointer:esID],
+                                                        VLCTick : [NSNumber numberWithLongLong:trackDelay] }];
+
+}
+
+- (vlc_tick_t)delayForElementaryStreamID:(vlc_es_id_t *)esID
+{
+    vlc_player_Lock(_p_player);
+    vlc_tick_t delay = vlc_player_GetEsIdDelay(_p_player, esID);
+    vlc_player_Unlock(_p_player);
+    return delay;
+}
+
+- (int)setDelay:(vlc_tick_t)delay forElementaryStreamID:(vlc_es_id_t *)esID relativeWhence:(BOOL)relative
+{
+    vlc_player_Lock(_p_player);
+    int returnValue = vlc_player_SetEsIdDelay(_p_player, esID, delay, relative ? VLC_PLAYER_WHENCE_RELATIVE : VLC_PLAYER_WHENCE_ABSOLUTE);
+    vlc_player_Unlock(_p_player);
+    return returnValue;
+}
+
 - (void)subtitlesFPSChanged:(float)subtitlesFPS
 {
     _subtitlesFPS = subtitlesFPS;