diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index 618ba193ff..029980063d 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -307,16 +307,10 @@ int enc_open(void *opaque, const AVFrame *frame)
     if (ost->bitexact)
         enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
 
-    if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
-        av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
+    if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)
+        enc_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE;
 
-    if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) {
-        ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
-        if (ret < 0)
-            return ret;
-    }
-
-    av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY);
+    enc_ctx->flags |= AV_CODEC_FLAG_FRAME_DURATION;
 
     ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
     if (ret < 0) {
@@ -325,7 +319,7 @@ int enc_open(void *opaque, const AVFrame *frame)
         return ret;
     }
 
-    if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) {
+    if ((ret = avcodec_open2(ost->enc_ctx, enc, NULL)) < 0) {
         if (ret != AVERROR_EXPERIMENTAL)
             av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe "
                    "incorrect parameters such as bit_rate, rate, width or height.\n");
@@ -337,10 +331,6 @@ int enc_open(void *opaque, const AVFrame *frame)
     if (ost->enc_ctx->frame_size)
         frame_samples = ost->enc_ctx->frame_size;
 
-    ret = check_avoptions(ost->encoder_opts);
-    if (ret < 0)
-        return ret;
-
     if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 &&
         ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
         av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low."
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 41afe8259d..61a0d8658f 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -711,14 +711,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
         /* two pass mode */
         MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st);
         if (do_pass) {
-            if (do_pass & 1) {
+            if (do_pass & 1)
                 video_enc->flags |= AV_CODEC_FLAG_PASS1;
-                av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND);
-            }
-            if (do_pass & 2) {
+            if (do_pass & 2)
                 video_enc->flags |= AV_CODEC_FLAG_PASS2;
-                av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND);
-            }
         }
 
         MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st);
@@ -740,7 +736,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
                                            DEFAULT_PASS_LOGFILENAME_PREFIX,
                      ost_idx);
             if (!strcmp(ost->enc_ctx->codec->name, "libx264")) {
-                av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
+                if (av_opt_is_set_to_default_by_name(ost->enc_ctx, "stats",
+                                                     AV_OPT_SEARCH_CHILDREN) > 0)
+                    av_opt_set(ost->enc_ctx, "stats", logfilename,
+                               AV_OPT_SEARCH_CHILDREN);
             } else {
                 if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
                     char  *logbuffer = file_read(logfilename);
@@ -1041,6 +1040,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
     const AVCodec *enc;
     AVStream *st;
     int ret = 0, keep_pix_fmt = 0, autoscale = 1;
+    int threads_manual = 0;
     AVRational enc_tb = { 0, 0 };
     enum VideoSyncMethod vsync_method = VSYNC_AUTO;
     const char *bsfs = NULL, *time_base = NULL;
@@ -1264,6 +1264,23 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
             enc_tb = q;
         }
+
+        threads_manual = !!av_dict_get(ost->encoder_opts, "threads", NULL, 0);
+
+        ret = av_opt_set_dict2(ost->enc_ctx, &ost->encoder_opts, AV_OPT_SEARCH_CHILDREN);
+        if (ret < 0) {
+            av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n",
+                   av_err2str(ret));
+            return ret;
+        }
+
+        ret = check_avoptions(ost->encoder_opts);
+        if (ret < 0)
+            return ret;
+
+        // default to automatic thread count
+        if (!threads_manual)
+            ost->enc_ctx->thread_count = 0;
     } else {
         ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
                                 NULL, &ost->encoder_opts,
@@ -1276,8 +1293,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
     if (o->bitexact) {
         ost->bitexact        = 1;
     } else if (ost->enc_ctx) {
-        ost->bitexact        = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags",
-                                                  AV_CODEC_FLAG_BITEXACT);
+        ost->bitexact        = !!(ost->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
     }
 
     MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st);
