Skip to content

Commit

Permalink
sub.TextFile: Add support for more formats
Browse files Browse the repository at this point in the history
Convert SRT, Webvtt, Microdvd, etc. to ASS on the fly with ffmpeg.

The explicit dependency on iconv also ensures that the "charset"
parameter is never ignored. Previously the "charset" parameter relied on
libass being compiled with iconv support, which is impossible to check
for and not at all a given.
  • Loading branch information
cantabile committed May 16, 2017
1 parent 84351dc commit c63e7df
Show file tree
Hide file tree
Showing 7 changed files with 563 additions and 25 deletions.
4 changes: 3 additions & 1 deletion Makefile.am
Expand Up @@ -137,7 +137,9 @@ pkglib_LTLIBRARIES += libsubtext.la
libsubtext_la_SOURCES = src/filters/subtext/text.c \
src/filters/subtext/common.c \
src/filters/subtext/common.h \
src/filters/subtext/image.cpp
src/filters/subtext/image.cpp \
src/filters/subtext/toass.cpp \
src/filters/subtext/toutf8.c

libsubtext_la_LDFLAGS = $(commonpluginldflags)
libsubtext_la_LIBTOOLFLAGS = $(commonlibtoolflags)
Expand Down
30 changes: 30 additions & 0 deletions configure.ac
Expand Up @@ -12,6 +12,10 @@ AC_PROG_CC
AC_PROG_CXX


AC_SYS_LARGEFILE
AC_FUNC_FSEEKO


AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Enable compilation options required for debugging. (default=no)]))
AS_IF(
[test "x$enable_debug" = "xyes"],
Expand Down Expand Up @@ -360,6 +364,32 @@ AS_CASE(
]
)

AC_CHECK_HEADERS(
[iconv.h],
[],
[
AS_IF(
[test "x$subtext" = "xyes"],
[AC_MSG_ERROR([the subtext plugin was explicitly enabled, but iconv.h cannot be found.])],
[subtext=""]
)
]
)

AC_SEARCH_LIBS([libiconv_open], [iconv])
AC_SEARCH_LIBS([iconv_open], [iconv])

AS_IF(
[test "x$ac_cv_search_libiconv_open" = "xno" -a "x$ac_cv_search_iconv_open" = "xno"],
[
AS_IF(
[test "x$subtext" = "xyes"],
[AC_MSG_ERROR([the subtext plugin was explicitly enabled, but iconv_open cannot be found.])],
[subtext=""]
)
]
)

