[FFmpeg-devel] [PATCH v1 2/2] avfilter/vf_subtitles: Added shift option for subtitles/ass filters.

Gyan Doshi ffmpeg at gyani.pro
Thu Jul 22 16:19:20 EEST 2021



On 2021-07-22 00:08, Manolis Stamatogiannakis wrote:
> Would it be possible to have a quick review for this patch? It is pretty
> straightforward.

Will test within a few days.

Regards,
Gyan

>
> Plus, this is its second submission. It already includes the requested
> changes from the first time (~1y ago).
>
> Thanks in advance,
> Manolis
>
>
> On Sun, 4 Jul 2021 at 18:13, 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           | 11 ++++++++
>>   libavfilter/vf_subtitles.c | 55 +++++++++++++++++++++++++++++++++-----
>>   2 files changed, 59 insertions(+), 7 deletions(-)
>>
>> diff --git a/doc/filters.texi b/doc/filters.texi
>> index 61c4cfc150..eebf455692 100644
>> --- a/doc/filters.texi
>> +++ b/doc/filters.texi
>> @@ -19474,6 +19474,9 @@ Common @ref{subtitles}/@ref{ass} filter 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
>> @@ -19487,6 +19490,9 @@ These fonts will be used in addition to whatever
>> the font provider uses.
>>
>>   @item alpha
>>   Process alpha channel, by default alpha channel is untouched.
>> +
>> + at item shift
>> +Shift subtitles timings by the specified amount.
>>   @end table
>>
>>   Additional options for @ref{subtitles} filter:
>> @@ -19533,6 +19539,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 ab32e1b7f3..2c7ce267e1 100644
>> --- a/libavfilter/vf_subtitles.c
>> +++ b/libavfilter/vf_subtitles.c
>> @@ -52,6 +52,7 @@ typedef struct AssContext {
>>       char *filename;
>>       char *fontsdir;
>>       char *charenc;
>> +    int64_t shift;
>>       char *force_style;
>>       int stream_index;
>>       int alpha;
>> @@ -66,11 +67,12 @@ typedef struct AssContext {
>>   #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
>>
>>   #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 }, \
>> -    {"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 }, \
>> +    {"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 }, \
>> +    {"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 }, \
>> +    {"shift",          "shift subtitles timing",
>>           OFFSET(shift),      AV_OPT_TYPE_DURATION,   {.i64 = 0   },
>> INT64_MIN, INT64_MAX, FLAGS }, \
>>
>>   /* libass supports a log level ranging from 0 to 7 */
>>   static const int ass_libavfilter_log_level_map[] = {
>> @@ -103,6 +105,11 @@ static av_cold int init(AVFilterContext *ctx)
>>           return AVERROR(EINVAL);
>>       }
>>
>> +    if (ass->shift != 0) {
>> +        ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q,
>> av_make_q(1, 1000));
>> +        av_log(ctx, AV_LOG_INFO, "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");
>> @@ -228,6 +235,8 @@ AVFILTER_DEFINE_CLASS(ass);
>>
>>   static av_cold int init_ass(AVFilterContext *ctx)
>>   {
>> +    int eid, nskip;
>> +    ASS_Event *event;
>>       AssContext *ass = ctx->priv;
>>       int ret = init(ctx);
>>
>> @@ -244,6 +253,25 @@ static av_cold int init_ass(AVFilterContext *ctx)
>>                  ass->filename);
>>           return AVERROR(EINVAL);
>>       }
>> +
>> +    /* Shift subtitles. */
>> +    nskip = 0;
>> +    for (eid = 0; eid < ass->track->n_events; eid++) {
>> +        event = &ass->track->events[eid];
>> +        event->Start += ass->shift;
>> +        if (event->Start + event->Duration < 0) {
>> +            ass_free_event(ass->track, eid);
>> +            nskip++;
>> +            continue;
>> +        } else if (nskip > 0) {
>> +            av_log(ctx, AV_LOG_INFO, "Skipped %d subtitles out of time
>> range.\n", nskip);
>> +            memmove(event - nskip, event, (ass->track->n_events - eid) *
>> sizeof(ASS_Event));
>> +            ass->track->n_events -= nskip;
>> +            eid -= nskip;
>> +            nskip = 0;
>> +        }
>> +    }
>> +
>>       return 0;
>>   }
>>
>> @@ -298,7 +326,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;
>> @@ -449,6 +477,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
>>           ass_process_codec_private(ass->track,
>>                                     dec_ctx->subtitle_header,
>>                                     dec_ctx->subtitle_header_size);
>> +    nskip = 0;
>>       while (av_read_frame(fmt, &pkt) >= 0) {
>>           int i, got_subtitle;
>>           AVSubtitle sub = {0};
>> @@ -459,8 +488,18 @@ 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));
>> +                /* Shift subtitles. */
>> +                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)
>> @@ -470,6 +509,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".



More information about the ffmpeg-devel mailing list