@@ -1372,7 +1388,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
     if (ost->enc &&
         (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
-        const AVDictionaryEntry *e;
         char name[16];
         OutputFilterOptions opts = {
             .enc = enc,
@@ -1398,10 +1413,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
 
         snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
 
-        e = av_dict_get(ost->encoder_opts, "threads", NULL, 0);
-        if (e)
-            opts.nb_threads = e->value;
-
         // MJPEG encoder exports a full list of supported pixel formats,
         // but the full-range ones are experimental-only.
         // Restrict the auto-conversion list unless -strict experimental
@@ -1413,33 +1424,26 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
                 { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
                   AV_PIX_FMT_NONE };
 
-            const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
-            int strict_val = ost->enc_ctx->strict_std_compliance;
-
-            if (strict) {
-                const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0);
-                av_assert0(o);
-                av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val);
-            }
-
-            if (strict_val > FF_COMPLIANCE_UNOFFICIAL)
+            if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
                 opts.pix_fmts = mjpeg_formats;
         }
 
+        if (threads_manual) {
+            ret = av_opt_get(ost->enc_ctx, "threads", 0, (uint8_t**)&opts.nb_threads);
+            if (ret < 0)
+                return ret;
+        }
+
         if (ofilter) {
             ost->filter       = ofilter;
             ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc, &opts);
-            if (ret < 0)
-                return ret;
         } else {
             ret = init_simple_filtergraph(ost->ist, ost, filters,
                                           mux->sch, ms->sch_idx_enc, &opts);
-            if (ret < 0) {
-                av_log(ost, AV_LOG_ERROR,
-                       "Error initializing a simple filtergraph\n");
-                return ret;
-            }
         }
+        av_freep(&opts.nb_threads);
+        if (ret < 0)
+            return ret;
 
         ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc),
                                     SCH_MSTREAM(mux->sch_idx, ms->sch_idx));
diff --git a/tests/ref/vsynth/vsynth1-prores_444_int b/tests/ref/vsynth/vsynth1-prores_444_int
index 76db62d4e9..3d4c616c7a 100644
--- a/tests/ref/vsynth/vsynth1-prores_444_int
+++ b/tests/ref/vsynth/vsynth1-prores_444_int
@@ -1,4 +1,4 @@
-fd2a2f49c61817c2338f39d5736d5fd2 *tests/data/fate/vsynth1-prores_444_int.mov
+bd1502671ce7144c106a6a460b2af404 *tests/data/fate/vsynth1-prores_444_int.mov
 9940947 tests/data/fate/vsynth1-prores_444_int.mov
 732ceeb6887524e0aee98762fe50578b *tests/data/fate/vsynth1-prores_444_int.out.rawvideo
 stddev:    2.83 PSNR: 39.08 MAXDIFF:   45 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth1-prores_int b/tests/ref/vsynth/vsynth1-prores_int
index 3e2bbeff2a..c3b57631c8 100644
--- a/tests/ref/vsynth/vsynth1-prores_int
+++ b/tests/ref/vsynth/vsynth1-prores_int
@@ -1,4 +1,4 @@
-1f1b246dfabe028f04c78887e5da51ed *tests/data/fate/vsynth1-prores_int.mov
+842f92426e56cf6208cc94360d29fc69 *tests/data/fate/vsynth1-prores_int.mov
 6308688 tests/data/fate/vsynth1-prores_int.mov
 164a4ca890695cf594293d1acec9463c *tests/data/fate/vsynth1-prores_int.out.rawvideo
 stddev:    2.66 PSNR: 39.62 MAXDIFF:   34 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth2-prores_444_int b/tests/ref/vsynth/vsynth2-prores_444_int
index a2ee569c49..8d2a13b91b 100644
--- a/tests/ref/vsynth/vsynth2-prores_444_int
+++ b/tests/ref/vsynth/vsynth2-prores_444_int
@@ -1,4 +1,4 @@
-5ac517fc2380a6cf11b7d86d2fafee0a *tests/data/fate/vsynth2-prores_444_int.mov
+6f5fa77609698fbed3a7eef1c91bb9ea *tests/data/fate/vsynth2-prores_444_int.mov
 6420787 tests/data/fate/vsynth2-prores_444_int.mov
 33a5db4f0423168d4ae4f1db3610928e *tests/data/fate/vsynth2-prores_444_int.out.rawvideo
 stddev:    0.93 PSNR: 48.73 MAXDIFF:   14 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth2-prores_int b/tests/ref/vsynth/vsynth2-prores_int
