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.
- 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.
- 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.
- Menus, the VMG, and a compiler for DVD navigation commands.
- 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:
- DVD-Video information (IFO, PGC, PCI / DSI, the instruction set; its author worked without the specification);
- Inside DVD-Video (Wikibooks, CC BY-SA).
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. Until it is on PyPI:
pip install git+https://github.com/kajisho5/vtskit
A tag v* on this repository builds the package, attaches it to a GitHub
release and publishes it to PyPI (.github/workflows/release.yml); the
first PyPI release needs the project registered there with this
repository as its trusted publisher. oncemore does not install vtskit: it
carries a copy of vtskit/ as oncemore/_vendor/vtskit, updated with its
tools/vendor_vtskit.py.
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.titlesetwrites 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 andAnglesblocks of 2 to 9 streams: an angle block is interleaved on the disc, its navigation packs point from each unit to every angle's next, and its cells are marked as an angle block.vtskit.subtitlesadds 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.langcompiles 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.vmgwrites 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. Withvtskit.titlesetit writes a whole VIDEO_TS.vtskit.vmencodes the navigation commands (dvdinfo vmi.html): jumps, calls and links, the system and general registers, andIfblocks assembled into Goto lines the way dvdauthor compiles its language (a Set followed by a Link folded into one command, as it does).vtskit.navfills 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.psreads the program stream for both.vtskit.iforeads where each chapter of each title starts, as a sector of the disc, from the IFO files.tests/dvdnav_sim.pyplays 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 (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.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vtskit-0.1.0.tar.gz | 97.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vtskit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 170.2 kB
Release files / vtskit-0.1.0.tar.gz
| Download URL | vtskit-0.1.0.tar.gz |
|---|---|
| Size | 97.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1fdc0144de8ab51dbed0b85de0e48efb2b27c685fdd65d9179d306eb70667e8b
|
|
BLAKE2b-256 checksum How to use checksums |
05909f594bcec3dadcf6fc770808a5b33040be834bb4e89a45cd2743feb513df
|
| 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 11, 2026.
Transparency logRelease files / vtskit-0.1.0-py3-none-any.whl
| Download URL | vtskit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 72.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
907cbc831e30b0c4adf2ad90d8f7b93a87a6456074ded96a1c341a77cc8eb05f
|
|
BLAKE2b-256 checksum How to use checksums |
66b104983501fcb291bb32bb00fd2c45ee81b385e809fec2156664d8a55f7e15
|
| 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 11, 2026.
Transparency log