> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-boun...@ffmpeg.org> On Behalf Of softworkz .
> Sent: Samstag, 17. Mai 2025 19:22
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH 3/4] fftools/graph/graphprint: load CSS and
> HTML resources from ffmpeg data directories
> 
> 
> 
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-boun...@ffmpeg.org> On Behalf Of Marton
> > Balint
> > Sent: Samstag, 17. Mai 2025 11:14
> > To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH 3/4] fftools/graph/graphprint: load CSS
> and
> > HTML resources from ffmpeg data directories
> >
> >
> >
> > On Sat, 17 May 2025, softworkz . wrote:
> >
> > >
> > >
> > >> -----Original Message-----
> > >> From: ffmpeg-devel <ffmpeg-devel-boun...@ffmpeg.org> On Behalf Of Marton
> > >> Balint
> > >> Sent: Samstag, 17. Mai 2025 01:09
> > >> To: ffmpeg-devel@ffmpeg.org
> > >> Cc: Marton Balint <c...@passwd.hu>
> > >> Subject: [FFmpeg-devel] [PATCH 3/4] fftools/graph/graphprint: load CSS
> and
> > >> HTML resources from ffmpeg data directories
> > >>
> > >> Similar to how it is done for ffpreset files. This allows the users to
> > change
> > >> the HTML/CSS templates at will.
> > >>
> > >> Signed-off-by: Marton Balint <c...@passwd.hu>
> > >> ---
> > >>  Makefile                        |  2 +-
> > >>  doc/ffmpeg.texi                 |  4 ++-
> > >>  fftools/cmdutils.c              | 48 +++++++++++++++++++++++++++++++++
> > >>  fftools/cmdutils.h              |  2 ++
> > >>  fftools/graph/graphprint.c      | 16 ++++++++---
> > >>  fftools/textformat/tf_mermaid.h |  4 +--
> > >>  6 files changed, 68 insertions(+), 8 deletions(-)
> > >>
> > >> diff --git a/Makefile b/Makefile
> > >> index e2250f6bc6..ebc50bb510 100644
> > >> --- a/Makefile
> > >> +++ b/Makefile
> > >> @@ -32,7 +32,7 @@ FFLIBS-$(CONFIG_SWSCALE)    += swscale
> > >>
> > >>  FFLIBS := avutil
> > >>
> > >> -DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset)
> > >> $(SRC_PATH)/doc/ffprobe.xsd
> > >> +DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset)
> > >> $(SRC_PATH)/doc/ffprobe.xsd $(SRC_PATH)/fftools/resources/graph.css
> > >> $(SRC_PATH)/fftools/resources/graph.html
> > >>
> > >>  SKIPHEADERS = compat/w32pthreads.h
> > >>
> > >> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
> > >> index 35675b5309..8edf188ab9 100644
> > >> --- a/doc/ffmpeg.texi
> > >> +++ b/doc/ffmpeg.texi
> > >> @@ -1402,7 +1402,9 @@ Writes execution graph details to the specified
> file
> > in
> > >> the format set via -prin
> > >>
> > >>  @item -print_graphs_format @var{format} (@emph{global})
> > >>  Sets the output format (available formats are: default, compact, csv,
> > flat,
> > >> ini, json, xml, mermaid, mermaidhtml)
> > >> -The default format is json.
> > >> +The default format is json. The mermarid and mermaidhtml formats need
> > >> graph.css
> > >> +and graph.html resources which are searched in the FFMPEG data
> > directories,
> > >> +similar to ffpreset files.
> > >>
> > >>  @item -progress @var{url} (@emph{global})
> > >>  Send program-friendly progress information to @var{url}.
> > >> diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
> > >> index 1de670c2e4..01e57d91e8 100644
> > >> --- a/fftools/cmdutils.c
> > >> +++ b/fftools/cmdutils.c
> > >> @@ -1005,6 +1005,54 @@ FILE *get_preset_file(AVBPrint *filename,
> > >>      return f;
> > >>  }
> > >>
> > >> +int file_read_from_datadir(const char *filename, char **outbuf)
> > >> +{
> > >> +    FILE *f;
> > >> +    char *buf = NULL;
> > >> +    long size;
> > >> +    AVBPrint bp;
> > >> +
> > >> +    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
> > >> +    f = get_datadir_file_fmt(&bp, "%s", filename);
> > >> +    if (!f)
> > >> +        return AVERROR(errno);
> > >> +
> > >> +    if (fseek(f, 0, SEEK_END)) {
> > >> +        int ret = AVERROR(errno);
> > >> +        fclose(f);
> > >> +        return ret;
> > >> +    }
> > >> +
> > >> +    size = ftell(f);
> > >> +    if (size < 0 || size >= INT_MAX) {
> > >> +        fclose(f);
> > >> +        return AVERROR(EINVAL);
> > >> +    }
> > >> +
> > >> +    if (fseek(f, 0, SEEK_SET)) {
> > >> +        int ret = AVERROR(errno);
> > >> +        fclose(f);
> > >> +        return ret;
> > >> +    }
> > >> +
> > >> +    buf = av_malloc(size + 1);
> > >> +    if (!buf) {
> > >> +        fclose(f);
> > >> +        return AVERROR(ENOMEM);
> > >> +    }
> > >> +
> > >> +    if (fread(buf, 1, size, f) != size) {
> > >> +        fclose(f);
> > >> +        return AVERROR(EIO);
> > >> +    }
> > >> +    buf[size] = 0;
> > >> +
> > >> +    fclose(f);
> > >> +
> > >> +    *outbuf = buf;
> > >> +    return 0;
> > >> +}
> > >> +
> > >>  int cmdutils_isalnum(char c)
> > >>  {
> > >>      return (c >= '0' && c <= '9') ||
> > >> diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h
> > >> index 216a2bcfe7..b324e5fc65 100644
> > >> --- a/fftools/cmdutils.h
> > >> +++ b/fftools/cmdutils.h
> > >> @@ -504,6 +504,8 @@ int read_yesno(void);
> > >>  FILE *get_preset_file(AVBPrint *filename,
> > >>                        const char *preset_name, int is_path, const char
> > >> *codec_name);
> > >>
> > >> +int file_read_from_datadir(const char *filename, char **buf);
> > >> +
> > >>  /**
> > >>   * Realloc array to hold new_size elements of elem_size.
> > >>   *
> > >> diff --git a/fftools/graph/graphprint.c b/fftools/graph/graphprint.c
> > >> index fc94a75797..fbcb7f1b75 100644
> > >> --- a/fftools/graph/graphprint.c
> > >> +++ b/fftools/graph/graphprint.c
> > >> @@ -41,7 +41,6 @@
> > >>  #include "libavutil/hwcontext.h"
> > >>  #include "fftools/textformat/avtextformat.h"
> > >>  #include "fftools/textformat/tf_mermaid.h"
> > >> -#include "fftools/resources/resman.h"
> > >>
> > >>  typedef enum {
> > >>      SECTION_ID_ROOT,
> > >> @@ -935,10 +934,19 @@ static int init_graphprint(GraphPrintContext
> **pgpc,
> > >> AVBPrint *target_buf)
> > >>      }
> > >>
> > >>      if (!strcmp(text_formatter->name, "mermaid") ||
> > !strcmp(text_formatter-
> > >>> name, "mermaidhtml")) {
> > >> -        gpc->diagram_config.diagram_css =
> > >> ff_resman_get_string(FF_RESOURCE_GRAPH_CSS);
> > >> +        ret = file_read_from_datadir("graph.css", &gpc-
> > >>> diagram_config.diagram_css);
> > >> +        if (ret < 0) {
> > >> +            av_log(NULL, AV_LOG_ERROR, "graph.css needed for mermaid
> graph
> > >> format cannot be opened: %s\n", av_err2str(ret));
> > >> +            goto fail;
> > >> +        }
> > >>
> > >> -        if (!strcmp(text_formatter->name, "mermaidhtml"))
> > >> -            gpc->diagram_config.html_template =
> > >> ff_resman_get_string(FF_RESOURCE_GRAPH_HTML);
> > >> +        if (!strcmp(text_formatter->name, "mermaidhtml")) {
> > >> +            ret = file_read_from_datadir("graph.html", &gpc-
> > >>> diagram_config.html_template);
> > >> +            if (ret < 0) {
> > >> +                av_log(NULL, AV_LOG_ERROR, "graph.html needed for
> > >> mermaridhtml graph format cannot be opened: %s\n", av_err2str(ret));
> > >> +                goto fail;
> > >> +            }
> > >> +        }
> > >>
> > >>          av_diagram_init(tfc, &gpc->diagram_config);
> > >>      }
> > >> diff --git a/fftools/textformat/tf_mermaid.h
> > b/fftools/textformat/tf_mermaid.h
> > >> index 6e8f2a9b42..0b34d8ab20 100644
> > >> --- a/fftools/textformat/tf_mermaid.h
> > >> +++ b/fftools/textformat/tf_mermaid.h
> > >> @@ -28,8 +28,8 @@ typedef enum {
> > >>
> > >>  typedef struct AVDiagramConfig {
> > >>      AVDiagramType diagram_type;
> > >> -    const char *diagram_css;
> > >> -    const char *html_template;
> > >> +    char *diagram_css;
> > >> +    char *html_template;
> > >>  } AVDiagramConfig;
> > >>
> > >>
> > >> --
> > >
> > > NAK - I totally disagree to this change
> > >
> > >
> > > 1. It makes the feature widely unusable. In all those years I've never
> seen
> > >   or dealt with an "FFmpeg data folder" and I know that everywhere I would
> > >   want to use this feature, there's no such folder nor files
> >
> > Using external folders for resources is quite common, admittedly not in
> > ffmpeg, but for other programs it is.
> >
> > >
> > > 2. The html and the CSS are in no way like exchangeable templates. They
> are
> > >   part of the implementation of the feature - especially the CSS.
> > >   Another - yet unsubmitted - feature (data schema graphs) will have its
> > >   own and different html and css, which is also very specific.
> > >
> > > 3. Even when considering the files as something different than templates,
> > >   this will still not fly. The code in FFmpeg is tightly coupled and
> > >   dependent of the html and css. When the feature gets updated or extended
> > >   this will almost certainly include changes to the css, which means that
> > >   it would be incompatible with the css from a different FFmpeg version.
> > >   There's no logical independence and hence the files cannot be delivered
> > >   separately
> >
> > If that is the case, then I am not sure if it is a good idea to maintain
> > the styling of these output variants embedded in ffmpeg CLI.
> 
> For styling Mermaid diagrams, the CSS must be part of the Mermaid graph
> definition - this is what is taken from the CSS resource file. It gets
> transformed and escaped into the Mermaid definition.
> 
> When you specify -print_graphs_format mermaid, then you get the plain
> Mermaid definition as a valid .mmd (or .mermaid) file - all without a
> CDN. Then you can open that in an application or just copy/paste it into
> a code block in most Markdown system. You might need to care about the
> version, though. For example to make it work in the current GitHub Markdown,
> you need to specify an extra parameter (until GitHub updates their Mermaid
> libs).
> 
> So far, this is all offline. In earlier versions, I had the CSS included
> in plain C strings, but I thought it would be a better practice to include
> it as compressed resource, to optimize the size of the binaries and that
> allowed to reduce it to 25% of the size.
> 
> This route (mermaid format) is also the way to got when you want to embed
> the diagram a custom html document, but then you are responsible for any
> compatibility issues.
> 
> The mermaidhtml output on the other hand is the reliable and quick way
> when you just want to see the diagram that always works without any worries
> and without any pre-conditions.
> 
> The compressed sizes are about 1k for the html and 2.5k for the CSS, that
> really not that big and it doesn't got into any libs, just the ffmpeg
> binary. Given the high value of the feature, I do believe that this is
> more than justified.
> 
> > Considering that you already depend on CDNs, IMHO it would make more sense
> > to generate some minimal HTML with the graph data embedded in JSON in it,
> > and then generate the required mermarid format via JS also loaded from
> > some CDN, or even better, ffmpeg.org.
> 
> That doesn't work, because for the Mermaid creation, the AVTextFormat APIs
> have a few extension features which are giving some extra information that
> is not included in the plain JSON output.
> 
> 
> Thanks for your interest in the feature,
> sw
> _______________________________________________


Hi Marton,

as you had mentioned the use of CDN, I wanted to share my thoughts and
reasonings about it.

In the first place, a full offline solution would clearly be preferable from
my point of view. The html loads two packages: Mermaid and a simple zoom/pan
library. I had thought about eliminating the zoom/pan lib by writing a custom
one. I'm not 100% satisfied with the current lib, but it was the best among 
almost a dozen of libs I had tried, most of them heavily bloated.
Eventually I've been too afraid of objections on the ML regarding the resource
sizes, so kept it external.

When looking at what the browser loads from the CDN, it sums up to 207kB.
I'm not sure how much potential there might be left for compression, that 
would need to be determined. But let's say it's maybe around 100kB of size 
that would be required to make it work fully offline without CDN.

It might also be possible to further reduce the size by creating a custom 
build of Mermaid. It currently supports 22 types of diagrams and we need
only one or two.

Personally, I don't care about the size. With binary sizes of >50 MB for 
static ffmpeg, those 100kB don't really matter. I think among those >50 MB,
there's a lot of stuff that is less important.

But others may see it differently, so I'm not sure. If there would be 
interest in turning it into a fully offline solution though, I can try to
transform it accordingly.

Thanks,
sw


_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to