index 72139ee6c3..f80ff34601 100644
--- a/tests/ref/vsynth/vsynth2-prores_int
+++ b/tests/ref/vsynth/vsynth2-prores_int
@@ -1,4 +1,4 @@
-4062c74196d95a64e642bd917377ed93 *tests/data/fate/vsynth2-prores_int.mov
+a9a9812dd8944a58c2c2b3b0ce41247d *tests/data/fate/vsynth2-prores_int.mov
 4070996 tests/data/fate/vsynth2-prores_int.mov
 bef9e38387a1fbb1ce2e4401b6d41674 *tests/data/fate/vsynth2-prores_int.out.rawvideo
 stddev:    1.54 PSNR: 44.37 MAXDIFF:   13 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth3-prores_444_int b/tests/ref/vsynth/vsynth3-prores_444_int
index ac30691143..ca30db5383 100644
--- a/tests/ref/vsynth/vsynth3-prores_444_int
+++ b/tests/ref/vsynth/vsynth3-prores_444_int
@@ -1,4 +1,4 @@
-50db4bbc4674de3dfdd41f306af1cb17 *tests/data/fate/vsynth3-prores_444_int.mov
+b61864cafb35ad8e592b4f899bdd84b6 *tests/data/fate/vsynth3-prores_444_int.mov
 184397 tests/data/fate/vsynth3-prores_444_int.mov
 a8852aa2841c2ce5f2aa86176ceda4ef *tests/data/fate/vsynth3-prores_444_int.out.rawvideo
 stddev:    3.24 PSNR: 37.91 MAXDIFF:   41 bytes:    86700/    86700
diff --git a/tests/ref/vsynth/vsynth3-prores_int b/tests/ref/vsynth/vsynth3-prores_int
index 86fc2266b5..0feee26de1 100644
--- a/tests/ref/vsynth/vsynth3-prores_int
+++ b/tests/ref/vsynth/vsynth3-prores_int
@@ -1,4 +1,4 @@
-24b765064b4aec754fdd0cc3658bba19 *tests/data/fate/vsynth3-prores_int.mov
+2e89dfb5e2b5146337c1d65ccc4fe196 *tests/data/fate/vsynth3-prores_int.mov
 120484 tests/data/fate/vsynth3-prores_int.mov
 e5859ba47a99f9e53c1ddcaa68a8f8f8 *tests/data/fate/vsynth3-prores_int.out.rawvideo
 stddev:    2.92 PSNR: 38.81 MAXDIFF:   29 bytes:    86700/    86700
diff --git a/tests/ref/vsynth/vsynth_lena-prores_444_int b/tests/ref/vsynth/vsynth_lena-prores_444_int
index f05f1fe775..b13a7a126a 100644
--- a/tests/ref/vsynth/vsynth_lena-prores_444_int
+++ b/tests/ref/vsynth/vsynth_lena-prores_444_int
@@ -1,4 +1,4 @@
-09b5dffd1a484e2152a3b5a0bcceed32 *tests/data/fate/vsynth_lena-prores_444_int.mov
+e76d98c772c65c7ac75f7d43484883d3 *tests/data/fate/vsynth_lena-prores_444_int.mov
 5696258 tests/data/fate/vsynth_lena-prores_444_int.mov
 466380156e4d2b811f4ffb9c5a8bca72 *tests/data/fate/vsynth_lena-prores_444_int.out.rawvideo
 stddev:    0.88 PSNR: 49.23 MAXDIFF:    9 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth_lena-prores_int b/tests/ref/vsynth/vsynth_lena-prores_int
index ea08089745..cec45a59b9 100644
--- a/tests/ref/vsynth/vsynth_lena-prores_int
+++ b/tests/ref/vsynth/vsynth_lena-prores_int
@@ -1,4 +1,4 @@
-c7e9a61054f44fe372a3bce619b68ce9 *tests/data/fate/vsynth_lena-prores_int.mov
+21d328216b194500a3c87c45afa5e927 *tests/data/fate/vsynth_lena-prores_int.mov
 3532698 tests/data/fate/vsynth_lena-prores_int.mov
 eb5caa9824ca294f403cd13f33c40f23 *tests/data/fate/vsynth_lena-prores_int.out.rawvideo
 stddev:    1.47 PSNR: 44.78 MAXDIFF:   12 bytes:  7603200/  7603200
