History
0.7.0 (01-11-2026)
See the upgrade notes at https://webvtt-py.readthedocs.io/en/latest/upgrading.html for what to change in code using the library.
Changes that may need updates to the code using the library:
Requires Python 3.10 or later, as Python 3.7, 3.8 and 3.9 are end-of-life (#136, #148)
Strict parsing raises
MalformedCaptionErrorfor cues whose end time is not after the start time, for blocks that are not a cue, comment, style or region, such as text without cue timings, for comments whereNOTEis not followed by a space, a tab or a line break, or with-->, and for styles after the first cue (#97, #133)Writing WebVTT raises
ValueErrorfor-->in a comment or in the header text, which WebVTT does not allow (#134, #135)NOTEblocks with-->are not read as comments, and header text with-->is read as empty, as WebVTT does, so the file can be saved again (#134, #135)Removed
Caption.CUE_TEXT_TAGS, which is no longer used (#139, #153)save,save_as_srtand the-ooption of the CLI write a path with an extension as given, instead of adding.vttor.srtto it, socaptions.webvttis no longer saved ascaptions.webvtt.vtt(#144, #156)saveandsave_as_srtwithout a path or with a folder, and the-ooption of the CLI with a folder, keep the extension of the file when it is already of the format, so a file read fromcaptions.webvttis saved to it instead ofcaptions.vtt(#159, #195)from_bufferraisesTypeErrorfor a string or bytes, instead ofMalformedFileError: usefrom_stringto read a string, orio.BytesIOto read bytes (#143, #157)SRT cues without an index are read, as most SRT players do, instead of skipped (#142, #158)
Styles after the first cue and blocks where
NOTEis not followed by a space, a tab or a line break, such asNOTEBOOK, are ignored, as WebVTT does, and strict parsing raisesMalformedFileErrorwhenWEBVTTis not followed by a space, a tab or the end of the first line, such asWEBVTTX(#141, #194)saveraisesValueErrorforadd_bom=Truewith an encoding without a Byte Order Mark, such aslatin-1, and foradd_bom=Falsewithutf-8-sig,utf-16orutf-32, which always write one, instead of ignoringadd_bom(#160, #196)save_as_srtsaves captions read withfrom_srtorfrom_bufferin SRT format and anencodingin the same encoding, instead of UTF-8, andencoding=Nonesaves in UTF-8 instead of the encoding of the locale (#161, #197)Setting
Caption.textto a value that is not a string or a sequence of lines raisesTypeErrorinstead ofAttributeError, andCaptionraises it for lines that are not strings instead of accepting them (#162, #198)WebVTTkeeps empty lists given as arguments, as it does with other lists, instead of replacing them with new ones, andStylecopies a list of lines, asCaptiondoes, instead of keeping it (#163, #199)segmentraisesFileExistsError, and thesegmentcommand of the CLI exits with an error, when the output folder has the playlist or segments of an earlier run, instead of writing over them and keeping the segments the new playlist does not have: useoverwrite=Trueor--overwriteto replace them (#164, #200)from_bufferraisesValueErrorforstrict=Truewith thesrtorsbvformat, which have no strict parsing, instead of ignoring it (#167, #203)
Changes:
Added reading binary file-like objects with
from_buffer, such as files opened in'rb'mode, with the encoding of their Byte Order Mark, kept when saving, or the newencodingargument (#143, #157)Added setting
Caption.textto a sequence of lines, as when creating aCaption(#162, #198)Added
WebVTTErroras the base class of the errors, and madeMalformedFileErrorandMalformedCaptionErrorsubclasses ofValueError(#146, #155)Added
MalformedRegionError, a subclass ofMalformedCaptionError, raised for region settings that are not valid and, with strict parsing, for regions after the first cue (#168, #204)Added the
overwriteargument ofsegmentand the--overwriteoption of the CLI, which replace the files of an earlier segmentation and delete its segments that the new playlist does not have (#164, #200)Added the
durationargument ofsegment,slice_segmentsandwrite_manifest, and the--durationoption of the CLI, for the length of the media, so the HLS playlist covers all of it and its last segment ends with it instead of lasting the whole target duration (#165, #201)Added segmenting a
WebVTTinstance withsegment, such as captions edited or read from another format, without saving them first, and reading the captions from standard input with-as thePATHof thesegmentcommand (#205, #209)Added the
--versionoption of the CLI, and reading the captions from standard input with-as thePATHof theshiftandsynccommands (#169, #207)Added running the CLI with
python -m webvtt(#210)Fixed reading SRT files with whitespace around the first cue index, thanks to @youdie006 (#130)
Fixed WebVTT styles ignored when
STYLEis followed by whitespace (#133)Fixed WebVTT regions ignored after header text with
-->(#135)Fixed reading SRT and SBV files that start with blank lines or with a cue without text, which raised
MalformedFileError(#142, #158)Fixed non-ASCII digits read as numbers in timestamps and SRT cue indexes, thanks to @emirmrkaljevic (#140, #147)
Fixed
from_bufferkeeping a name that is not a path as thefileto save to, such as<stdin>or the file descriptor of a file opened from one, whichsavewrote to<stdin>.vttor failed on withTypeError(#206, #208)Fixed comparing a
Timestampwith other types raisingAttributeError:==returnsFalseand ordering comparisons raiseTypeError(#137, #150)Fixed the SRT output not ending with a line break (#138, #151)
Fixed SRT output of captions without text, such as text of blank lines, which were written as cues without text that are lost when read back: they are left out and the others numbered consecutively (#166, #202)
Fixed
saveleaving out the Byte Order Mark when the encoding is written differently, such asUTF-8orutf8(#160, #196)Fixed HLS segments repeating a cue that ends on a segment boundary, and the playlist having no segments for captions without cues, thanks to @radixun (#145, #149)
Fixed segmenting raising
IndexErrorfor a cue that ends before it starts, which is now written to the segment it starts in (#152, #154)Fixed the
read_bufferdeprecation warning pointing at the library instead of the code calling it (#139, #153)
0.6.0 (25-10-2026)
This is the last release supporting Python 3.7, 3.8 and 3.9.
Changes that may need updates to the code using the library:
WebVTTtakes keyword arguments only and does not read files, soWebVTT('captions.vtt')raisesTypeError: usewebvtt.readto read captions from a file (#123)Writing WebVTT raises
ValueErrorfor text that could not be read back, such as an empty line or-->in the text of a caption (#122)Malformed cues are skipped when reading, instead of raising
MalformedCaptionError, unlessstrict=True(#93, #99)Timestamps are limited to
9999999999:59:59.999: cues past it are skipped when reading, andshift,syncandchange_framerateraiseValueErrorinstead of moving captions past it (#119)The segment duration must be a whole number above zero, and the MPEG-TS value from 0 to 8589934591 (#125)
Changes:
Added WebVTT regions (#108)
Added cue settings to captions (#107)
Added shift to captions, WebVTT and the CLI (#101)
Added sync and change_framerate to WebVTT and the CLI (#102)
Added Timestamp.from_seconds and Timestamp.in_milliseconds (#100)
Added strict option to raise on malformed cue blocks (#93)
Added keep_formatting to keep bold, italic, underline and the colours of the cue classes when saving SRT, thanks to @darodi (#39, #118)
Added manpage and documentation for the webvtt command (#95)
Added py.typed marker for type checkers (#92)
Added support for Python 3.13, 3.14 and 3.15, and tests on Windows and macOS (#84, #126)
Improved parsing to follow the WebVTT spec for blocks (#98)
Improved parsing to accept non-padded timestamps such as
0:0:7.5, as in Microsoft Teams transcripts, thanks to @apetresc (#45, #99)Improved writing to keep the header text and metadata (#103)
Improved splitting text into lines to only break on CR, LF and CRLF (#104, #105)
Improved reading of SRT cue timings to work as most SRT readers do (#114), and of SBV cue timings to carry over fields over their range (#115)
Allowed more than two digits for timestamp hours, thanks to @hlecnt (#80) and @uzumakienes for SBV (#111)
Improved performance of Caption.text on long lines, thanks to @BrianWillows (#81), and of Caption.voice, thanks to @uzumakienes (#112)
Improved segments to keep the styles, regions and identifiers of the captions (#125)
Deprecated the file argument of WebVTT in favor of the file attribute (#123)
Fixed reading buffers with a leading BOM, thanks to @natesute (#82)
Fixed the HLS playlist to use the configured segment duration, thanks to @shkyyy18 (#83)
Fixed IndexError in slice_segments when the last caption ends on a segment boundary, thanks to @t-hiroishi (#70), and when the captions are not sorted by end time, thanks to @uzumakienes (#110)
Fixed SRT caption text lost after empty lines (#109) and after lines with only digits (#120)
Fixed saving leaving an empty file when the captions cannot be encoded (#121)
Fixed the API reference, the documentation of the exceptions and the examples (#90, #91, #127), and a docstring typo, thanks to @Frenzie (#72)
0.5.1 (30-05-2024)
Added voice span support (#55)
Extended from_buffer support to allow BytesIO and also other format conversions (#32)
Fixed save SRT to not include cue tags, thanks to @lilaboc (#56)
Fixed saved caption to include a line break after the last caption as per standard (#49)
0.5.0 (15-05-2024)
Added styles support
Added comments support
Added from_string
Added iterate over a slice of captions
Refactor of the library
Parser is no longer strict and ignores malformed blocks
Improved BOM support allowing to keep the BOM or remove it
Deprecated read_buffer in favor of from_buffer
Removed support for old versions of Python: 3.4, 3.5 and 3.6
0.4.6 (18-11-2020)
Add capability to get WebVTT formatted content without an output file, thanks to @DawoudSheraz (#34)
Add Python 3.9 support
0.4.5 (09-04-2020)
Fix issue reading buffer
0.4.4 (27-03-2020)
0.4.3 (22-11-2019)
0.4.2 (08-06-2018)
Renamed and reorganized few of the modules
Parsing methods are now class methods: read, from_srt and from_sbv
Improved usability with the addition of shortcuts to avoid instantiating the classes so we can do:
import webvtt
webvtt.read(‘captions.vtt’) # this will return a WebVTT instance
0.4.1 (24-12-2017)
Support for saving cue identifiers
0.4.0 (18-09-2017)
The main goal of this release is a refactor of the WebVTT parser to be able to parse easier and give support to new features of the format.
New features:
Support for cue identifiers
Support for parsing WebVTT captions with comments
Support for parsing WebVTT captions with Style blocks
Support for BOM in caption files
Added method to write the captions to an opened file
Convert WebVTT to SRT format
Ignore empty captions in SRT format
Other:
Refactored WebVTT parser
0.3.3 (23-08-2017)
The text for the caption is now returned clean (tags removed). The cue text could contain tags like: * timestamp tags: <00:19.000> * class tags: <c.classname>text</c> * and others… Important: It currently removes any tag present in the cue text. For example <b> would be removed.
Also a new attribute is available on captions to retrieve the text without cleaning tags: raw_text
0.3.2 (11-08-2017)
The goal of this release if to allow the WebVTT parser to be able to read caption files that contain metadata headers that extend to more than one line.
0.3.1 (08-08-2017)
Made hours in WebVTT parser optional as per specs.
Added support to parse WebVTT files that contain metadata headers.
0.3.0 (02-06-2016)
New features:
Added support for YouTube SBV captions.
Added easy iteration to WebVTT class.
New CLI command for segmenting captions for HLS.
Other:
Improved parsers to reuse functionality.
Added an exception for invalid timestamps in captions.
Added an exception when saving without a filename.
0.2.0 (23-05-2016)
Refactor of the main module and parsers.
0.1.0 (20-05-2016)
This module is released with the following initial features:
Read/Edit/Write WebVTT captions.
Read SRT captions and convert to WebVTT.
Segment WebVTT files for captioning HLS video.