Skip to main content

vtskit

vtskit

DVD-Video authoring in pure Python, in place of dvdauthor. vtskit writes VIDEO_TS itself: the IFO files, the VOBs' navigation packs, menus, subtitles, angle blocks and the DVD's navigation commands, which it also compiles from dvdauthor's command language. Where dvdauthor writes the same thing, vtskit's bytes are dvdauthor's (see What is here now); oncemore writes its discs with it since oncemore#90 (angles since #91).

日本語の説明は README.ja.md にあります。

Why

Open-source DVD authoring today means dvdauthor. It is old, and some things it cannot do at all, multi-angle titles for one. ffmpeg writes DVD program streams, but leaves their navigation packs empty. vtskit is meant to be a complete, tested writer that tools can build on, as bdmvkit is for Blu-ray.

Plan

It grows out of oncemore, step by step, each step checked against the same playback tests. The full plan is in oncemore#75.

  1. A titleset writer, for ordinary titles first: the VOBs (split at 1 GiB), their navigation packs (PCI / DSI) and the VTS IFO with its BUP, compared with what dvdauthor writes for the same title. It includes a small encoder for the navigation commands oncemore's titles carry (pre, post and cell commands, given as numbers, not as a language), so it can replace dvdauthor's titlesets for real discs.
  2. Titles with several angles, which dvdauthor cannot make: interleaved angle blocks, and the VMG's title table and titleset attributes kept in step with them.
  3. Menus, the VMG, and a compiler for DVD navigation commands.
  4. oncemore without dvdauthor.

Ordinary titles come first because they can be checked against dvdauthor field by field, and an angle block cannot be checked before the titleset around it is right.

Input: the MPEG-2 program stream oncemore's encoder makes (ffmpeg -f dvd, 2048-byte packs, a navigation pack at every GOP with its PCI and DSI left empty), with subtitles added by spumux if there are any. vtskit fills in the navigation packs; every other pack keeps its place, except packs of padding alone (spumux leaves some), which are dropped as dvdauthor drops them.

Clean implementation: the DVD-Video specification itself is not public (it was licensed under NDA by DVD FLLC). vtskit is written from public descriptions of the format:

Where they say nothing, the bytes dvdauthor writes are observed; its source is not read, nor libdvdread's or libdvdnav's. libdvdnav is only used in the tests, through its public API (the function declarations of dvdnav.h), to play the discs vtskit writes.

Installing

vtskit is one package of plain Python (3.11 or later), with nothing else to install:

pip install vtskit

A release is made by the version: when the version in pyproject.toml (and vtskit/__init__.py) reaches main without a tag of its own, .github/workflows/release.yml runs the tests, builds the package, makes the GitHub release with its tag and publishes to PyPI. Merging the version bump is the whole act; a tag v* pushed by hand releases the same way. PyPI knows this repository and workflow as the project's trusted publisher. oncemore does not install vtskit: it carries a copy of each release as oncemore/_vendor/vtskit, taken from PyPI with its tools/vendor.py vtskit --pypi <version> (a pull request does it there each day a newer release is out).

What is here now

The four steps of the plan are in: discs with titles, menus, subtitles and angles, dvdauthor's command language, what they are checked with, and oncemore writing its discs with vtskit.

  • vtskit.titleset writes a titleset: the title VOBs (one a title, cut into files under 1 GiB) with their navigation packs filled, and VTS_nn_0.IFO with its BUP: the streams' attributes, each title's chapters, a program chain a title (programs and cells one a chapter, its pre, post and cell commands given as bytes), the time maps, the cell and VOBU address tables. A chapter starts at the VOBU nearest its time, as dvdauthor places it. A title's stream is read through a memory map and copied out in blocks, its navigation packs kept aside, so a title of gigabytes is not held in memory. With menus (vtskit.menu: a Menu's stream, its Buttons with their rectangles, arrow-key neighbours and commands, its cells and which remote key it answers) it also writes the menu VOB, with the button overlay as a subpicture (vtskit.spu; invisible until a button is selected, or drawn in a normal colour all the time) and the highlight information in every navigation pack, and the menu tables of the IFO. A menu without a stream is a program chain of commands alone, as dvdauthor writes a <pgc> without a <vob> (a title menu that only jumps on, a titleset's root menu that only routes). Menus answer the remote keys they are marked for (root, audio, subpicture, angle, PTT); as dvdauthor arranges it, a domain whose menus name no root menu makes its first menu the root, and a titleset without a chapter menu gets one that links to the first menu. A title may name the program chains that follow, precede and contain it (next_pgc, prev_pgc, up_pgc): under libdvdnav a title whose post commands run out plays on into its next program chain; dvdauthor writes none of these. A title may be several parts in a row, streams and Angles blocks of 2 to 9 streams: an angle block is interleaved on the disc and its cells are marked as an angle block. A seamless block (the default) is switched at the end of an interleaved unit: its navigation packs point from each unit to every angle's next (SML_AGLI) and its cells say "seamless angle"; a block switched with a break (seamless=False) points instead at every angle's VOBU of the same moment (NSML_AGLI). Only one of the two is filled, as players take NSML_AGLI whenever it is there. A stream whose interleaved units start with open groups of pictures (B-pictures leaning on the group before, another angle's after a switch) is refused.
  • vtskit.subtitles adds subtitles to a title's program stream, as spumux does: each cue a picture of up to four colours placed on the screen and shown for a while, as subpicture packs a little before their time.
  • vtskit.lang compiles dvdauthor's command language (jump title 2;, if (g5 != 0) { button = g5; }, call menu entry root;) for the domain a text runs in, to the same commands dvdauthor writes for it: a tool that already speaks the language, as oncemore does, keeps its text. A button of several commands runs them from the menu's post through a dispatcher, and a jump to a chapter of another titleset goes through pad program chains, as dvdauthor's "jumppads" do.
  • vtskit.vmg writes the video manager: VIDEO_TS.IFO and its BUP, with the first-play commands, the table of titles and the titlesets' attributes, and VIDEO_TS.VOB with the title menu when there is one. With vtskit.titleset it writes a whole VIDEO_TS.
  • vtskit.vm encodes the navigation commands (dvdinfo vmi.html): jumps, calls and links, the system and general registers, and If blocks assembled into Goto lines the way dvdauthor compiles its language (a Set followed by a Link folded into one command, as it does).
  • vtskit.nav fills the navigation packs of a VOB: the PCI (times) and DSI (where the VOBU and its reference pictures end, where the VOBUs 0.5 s to 120 s away start, where its sound and subtitles start). vtskit.ps reads the program stream for both.
  • vtskit.ifo reads where each chapter of each title starts, as a sector of the disc, from the IFO files.
  • tests/dvdnav_sim.py plays a disc with libdvdnav through ctypes: titles, chapters, menus and buttons, sound and subtitle tracks, and angles.

