diff --git a/subprojects/gst-editing-services/ges/ges-enums.c b/subprojects/gst-editing-services/ges/ges-enums.c
index 83b5cd7961..b16e6e1afe 100644
--- a/subprojects/gst-editing-services/ges/ges-enums.c
+++ b/subprojects/gst-editing-services/ges/ges-enums.c
@@ -437,6 +437,9 @@ static GEnumValue transition_types[] = {
   {GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE,
         "GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE",
       "crossfade"},
+  {GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN,
+        "GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN",
+      "fade-in"},
   {0, NULL, NULL}
 };
 
diff --git a/subprojects/gst-editing-services/ges/ges-enums.h b/subprojects/gst-editing-services/ges/ges-enums.h
index ff7a013625..e7ee4ce457 100644
--- a/subprojects/gst-editing-services/ges/ges-enums.h
+++ b/subprojects/gst-editing-services/ges/ges-enums.h
@@ -143,6 +143,7 @@ typedef enum {
  * @GES_VIDEO_STANDARD_TRANSITION_TYPE_WINDSHIELD_V: Two sets of radial hands attached at the midpoints of the top and bottom halves sweep from top to bottom and bottom to top,
  * @GES_VIDEO_STANDARD_TRANSITION_TYPE_WINDSHIELD_H: Two sets of radial hands attached at the midpoints of the left and right halves sweep from left to right and right to left,
  * @GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE: Crossfade
+ * @GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN: Similar to crossfade, but fade in the front video without fading out the background one (Since: 1.22)
  *
  */
 
@@ -218,7 +219,16 @@ typedef enum {
   GES_VIDEO_STANDARD_TRANSITION_TYPE_WINDSHIELD_U = 262,
   GES_VIDEO_STANDARD_TRANSITION_TYPE_WINDSHIELD_V = 263,
   GES_VIDEO_STANDARD_TRANSITION_TYPE_WINDSHIELD_H = 264,
-  GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE = 512
+  GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE = 512,
+  /**
+   * GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN:
+   *
+   * Similar to crossfade, but fade in the front video without fading out
+   * the background one
+   *
+   * Since: 1.22
+   */
+  GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN = 513
 } GESVideoStandardTransitionType;
 
 #define GES_VIDEO_STANDARD_TRANSITION_TYPE_TYPE \
diff --git a/subprojects/gst-editing-services/ges/ges-video-transition.c b/subprojects/gst-editing-services/ges/ges-video-transition.c
index e84af2569f..a917a9a03a 100644
--- a/subprojects/gst-editing-services/ges/ges-video-transition.c
+++ b/subprojects/gst-editing-services/ges/ges-video-transition.c
@@ -337,10 +337,14 @@ ges_video_transition_create_element (GESTrackElement * object)
   GESVideoTransition *self;
   GESVideoTransitionPrivate *priv;
   const gchar *smpte_properties[] = { "invert", "border", NULL };
+  gboolean is_fade;
 
   self = GES_VIDEO_TRANSITION (object);
   priv = self->priv;
 
+  is_fade = (priv->type == GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ||
+      priv->type == GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN);
+
   GST_LOG ("creating a video bin");
 
   topbin = gst_bin_new ("transition-bin");
@@ -373,11 +377,9 @@ ges_video_transition_create_element (GESTrackElement * object)
   g_object_set (priv->mixer_sinka, "zorder", 0, NULL);
   g_object_set (priv->mixer_sinkb, "zorder", 1, NULL);
   gst_util_set_object_arg (G_OBJECT (priv->mixer_sinka), "operator",
-      priv->type ==
-      GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ? "source" : "over");
+      is_fade ? "source" : "over");
   gst_util_set_object_arg (G_OBJECT (priv->mixer_sinkb), "operator",
-      priv->type ==
-      GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ? "add" : "over");
+      is_fade ? "add" : "over");
 
   fast_element_link (mixer, priv->positioner);
 
@@ -480,6 +482,13 @@ ges_video_transition_update_control_sources (GESVideoTransition * self,
         (priv->fade_out_control_source, duration, 1.0, 0.0);
     ges_video_transition_update_control_source (priv->smpte_control_source,
         duration, 0.0, 0.0);
+  } else if (type == GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN) {
+    ges_video_transition_update_control_source
+        (priv->fade_in_control_source, duration, 0.0, 1.0);
+    ges_video_transition_update_control_source
+        (priv->fade_out_control_source, duration, 1.0, 1.0);
+    ges_video_transition_update_control_source (priv->smpte_control_source,
+        duration, 0.0, 0.0);
   } else {
     ges_video_transition_update_control_source
         (priv->fade_in_control_source, duration, 1.0, 1.0);
@@ -531,6 +540,7 @@ ges_video_transition_set_transition_type_internal (GESVideoTransition
     * self, GESVideoStandardTransitionType type)
 {
   GESVideoTransitionPrivate *priv = self->priv;
+  gboolean is_fade;
 
   GST_DEBUG ("%p %d => %d", self, priv->type, type);
 
@@ -547,17 +557,17 @@ ges_video_transition_set_transition_type_internal (GESVideoTransition
   ges_video_transition_update_control_sources (self, type);
 
   priv->type = type;
+  is_fade = (type == GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ||
+      type == GES_VIDEO_STANDARD_TRANSITION_TYPE_FADE_IN);
 
-  if (type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) {
+  if (!is_fade) {
     g_object_set (priv->smpte, "type", (gint) type, NULL);
   }
 
   gst_util_set_object_arg (G_OBJECT (priv->mixer_sinka), "operator",
-      priv->type ==
-      GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ? "source" : "over");
+      is_fade ? "source" : "over");
   gst_util_set_object_arg (G_OBJECT (priv->mixer_sinkb), "operator",
-      priv->type ==
-      GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE ? "add" : "over");
+      is_fade ? "add" : "over");
 
   return TRUE;
 }