PKG_CHECK_MODULES(
[LIBASS],
[libass],
Expand Down
2 changes: 1 addition & 1 deletion doc/installation.rst
Expand Up @@ -75,7 +75,7 @@ These are the requirements:

* Sphinx for the documentation (optional)

* libass and ffmpeg for the Subtext plugin (optional)
* iconv, libass, and ffmpeg for the Subtext plugin (optional)

* ImageMagick 7 for the Imwri plugin (optional)

Expand Down
17 changes: 11 additions & 6 deletions doc/plugins/subtext.rst
Expand Up @@ -5,10 +5,10 @@ Subtext

Subtext is a subtitle renderer that uses libass and ffmpeg.

.. function:: TextFile(clip clip, string file[, string charset="UTF-8", float scale=1, int debuglevel=0, string fontdir="", float linespacing=0, int[] margins=[0, 0, 0, 0], float sar=0, bint blend=True, int matrix, string matrix_s, int transfer, string transfer_s, int primaries, string primaries_s])
.. function:: TextFile(clip clip, string file[, string charset="UTF-8", float scale=1, int debuglevel=0, string fontdir="", float linespacing=0, int[] margins=[0, 0, 0, 0], float sar=0, string style="", bint blend=True, int matrix, string matrix_s, int transfer, string transfer_s, int primaries, string primaries_s])
:module: sub

TextFile renders ASS subtitles.
TextFile renders text subtitles, such as ASS and SRT.

TextFile has two modes of operation. With blend=True (the default),
it returns *clip* with the subtitles burned in. With blend=False, it
Expand All @@ -22,10 +22,10 @@ Subtext is a subtitle renderer that uses libass and ffmpeg.
Input clip.

file
ASS script to be rendered.
Subtitle file to be rendered.

charset
Character set of the ASS script, in enca or iconv format.
Character set of the subtitle, in iconv format.

scale
Font scale.
Expand All @@ -48,6 +48,11 @@ Subtext is a subtitle renderer that uses libass and ffmpeg.
sar
Storage aspect ratio.

style
Custom ASS style for subtitle formats other than ASS. If empty
(the default), libavcodec's default style is used. This
parameter has no effect on ASS subtitles.

blend
If True, the subtitles will be blended into *clip*. Otherwise,
the bitmaps will be returned untouched.
Expand All @@ -68,10 +73,10 @@ Subtext is a subtitle renderer that uses libass and ffmpeg.
"709".


.. function:: Subtitle(clip clip, string text[, string style="sans-serif,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,7,10,10,10,1", int start=0, int end=clip.numFrames, int debuglevel=0, string fontdir="", float linespacing=0, int[] margins=[0, 0, 0, 0], float sar=0, bint blend=True, int matrix, string matrix_s, int transfer, string transfer_s, int primaries, string primaries_s])
.. function:: Subtitle(clip clip, string text[, int start=0, int end=clip.numFrames, int debuglevel=0, string fontdir="", float linespacing=0, int[] margins=[0, 0, 0, 0], float sar=0, string style="sans-serif,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,7,10,10,10,1", bint blend=True, int matrix, string matrix_s, int transfer, string transfer_s, int primaries, string primaries_s])
:module: sub

Instead of rendering an ASS script, Subtitle renders the string *text*.
Instead of rendering a subtitle file, Subtitle renders the string *text*.
Otherwise it works the same as TextFile.

Parameters:
Expand Down
50 changes: 33 additions & 17 deletions src/filters/subtext/text.c
Expand Up @@ -266,6 +266,11 @@ static int frameToTime(int frame, int64_t fpsNum, int64_t fpsDen, char *str, siz
return 1;
}


char *convertToUtf8(const char *file_name, const char *charset, int64_t *file_size, char *error, size_t error_size);
ASS_Track *convertToASS(const char *file_name, const char *contents, size_t contents_size, ASS_Library *ass_library, const char *user_style, const char *charset, char *error, size_t error_size);


static void VS_CC assRenderCreate(const VSMap *in, VSMap *out, void *userData,
VSCore *core, const VSAPI *vsapi)
{
Expand Down Expand Up @@ -298,12 +303,6 @@ static void VS_CC assRenderCreate(const VSMap *in, VSMap *out, void *userData,
d.file = NULL;
d.text = vsapi->propGetData(in, "text", 0, &err);

d.style = vsapi->propGetData(in, "style", 0, &err);

if(err) {
d.style = "sans-serif,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,7,10,10,10,1";
}

d.startframe = int64ToIntS(vsapi->propGetInt(in, "start", 0, &err));
if (err) {
d.startframe = 0;
Expand All @@ -325,6 +324,12 @@ static void VS_CC assRenderCreate(const VSMap *in, VSMap *out, void *userData,
}
}

d.style = vsapi->propGetData(in, "style", 0, &err);

if(err && !d.file) {
d.style = "sans-serif,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,7,10,10,10,1";
}

d.charset = vsapi->propGetData(in, "charset", 0, &err);

if(err)
Expand Down Expand Up @@ -456,16 +461,27 @@ static void VS_CC assRenderCreate(const VSMap *in, VSMap *out, void *userData,

free(str);
} else {
d.ass = ass_read_file(d.ass_library, (char *)d.file, (char *)d.charset);
}
snprintf(error, ERROR_SIZE, "%s: ", filter_name);

if(!d.ass) {
snprintf(error, ERROR_SIZE, "%s: unable to parse input file", filter_name);
vsapi->setError(out, error);
vsapi->freeNode(d.node);
ass_renderer_done(d.ass_renderer);
ass_library_done(d.ass_library);
return;
int64_t contents_size;
char *contents = convertToUtf8(d.file, d.charset, &contents_size, error + strlen(error), ERROR_SIZE - strlen(error));

if (contents) {
d.ass = ass_read_memory(d.ass_library, contents, contents_size, NULL);

if (!d.ass)
d.ass = convertToASS(d.file, contents, contents_size, d.ass_library, d.style, d.charset, error + strlen(error), ERROR_SIZE - strlen(error));

free(contents);
}

if (!contents || !d.ass) {
vsapi->setError(out, error);
vsapi->freeNode(d.node);
ass_renderer_done(d.ass_renderer);
ass_library_done(d.ass_library);
return;
}
}

d.lastframe = vsapi->newVideoFrame(d.vi[0].format,
Expand Down Expand Up @@ -526,7 +542,8 @@ VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc,
"fontdir:data:opt;" \
"linespacing:float:opt;" \
"margins:int[]:opt;" \
"sar:float:opt;"
"sar:float:opt;" \
"style:data:opt;"

#define COMMON_PARAMS \
"blend:int:opt;" \
Expand All @@ -548,7 +565,6 @@ VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc,
registerFunc("Subtitle",
"clip:clip;"
"text:data;"
"style:data:opt;"
"start:int:opt;"
"end:int:opt;"
COMMON_TEXTFILE_PARAMS
Expand Down

0 comments on commit c63e7df

Please sign in to comment.