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

lance.lmwang at gmail.com lance.lmwang at gmail.com
Mon May 18 13:21:26 EEST 2020


On Mon, May 18, 2020 at 11:34:03AM +0200, Manolis Stamatogiannakis wrote:
> Bumping this up after 10 days without a comment.
> 
> On Fri, 8 May 2020 at 13:14, Manolis Stamatogiannakis <mstamat at gmail.com>
> wrote:
> 
> > 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..47a38b55b1 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",          "shift the timing of the subtitles",
> >           OFFSET(shift_opt),  AV_OPT_TYPE_STRING,     {.str = NULL},  0, 0,
> > FLAGS }, \

I can't give comments for the function, but here It's better to use AV_OPT_TYPE_DURATION type
for the timing shift, then you can use shift directly and shift_opt isn't necessary anymore.


> >      {"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);
> >      }
> > --
> > 2.17.1
> >
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".

-- 
Thanks,
Limin Wang


More information about the ffmpeg-devel mailing list