Skip to content

5.27.0 - WebVTT placement and teletext grid rows

Choose a tag to compare

@superuser404notfound superuser404notfound released this 28 Jul 18:33

Follow-up to #233 from tresby's retest. Three findings, one of which contradicts a note that shipped with 5.26.0.

Added

  • External WebVTT subtitle files load at all. The FFmpeg build carried the webvtt decoder but never the webvtt demuxer, so avformat_open_input rejected every standalone .vtt file with AVERROR_INVALIDDATA and a sidecar WebVTT track failed before a single cue was decoded, on every path that opens one. Same shape as the raw-PGS sup gap fixed in FFmpegBuild 2.1.3, and it hid for the same reason: the codec was present, so the failure looked like it had to be elsewhere. Requires FFmpegBuild 2.3.0, which this release pins.
  • WebVTT cue settings reach the host after all: line, position and align arrive as SubtitleCue.placement. 5.26.0 reported them as upstream-blocked, which was a conclusion about the wrong layer. libavcodec's WebVTT decoder really does drop them, and says so as a @todo in webvttdec.c's file header, so nothing about the placement is in the ASS event line it synthesises. The demuxer keeps them: libavformat/webvttdec.c attaches the verbatim settings string to every packet as AV_PKT_DATA_WEBVTT_SETTINGS, and matroskadec.c propagates the same side data for WebVTT in Matroska. Both subtitle decoders now read it, and the packet store carries the string through a rebuild, since side data does not live in the payload and a stored packet would otherwise lose the placement a freshly demuxed one has. A percentage line becomes an anchor point plus the alignment row, anchored to the frame edge it is nearer (the spec's default line alignment would pin the box top at line:90% and hang a two-line cue off the frame); a line number keeps only the half of the frame it names, because line boxes need a rendered line height the engine does not have. An ASS \an or \pos still wins, since that came from the payload itself. size and vertical have no equivalent in the placement model and are ignored, and a position without a line keeps only the alignment column, because an anchor point needs both axes.

Fixed

  • Teletext captions keep their vertical placement on pages libzvbi does not flag as subtitle pages. gen_sub_ass derives the vertical anchor from the grid row itself and emits it as {\anN}, which the engine has read since 5.26.0, but that whole block sits behind is_subtitle_page. That flag comes from the row-0 page header (NEWSFLASH clear, SUBTITLE set, SUPPRESS_HEADER set), and when a broadcaster does not set all three, or the header has not been seen yet, the else path writes the whole page instead: one " \N" per grid row with the empty ones included, no \an, no per-row trim. The ordinal of the first non-blank row is then the only carrier of the position, and the edge trim was removing it before anything could read it. That ordinal now feeds libzvbi's own third-of-the-page formula rather than an invented scale, so a caption the broadcaster moved to the top of frame to clear a lower-third graphic stays there. Deliberately coarse: three bands is what the source encodes, and mapping each row to its own offset makes consecutive cues of different heights sit at different heights, which reads as a blink. It never overrides an \an that arrived, including {\an2}, which is explicitly bottom and produces exactly the empty derived output that "no information" would.
  • A styled cue trims the same whitespace an unstyled one does. The plain path trimmed with .whitespacesAndNewlines, the styled path tested for a literal space, tab or newline, so a Unicode space (U+00A0 among them) survived on a styled cue and not on an unstyled one carrying the same text. Teletext cannot produce one, since libzvbi maps U+00A0 to a space and writes it as \h, but SRT, WebVTT and ASS payloads can.
  • A blank teletext row that a colour change split into its own run folds like any other. The #107 interior blank-line fold worked per run plus one run boundary, which misses the shape the source produces most easily: the padding of an otherwise empty row carries the spacing attribute that changes colour, so the blank row lands in a whitespace-only run of its own and breaks the chain between the two text rows. The fold now runs on the flattened sequence and re-splits along the original run boundaries, so run structure cannot hide a blank row from it.

Reported by tresby (#233), whose teletext write-up identified the non-flagged-page case and whose push on WebVTT is what got the side-data path found.

No API changes. SubtitleCue.placement is populated on more sources than before; a host that ignores it is unaffected.