[FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift options

Bodecs Bela bodecsb at vivanet.hu
Fri May 8 13:33:42 EEST 2020


see may comment in text

2020.05.03. 20:08 keltezéssel, Manolis Stamatogiannakis írta:
> Allows shifting of subtitle display times to align them with the video.
> This avoids having to rewrite the subtitle file in order to display
> subtitles correctly when input is seeked (-ss).
> Also handy for minor subtitle timing corrections without rewriting the
> subtitles file.
>
> Signed-off-by: Manolis Stamatogiannakis <mstamat at gmail.com>
> ---
>   doc/filters.texi           |  8 ++++++++
>   libavfilter/vf_subtitles.c | 29 +++++++++++++++++++++++++++--
>   2 files changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index d19fd346ae..94323495f0 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -17851,6 +17851,9 @@ The filter accepts the following options:
>   @item filename, f
>   Set the filename of the subtitle file to read. It must be specified.
>   
> + at item shift
> +Shift subtitles timings by the specified amount.
> +
>   @item original_size
>   Specify the size of the original video, the video for which the ASS file
>   was composed. For the syntax of this option, check the
> @@ -17907,6 +17910,11 @@ To make the subtitles stream from @file{sub.srt} appear in 80% transparent blue
>   subtitles=sub.srt:force_style='FontName=DejaVu Serif,PrimaryColour=&HCCFF0000'
>   @end example
>   
> +To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20}, use:
> + at example
> +subtitles=filename=sub.srt:shift=-20\:20
> + at end example
> +
>   @section super2xsai
>   
>   Scale the input by 2x and smooth using the Super2xSaI (Scale and
> diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
> index a3b4029af4..74a902941a 100644
> --- a/libavfilter/vf_subtitles.c
> +++ b/libavfilter/vf_subtitles.c
> @@ -52,6 +52,8 @@ typedef struct AssContext {
>       char *filename;
>       char *fontsdir;
>       char *charenc;
> +    int64_t shift;
> +    char *shift_opt;
>       char *force_style;
>       int stream_index;
>       int alpha;
> @@ -68,6 +70,7 @@ typedef struct AssContext {
>   #define COMMON_OPTIONS \
>       {"filename",       "set the filename of file to read",                         OFFSET(filename),   AV_OPT_TYPE_STRING,     {.str = NULL},  0, 0, FLAGS }, \
>       {"f",              "set the filename of file to read",                         OFFSET(filename),   AV_OPT_TYPE_STRING,     {.str = NULL},  0, 0, FLAGS }, \
> +    {"shift",          "set the tilename of file to read",                         OFFSET(shift_opt),  AV_OPT_TYPE_STRING,     {.str = NULL},  0, 0, FLAGS }, \
desciption is wrong:
>       {"original_size",  "set the size of the original video (used to scale fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL},  0, 0, FLAGS }, \
>       {"fontsdir",       "set the directory containing the fonts to read",           OFFSET(fontsdir),   AV_OPT_TYPE_STRING,     {.str = NULL},  0, 0, FLAGS }, \
>       {"alpha",          "enable processing of alpha channel",                       OFFSET(alpha),      AV_OPT_TYPE_BOOL,       {.i64 = 0   },         0,        1, FLAGS }, \
> @@ -103,6 +106,16 @@ static av_cold int init(AVFilterContext *ctx)
>           return AVERROR(EINVAL);
>       }
>   
> +    if (ass->shift_opt) {
> +        if (av_parse_time(&ass->shift, ass->shift_opt, 1) < 0) {
> +            av_log(ctx, AV_LOG_ERROR, "Invalid subtitles shift: %s\n",
> +                   ass->shift_opt);
> +            return AVERROR(EINVAL);
> +        }
> +        ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q, av_make_q(1, 1000));
> +        av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n", ass->shift/1000.0);
> +    }
> +
>       ass->library = ass_library_init();
>       if (!ass->library) {
>           av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n");
> @@ -297,7 +310,7 @@ AVFILTER_DEFINE_CLASS(subtitles);
>   
>   static av_cold int init_subtitles(AVFilterContext *ctx)
>   {
> -    int j, ret, sid;
> +    int j, ret, sid, nskip;
>       int k = 0;
>       AVDictionary *codec_opts = NULL;
>       AVFormatContext *fmt = NULL;
> @@ -448,6 +461,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
>       av_init_packet(&pkt);
>       pkt.data = NULL;
>       pkt.size = 0;
> +    nskip = 0;
>       while (av_read_frame(fmt, &pkt) >= 0) {
>           int i, got_subtitle;
>           AVSubtitle sub = {0};
> @@ -458,8 +472,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
>                   av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
>                          av_err2str(ret));
>               } else if (got_subtitle) {
> -                const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000));
> +                const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000)) + ass->shift;
>                   const int64_t duration   = sub.end_display_time;
> +
> +                if (start_time + duration < 0) {
> +                    nskip++;
> +                    goto pkt_end;
> +                } else if (nskip > 0) {
> +                    av_log(ctx, AV_LOG_INFO, "Skipped %d subtitles out of time range.\n", nskip);
> +                    nskip = 0;
> +                }
> +
>                   for (i = 0; i < sub.num_rects; i++) {
>                       char *ass_line = sub.rects[i]->ass;
>                       if (!ass_line)
> @@ -472,6 +495,8 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
>                   }
>               }
>           }
> +
> +pkt_end:
>           av_packet_unref(&pkt);
>           avsubtitle_free(&sub);
>       }


More information about the ffmpeg-devel mailing list