The tests give the same titles to dvdauthor and to vtskit, and the IFO and the VOBs must be the same byte for byte: NTSC and PAL, 4:3 and 16:9, chapters on and between VOBU starts, two titles in a titleset, AC-3, LPCM and MPEG sound with languages, B-pictures, short GOPs, a 40-second title, a subtitle track, two titlesets; every command form is the bytes dvdauthor compiles for the same statement, and a disc described in its language (menus of commands alone, buttons of several commands, cell commands, two titlesets) comes out with the same IFOs; for menus, the highlight information of every navigation pack and the IFOs' menu tables are dvdauthor's (its buttons made with spumux), and a menu's overlay in a normal colour is spumux's unit byte for byte; subtitles muxed by vtskit are spumux's units, placed where spumux places them, and the title written from that stream (4:3, and 16:9 with and without pan-scan or letterbox) is dvdauthor's. A VIDEO_TS written by vtskit alone plays its titles and chapters in order under libdvdnav, its commands jumping between titles, its menus' buttons lead where they say, and its jumps into another titleset's chapters land; a title with an angle block plays and switches angles under libdvdnav, every pointer of its navigation packs landing on the unit it names, and the pictures libdvdnav hands a player through a switch, decoded with ffmpeg, are every picture once, in order, the new angle from the end of a unit (dvdauthor writes no angles, so a set-top player is the check still owed) (python -m unittest discover -s tests -t .; a test is skipped when a tool it needs is missing). oncemore's switch to vtskit (step 4) is merged: oncemore#90 and #91 keep a copy of vtskit/ as oncemore/_vendor/vtskit.

vtskit.ifo and tests/dvdnav_sim.py come from oncemore (its layerbreak.py and tests/dvdnav_sim.py, GPL-3.0 there) and are relicensed here under LGPL-3.0-or-later by their author.

Support

vtskit is free and stays free. If it saves you time, you can support its development through GitHub Sponsors (the Sponsor button at the top of this repository). Bug reports help just as much: Issues.

The logo, colours and writing rules: docs/DESIGN.md.

License

GNU Lesser General Public License, version 3 or later. See COPYING.LESSER and COPYING.

Metadata

Release files for vtskit 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vtskit 0.1.1
File Size Uploaded
vtskit-0.1.1.tar.gz 100.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vtskit 0.1.1
File Interpreter ABI Platform
vtskit-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 174.5 kB

Release files / vtskit-0.1.1.tar.gz

Download URL vtskit-0.1.1.tar.gz
Size 100.9 kB
Tags Source
SHA-256 checksum
How to use checksums
61c295e6791d71ebd8fe6151b280b77da6d3e4230b68caf938b320f4f596fbc5
BLAKE2b-256 checksum
How to use checksums
73550a8c7aab656cced935dca6b0a1f234d742d12ce23f69908f82f6e4f0c425
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / vtskit-0.1.1-py3-none-any.whl

Download URL vtskit-0.1.1-py3-none-any.whl
Size 73.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a99c08702325971e9b1490eee4a3c8ac83759b9079709bfc3dfdaf8ded3d70ba
BLAKE2b-256 checksum
How to use checksums
9be4211a825e1c294510ee1b1b4574a9be7d2e3169a30e58ea7f79a73b96351d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page