Message ID | 20200503180829.6767-1-mstamat@gmail.com |
---|---|
State | Superseded, archived |
Headers | show |
Series | [FFmpeg-devel] avfilter/vf_subtitles: add shift options | expand |
Context | Check | Description |
---|---|---|
andriy/default | pending | |
andriy/make | success | Make finished |
andriy/make_fate | success | Make fate finished |
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@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. > > +@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: > +@example > +subtitles=filename=sub.srt:shift=-20\:20 > +@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); > }
Good catch. I've fixed the text and resubmitted. Thanks. Manolis On Fri, 8 May 2020 at 12:33, Bodecs Bela <bodecsb@vivanet.hu> wrote: > 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@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. > > > > +@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: > > +@example > > +subtitles=filename=sub.srt:shift=-20\:20 > > +@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); > > } > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
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. +@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: +@example +subtitles=filename=sub.srt:shift=-20\:20 +@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 }, \ {"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); }
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@gmail.com> --- doc/filters.texi | 8 ++++++++ libavfilter/vf_subtitles.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-)