diff --git a/doc/filters.texi b/doc/filters.texi
index 0da5702..a6110e4 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1078,7 +1078,7 @@ For more information about libfreetype, check:
 Apply fade-in/out effect to input video.
 
 It accepts the parameters:
-@var{type}:@var{start_frame}:@var{nb_frames}
+@var{type}:@var{start_frame}:@var{nb_frames}[:@var{options}]
 
 @var{type} specifies if the effect type, can be either "in" for
 fade-in, or "out" for a fade-out effect.
@@ -1091,6 +1091,22 @@ effect has to last. At the end of the fade-in effect the output video
 will have the same intensity as the input video, at the end of the
 fade-out transition the output video will be completely black.
 
+This source accepts an optional sequence of @var{key}=@var{value} pairs,
+separated by ":". The description of the accepted options follows.
+
+@table @option
+
+@item type, t
+See @var{type}
+
+@item in_point, i
+See @var{start_frame}
+
+@item duration, d
+See @var{nb_frames}
+
+@end table
+
 A few usage examples follow, usable too as test scenarios.
 @example
 # fade in first 30 frames of video
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index 5032019..6f750b4 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -25,48 +25,130 @@
  * based heavily on vf_negate.c by Bobby Bingham
  */
 
+#include "libavutil/avstring.h"
+#include "libavutil/eval.h"
+#include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "drawutils.h"
 #include "internal.h"
 
 typedef struct {
+    const AVClass *class;
     int factor, fade_per_frame;
     unsigned int frame_index, start_frame, stop_frame;
     int hsub, vsub, bpp;
     unsigned int black_level, black_level_scaled;
+
+    char *type, *start_expr, *count_expr;
 } FadeContext;
 
+#define OFFSET(x) offsetof(FadeContext, x)
+
+static const AVOption fade_options[] = {
+    { "type",     "set the fade direction",                     OFFSET(type),       AV_OPT_TYPE_STRING, {.str = "in" }, CHAR_MIN, CHAR_MAX },
+    { "t",        "set the fade direction",                     OFFSET(type),       AV_OPT_TYPE_STRING, {.str = "in" }, CHAR_MIN, CHAR_MAX },
+    { "in_point", "set expression of frame to start fading",    OFFSET(start_expr), AV_OPT_TYPE_STRING, {.str = "0"  }, CHAR_MIN, CHAR_MAX },
+    { "i",        "set expression of frame to start fading",    OFFSET(start_expr), AV_OPT_TYPE_STRING, {.str = "0"  }, CHAR_MIN, CHAR_MAX },
+    { "duration", "set expression for fade duration in frames", OFFSET(count_expr), AV_OPT_TYPE_STRING, {.str = "25" }, CHAR_MIN, CHAR_MAX },
+    { "d",        "set expression for fade duration in frames", OFFSET(count_expr), AV_OPT_TYPE_STRING, {.str = "25" }, CHAR_MIN, CHAR_MAX },
+    {NULL},
+};
+
+static const char *fade_get_name(void *ctx)
+{
+    return "fade";
+}
+
+static const AVClass fade_class = {
+    "FadeContext",
+    fade_get_name,
+    fade_options
+};
+
 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 {
     FadeContext *fade = ctx->priv;
     unsigned int nb_frames;
-    char in_out[4];
+    double res;
+    int ret = 0;
+    char *args1, *expr, *bufptr = NULL;
 
-    if (!args ||
-        sscanf(args, " %3[^:]:%u:%u", in_out, &fade->start_frame, &nb_frames) != 3) {
-        av_log(ctx, AV_LOG_ERROR,
-               "Expected 3 arguments '(in|out):#:#':'%s'\n", args);
-        return AVERROR(EINVAL);
+    fade->class = &fade_class;
+    av_opt_set_defaults(fade);
+
+    if (!(args1 = av_strdup(args))) {
+        ret = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    if (expr = av_strtok(args1, ":", &bufptr)) {
+        if (!(fade->type = av_strdup(expr))) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
+    }
+    if (expr = av_strtok(NULL, ":", &bufptr)) {
+        if (!(fade->start_expr = av_strdup(expr))) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
+    }
+    if (expr = av_strtok(NULL, ":", &bufptr)) {
+        if (!(fade->count_expr = av_strdup(expr))) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
     }
 
-    nb_frames = nb_frames ? nb_frames : 1;
+    if (bufptr && (ret = av_set_options_string(fade, bufptr, "=", ":")) < 0)
+        goto end;
+
+    if ((ret = av_expr_parse_and_eval(&res, (expr = fade->start_expr), NULL, NULL,
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
+        goto fail;
+    fade->start_frame = res;
+    if ((ret = av_expr_parse_and_eval(&res, (expr = fade->count_expr), NULL, NULL,
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
+        goto fail;
+    nb_frames = res;
+
     fade->fade_per_frame = (1 << 16) / nb_frames;
-    if (!strcmp(in_out, "in"))
+    if (!strcmp(fade->type, "in"))
         fade->factor = 0;
-    else if (!strcmp(in_out, "out")) {
+    else if (!strcmp(fade->type, "out")) {
         fade->fade_per_frame = -fade->fade_per_frame;
         fade->factor = (1 << 16);
     } else {
         av_log(ctx, AV_LOG_ERROR,
-               "first argument must be 'in' or 'out':'%s'\n", in_out);
-        return AVERROR(EINVAL);
+               "type argument must be 'in' or 'out':'%s'\n", fade->type);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
     fade->stop_frame = fade->start_frame + nb_frames;
 
     av_log(ctx, AV_LOG_INFO,
            "type:%s start_frame:%d nb_frames:%d\n",
-           in_out, fade->start_frame, nb_frames);
-    return 0;
+           fade->type, fade->start_frame, nb_frames);
+
+end:
+    av_free(args1);
+    return ret;
+
+fail:
+    av_free(args1);
+    av_log(ctx, AV_LOG_ERROR,
+           "Error when evaluating the expression '%s'\n", expr);
+    return ret;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    FadeContext *fade = ctx->priv;
+
+    av_freep(&fade->type);
+    av_freep(&fade->start_expr);
+    av_freep(&fade->count_expr);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -163,6 +245,7 @@ AVFilter avfilter_vf_fade = {
     .name          = "fade",
     .description   = NULL_IF_CONFIG_SMALL("Fade in/out input video"),
     .init          = init,
+    .uninit        = uninit,
     .priv_size     = sizeof(FadeContext),
     .query_formats = query_formats,
 
