Skip to main content

Racjin PS2 DSI container multiplexer/demultiplexer

Project description

DSI Muxer

Multiplexer/demultiplexer for the Racjin PS2 DSI container format.

If this helped you, consider buying me a coffee

DSI is a proprietary streaming container used by Racjin for PS2 cutscenes in games like:

  • Fullmetal Alchemist and the Broken Angel
  • Fullmetal Alchemist 2: Curse of the Crimson Elixir
  • Busin 0: Wizardry Alternative NEO

No DSI muxer existed before this tool. VGMToolbox could demux DSI files but not create them.

Install

pip install dsi-muxer

Usage

Command Line

# Extract video and audio from a DSI file
dsi-muxer demux M004.DSI --video M004.m2v --audio M004.adpcm

# Create a new DSI from video + audio (auto-calculates block count)
dsi-muxer mux --video subtitled.m2v --audio jp_audio.adpcm -o M004_new.DSI

# Or specify block count manually
dsi-muxer mux --video subtitled.m2v --audio jp_audio.adpcm --blocks 307 -o M004_new.DSI

# Show DSI file info
dsi-muxer info M004.DSI

Python API

from dsi_muxer import DSI
from dsi_muxer.container import ensure_end_of_sequence

# Demux
dsi = DSI.from_file("M004.DSI")
video = dsi.extract_video()   # MPEG-2 elementary stream
audio = dsi.extract_audio()   # PS2 SPU ADPCM

# Mux with proportional audio (for perfect A/V sync)
video = ensure_end_of_sequence(video)
new_dsi = DSI.mux(video, audio)  # auto block count
# or: DSI.mux(video, audio, nblocks=307)  # explicit
new_dsi.to_file("M004_new.DSI")

# Inspect
for block in new_dsi.block_info():
    print(f"Block {block['block']}: {block['frames']}f, "
          f"aud={block['audio_size']}, vid={block['video_size']}")

How It Works

The DSI Format

DSI files are divided into fixed 0x40000 byte (256 KB) blocks. Each block contains:

  • A 32-byte header identifying two streams (audio + video) with type tags and sizes
  • 32 bytes of zero padding
  • Interleaved audio and video data

Audio uses PS2 SPU ADPCM (44100 Hz, stereo, 0x100 interleave). Video is MPEG-2 Main Profile (512x448, 29.97 fps).

Proportional Audio Muxing

The key to perfect A/V sync in DSI is proportional audio distribution:

audio_per_block = frames_in_block * (total_audio / total_frames)

Blocks with more video frames get more audio. This ensures each block's audio duration matches its video duration. The PS2's SPU2 buffer smooths per-block variation.

The video is byte-sliced as a continuous stream — GOPs flow freely across block boundaries, just like the original game files. No per-block re-encoding or extra sequence headers.

Why This Matters

Unlike Sony's standard PSS format (which has timestamps for A/V sync), DSI has no timestamps. Sync is entirely determined by the audio/video ratio per block. Getting this ratio wrong causes audible desync during PS2 playback.

Format Reference

Block Header (32 bytes, little-endian)

Offset Type Field
0x00 uint32 Stream count (always 2)
0x04 uint32 Stream 1 offset (always 64)
0x08 int32 Stream 1 type (-8192=audio, -16384=video)
0x0C uint32 Stream 1 size
0x10 uint32 Stream 2 offset
0x14 int32 Stream 2 type
0x18 uint32 Stream 2 size
0x1C uint32 Reserved (always 0)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dsi_muxer-1.4.1.tar.gz (12.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dsi_muxer-1.4.1-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file dsi_muxer-1.4.1.tar.gz.

File metadata

  • Download URL: dsi_muxer-1.4.1.tar.gz
  • Upload date:
  • Size: 12.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for dsi_muxer-1.4.1.tar.gz
Algorithm Hash digest
SHA256 7332e84dfbdb23e53a6a111709023c418d4ac3e67efda7fd4948cdb58eb134bf
MD5 c141321785078450421630a816869f0e
BLAKE2b-256 89e80503d507540f639999b30b2dbc22c1cdae8f38f99f7d4b236216f9736dc9

See more details on using hashes here.

File details

Details for the file dsi_muxer-1.4.1-py3-none-any.whl.

File metadata

  • Download URL: dsi_muxer-1.4.1-py3-none-any.whl
  • Upload date:
  • Size: 9.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for dsi_muxer-1.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7edce82a27edc03a79a14abf9b913c24f5fb8de1431a600d263901f48fd7e39e
MD5 50109a021b8f2d4bc3468238e8782aa0
BLAKE2b-256 bb30236282132b8497125f3eec1aaac01567be3c60b592598c8414a605d985c0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page