PR #21040 opened by Zhao Zhili (quink)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21040
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21040.patch
For example:
./ffmpeg -hwaccel videotoolbox \
-i input.mp4 -c:a copy \
-vf scdet=threshold=10 \
-c:v h264_videotoolbox \
-force_key_frames scd_metadata \
-g 1000 -t 30 output.mp4
>From c07193ae1b9bba6131c9292e6c92a5bdd95fff4e Mon Sep 17 00:00:00 2001
From: Zhao Zhili <[email protected]>
Date: Fri, 28 Nov 2025 11:17:05 +0800
Subject: [PATCH] fftools/ffmpeg: add force key frame by scdet metadata support
For example:
./ffmpeg -hwaccel videotoolbox \
-i input.mp4 -c:a copy \
-vf scdet=threshold=10 \
-c:v h264_videotoolbox \
-force_key_frames scd_metadata \
-g 1000 -t 30 output.mp4
---
doc/ffmpeg.texi | 9 +++++++++
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_enc.c | 3 +++
fftools/ffmpeg_mux_init.c | 2 ++
4 files changed, 16 insertions(+)
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 3daf2f7ec2..2dae6632bc 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1665,6 +1665,7 @@ Force video tag/fourcc. This is an alias for
@code{-tag:v}.
@item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...]
(@emph{output,per-stream})
@item -force_key_frames[:@var{stream_specifier}] expr:@var{expr}
(@emph{output,per-stream})
@item -force_key_frames[:@var{stream_specifier}] source
(@emph{output,per-stream})
+@item -force_key_frames[:@var{stream_specifier}] scd_metadata
(@emph{output,per-stream})
@var{force_key_frames} can take arguments of the following form:
@@ -1728,6 +1729,14 @@ the current frame being encoded is marked as a key frame
in its source.
In cases where this particular source frame has to be dropped,
enforce the next available frame to become a key frame instead.
+@item scd_metadata
+If the argument is @code{scd_metadata}, ffmpeg will force a key frame if
+the current frame contains a metadata entry with the key @code{lavfi.scd.time}.
+The metadata can be added by filters like @code{scdet} and @code{scdet_vulkan}.
+Avoid inserting filters that duplicate frames after @code{scdet}, as this can
+cause duplicate metadata for multiple frames and repeated insertion of key
+frames.
+
@end table
Note that forcing too many keyframes is very harmful for the lookahead
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index cc2ea1a56e..7720dd9c59 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -602,6 +602,8 @@ enum {
#if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP
KF_FORCE_SOURCE_NO_DROP = 2,
#endif
+ // force keyframe if lavfi.scd.time metadata is set
+ KF_FORCE_SCD_METADATA = 3,
};
typedef struct KeyframeForceCtx {
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index 8f07a10848..0f7d961472 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -768,6 +768,9 @@ static enum AVPictureType forced_kf_apply(void *logctx,
KeyframeForceCtx *kf,
}
} else if (kf->type == KF_FORCE_SOURCE && (frame->flags &
AV_FRAME_FLAG_KEY)) {
goto force_keyframe;
+ } else if (kf->type == KF_FORCE_SCD_METADATA &&
+ av_dict_get(frame->metadata, "lavfi.scd.time", NULL, 0)) {
+ goto force_keyframe;
}
return AV_PICTURE_TYPE_NONE;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index bcbbee9126..194a87875d 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -3279,6 +3279,8 @@ static int process_forced_keyframes(Muxer *mux, const
OptionsContext *o)
"-force_key_frames is deprecated, use just 'source'\n");
ost->kf.type = KF_FORCE_SOURCE;
#endif
+ } else if (!strcmp(forced_keyframes, "scd_metadata")) {
+ ost->kf.type = KF_FORCE_SCD_METADATA;
} else {
int ret = parse_forced_key_frames(ost, &ost->kf, mux,
forced_keyframes);
if (ret < 0)
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]