PyCriCodecsEx documentation

This site contains automatically generated API documentation for every format PyCriCodecsEx supports.

Most if not all features are verified to work with either commercial games, or official SDK tools. However issues are to be expected - submit bug reports or feature requests on the Issue Tracker.

PyCriCodecsEx is a fork of Youjose/PyCriCodecs. Refer to the original repository and its Wiki for more information.

The GitHub repository is available at mos9527/PyCriCodecsEx

Installation

PyCriCodecsEx is available on PyPI

pip install PyCriCodecsEx

For USM features, you need ffmpeg installed and available in your PATH, and install the [usm] extra - which installs ffmpeg-python.

To make sure ffmpeg is available, you can refer to ffmpeg-python’s instructions.

pip install PyCriCodecsEx[usm]

Support Status

USM Sofdec2 (Encode & Decode)

Audio Stream

Decoding and Encoded format can be the following:

  • HCA

  • ADX

Video Stream

NOTE: You definitely want to tweak these encode settings a bit.

  • Sofdec Prime (MPEG1, from .m1v container)

    • Prepare source file with: ffmpeg -i <input_file> -c:v mpeg1video -an <output_file>.m1v

  • H264 (from .h264 raw container)

    • Prepare source file with: ffmpeg -i <input_file> -c:v libx264 -an <output_file>.h264

  • VP9 (from .ivf container)

    • Prepare source file with: ffmpeg -i <input_file> -c:v libvpx -an <output_file>.ivf

CPK

  • Unpacking

  • Packing

ACB Cue sheets (also AWB)

  • Cue extraction support for most ACBs

  • Cue waveform(s) encoding with ADX/HCA support

  • Comprehensive Cue metadata editing support (via Python API)

ADX Audio Codec

  • Decoding

  • Encoding

HCA Audio Codec

  • Decoding (up to version 3.0)

  • Encoding (up to version 3.0)

Roadmap

  • Interface for encode tasks (most probably done in a separate project)

  • C/C++ port + FFI

Currently Known Bugs

  • USM seeking does not work. Though most games don’t use it anyways.

  • Not important, and might not fix: ADX encoding and decoding at higher bitdepths (11-15) adds popping noise.

  • Some CPK’s that has the same filename for every file in the entry will overwrite each other.

  • Probably many more I am unaware of, report if you find any.

USM (Sofdec 2) Video Codecs

class PyCriCodecsEx.usm.FFmpegCodec(stream: str | bytes)[source]

Bases: object

Base codec for FFMpeg-based Video streams

__init__(stream: str | bytes)[source]

Initialize FFmpegCodec with a media stream, gathering metadata and frame info.

Parameters:

stream (str | bytes) – The media stream to process.

Note

A temp file maybe created for probing only. Which will be deleted after use.

frames()[source]

Generator of [frame data, frame dict, is keyframe, duration]

save(filepath: str)[source]

Saves the underlying video stream to a file.

property avg_framerate

Average framerate

property framerate

Running framerate (max frame rate)

class PyCriCodecsEx.usm.H264Codec(filename: str | bytes)[source]

Bases: FFmpegCodec

H264 Video stream codec.

Only streams with .h264 containers are supported.

__init__(filename: str | bytes)[source]

Initialize FFmpegCodec with a media stream, gathering metadata and frame info.

Parameters:

stream (str | bytes) – The media stream to process.

Note

A temp file maybe created for probing only. Which will be deleted after use.

class PyCriCodecsEx.usm.MPEG1Codec(stream: str | bytes)[source]

Bases: FFmpegCodec

MPEG1 Video stream codec.

Only streams with .mpeg1 containers are supported.

__init__(stream: str | bytes)[source]

Initialize FFmpegCodec with a media stream, gathering metadata and frame info.

Parameters:

stream (str | bytes) – The media stream to process.

Note

A temp file maybe created for probing only. Which will be deleted after use.

class PyCriCodecsEx.usm.USM(filename: str | BinaryIO, key: str | int = None)[source]

Bases: USMCrypt

Use this class to extract infromation and data from a USM file.

__init__(filename: str | BinaryIO, key: str | int = None)[source]

Loads a USM file into memory and prepares it for processing.

Parameters:
  • filename (str) – The path to the USM file.

  • key (str, optional) – The decryption key. Either int64 or a hex string. Defaults to None.

get_audios() List[ADXCodec | HCACodec][source]

Create a list of audio codecs from the available streams.

get_video() VP9Codec | H264Codec | MPEG1Codec[source]

Create a video codec from the available streams.

NOTE: A temporary file may be created with this process to determine the stream information.

property streams

Generator of Tuple[Stream Type (“@SFV”, “@SFA”), File name, Raw stream data]

class PyCriCodecsEx.usm.USMBuilder(key=None, encrypt_audio=False)[source]

Bases: USMCrypt

Use this class to build USM files.

__init__(key=None, encrypt_audio=False) None[source]

Initialize the USMBuilder from set source files.

Parameters:
  • key (str | int, optional) – The encryption key. Either int64 or a hex string. Defaults to None.

  • encrypt_audio (bool, optional) – Whether to also encrypt the audio. Defaults to False.

add_audio(audio: ADXCodec | HCACodec)[source]

Append the audio stream(s) from the specified audio file(s).

Parameters:

audio (ADXCodec | HCACodec) – The path(s) to the audio file(s).

add_video(video: str | H264Codec | VP9Codec | MPEG1Codec)[source]

Sets the video stream from the specified video file.

USMs only support one video stream. Consecutive calls to this method will replace the existing video stream.

When video is str - it will be treated as a file path. The video source format will be used to map accordingly to the ones Sofdec use.
  • MPEG1 (with M1V container): MPEG1 Codec (Sofdec Prime)

  • H264 (with H264 container): H264 Codec

  • VP9 (with IVF container): VP9 Codec

Parameters:

video (str | FFmpegCodec) – The path to the video file or an FFmpegCodec instance.

build() bytes[source]

Build the USM payload

class PyCriCodecsEx.usm.USMCrypt[source]

Bases: object

USM related crypto functions

class PyCriCodecsEx.usm.VP9Codec(filename: str | bytes)[source]

Bases: FFmpegCodec

VP9 Video stream codec.

Only streams with .ivf containers are supported.

__init__(filename: str | bytes)[source]

Initialize FFmpegCodec with a media stream, gathering metadata and frame info.

Parameters:

stream (str | bytes) – The media stream to process.

Note

A temp file maybe created for probing only. Which will be deleted after use.

CPK File Pack

class PyCriCodecsEx.cpk.CPK(filename: str | BinaryIO)[source]

Bases: object

Use this class to load CPK file table-of-content, and read files from them on-demand.

__init__(filename: str | BinaryIO) None[source]

Loads a CPK archive’s table-of-content and ready for file reading.

Parameters:

filename (str | BinaryIO) – The path to the CPK file or a BinaryIO stream containing the CPK data.

property files: Generator[PackedFile, None, None]

Creates a generator for all files in the CPK archive as PackedFile.

property mode

Get the current mode of the CPK archive. [0,1,2,3]

See also CPKBuilder

class PyCriCodecsEx.cpk.CPKBuilder(mode: int = 1, Tver: str = None, encrypt: bool = False, encoding: str = 'utf-8', progress_cb: callable = None)[source]

Bases: object

Use this class to build semi-custom CPK archives.

__init__(mode: int = 1, Tver: str = None, encrypt: bool = False, encoding: str = 'utf-8', progress_cb: callable = None) None[source]

Setup CPK file building

Parameters:
  • mode (int, optional) – CPK mode. 0: ID Only (ITOC), 1: Name Only (TOC), 2: Name + ID (ITOC + TOC), 3: Name + ID + GTOC (GTOC). Defaults to 1.

  • Tver (str, optional) – CPK version. Defaults to None.

  • encrypt (bool, optional) – Enable encryption. Defaults to False.

  • encoding (str, optional) – Filename encoding. Defaults to “utf-8”.

  • progress_cb (callable, optional) – Progress callback taking (task name, current, total). Defaults to None.

add_file(src: str, dst: str = None, compress=False)[source]

Add a file to the bundle.

Parameters:
  • src (str) – The source file path.

  • dst (str) – The destination full file name (containing directory). Can be None in ITOC Mode. Defaults to None.

  • compress (bool, optional) – Whether to compress the file. Defaults to False.

Note

  • In ITOC-related mode, the insertion order determines the final integer ID of the files.

  • Compression can be VERY slow with high entropy files (e.g. encoded media). Use at discretion.

save(outfile: str | BinaryIO, parallel: bool = False)[source]

Build and save the bundle into a file

Parameters:
  • outfile (str | BinaryIO) – The output file path or a writable binary stream.

  • parallel (bool, optional) – Whether to use parallel processing for file compression (if at all used). Defaults to False.

Note

  • Temporary files may be created during the process if compression is used.

  • parallel uses multiprocessing. Make sure your main function is guarded with if __name__ == ‘__main__’ clause.

class PyCriCodecsEx.cpk.PackedFile(stream: BinaryIO, path: str, offset: int, size: int, compressed: bool = False)[source]

Bases: object

Helper class for packed files within a CPK.

__init__(stream: BinaryIO, path: str, offset: int, size: int, compressed: bool = False) None
get_bytes() bytes[source]

Get the raw bytes of the packed file, decompressing if necessary.

save(path: str)[source]

Save the packed file to a specified path.

ACB Cuesheet Binaries

class PyCriCodecsEx.acb.ACB(stream: str | BinaryIO)[source]

Bases: UTF

Use this class to read, and modify ACB files in memory.

__init__(stream: str | BinaryIO) None[source]

Loads an ACB file from the given stream.

Parameters:

stream (str | BinaryIO) – The path to the ACB file or a BinaryIO stream containing the ACB data.

get_waveforms() List[HCACodec | ADXCodec | Tuple[AcbEncodeTypes, int, int, int, bytes]][source]

Returns a list of decoded waveforms.

Item may be a codec (if known), or a tuple of (Codec ID, Channel Count, Sample Count, Sample Rate, Raw data).

set_waveforms(value: List[HCACodec | ADXCodec | Tuple[AcbEncodeTypes, int, int, int, bytes]])[source]

Sets the waveform data.

Input item may be a codec (if known), or a tuple of (Codec ID, Channel Count, Sample Count, Sample Rate, Raw data).

NOTE: Cue duration is not set. You need to change that manually.

property awb: AWB

Returns the AWB object associated with the ACB.

property cues: Generator[PackedCueItem, None, None]

Returns a generator of read-only Cues.

Cues reference waveform bytes by their AWB IDs, which can be accessed via waveforms. To modify cues, use the view property instead.

property name: str

Returns the name of the ACB file.

property payload: dict

Retrives the only UTF table dict within the ACB file.

property view: ACBTable

Returns a view of the ACB file, with all known tables mapped to their respective classes.

  • Use this to interact with the ACB payload instead of payload for helper functions, etc

class PyCriCodecsEx.acb.ACBBuilder(acb: ACB)[source]

Bases: object

Use this class to build ACB files from an existing ACB object.

__init__(acb: ACB) None[source]

Initializes the ACBBuilder with an existing ACB object.

Parameters:

acb (ACB) – The ACB object to build from.

Building ACB from scratch isn’t planned for now since:

  • We don’t know how SeqCommandTable TLVs work. This is the biggest issue.

  • Many fields are unknown or not well understood

  • Games may expect AcfReferenceTable, Asiac stuff etc to be present for their own assets in conjunction

    with their own ACF table. Missing these is not a fun debugging experience.

  • ACB tables differ a LOT from game to game (e.g. Lipsync info), contary to USM formats.

Maybe one day I’ll get around to this. But otherwise starting from nothing is a WONTFIX for now.

build() bytes[source]

Builds an ACB binary blob from the current ACB object.

The object may be modified in place before building, which will be reflected in the output binary.

acb: ACB
class PyCriCodecsEx.acb.ACBTable(payload: list | dict, **args)[source]

Bases: UTFViewer

ACB Table View

waveform_of(index: int) List[WaveformTable][source]

Retrieves the waveform(s) associated with a cue.

Cues may reference multiple waveforms, which could also be reused.

AcbGuid: bytes

GUID of the ACB. This SHOULD be different for each ACB file.

AwbFile: bytes
CueNameTable: List[CueNameTable]

A list of cue names with their corresponding indices into CueTable

CueTable: List[CueTable]

A list of cues with their corresponding references

Name: str

Name of the ACB. This is usually the name of the sound bank.

SequenceTable: List[SequenceTable]
SynthTable: List[SynthTable]
TrackEventTable: List[TrackEventTable]
TrackTable: List[TrackTable]
Version: int
VersionString: str
WaveformTable: List[WaveformTable]
class PyCriCodecsEx.acb.CueNameTable(payload: list | dict, **args)[source]

Bases: UTFViewer

CueIndex: int

Index into CueTable

CueName: str

Name of the cue

class PyCriCodecsEx.acb.CueTable(payload: list | dict, **args)[source]

Bases: UTFViewer

CueId: int

Corresponds to the cue index found in CueNameTable

Length: int

Duration of the cue in milliseconds

ReferenceIndex: int
ReferenceType: int
class PyCriCodecsEx.acb.PackedCueItem(CueId: int, CueName: str, Length: float, Waveforms: list[int])[source]

Bases: object

Helper class for read-only cue information

__init__(CueId: int, CueName: str, Length: float, Waveforms: list[int]) None
CueId: int

Cue ID

CueName: str

Cue name

Length: float

Duration in seconds

Waveforms: list[int]

List of waveform IDs, corresponds to ACB.get_waveforms()

class PyCriCodecsEx.acb.SequenceTable(payload: list | dict, **args)[source]

Bases: UTFViewer

NumTracks: int
TrackIndex: bytes
Type: int
class PyCriCodecsEx.acb.SynthTable(payload: list | dict, **args)[source]

Bases: UTFViewer

ReferenceItems: bytes
class PyCriCodecsEx.acb.TrackEventTable(payload: list | dict, **args)[source]

Bases: UTFViewer

Command: bytes
class PyCriCodecsEx.acb.TrackTable(payload: list | dict, **args)[source]

Bases: UTFViewer

EventIndex: int
class PyCriCodecsEx.acb.WaveformTable(payload: list | dict, **args)[source]

Bases: UTFViewer

EncodeType: int
MemoryAwbId: int
NumChannels: int
NumSamples: int
SamplingRate: int
Streaming: int

ADX ADPCM Audio Codec

class PyCriCodecsEx.adx.ADX[source]

Bases: object

ADX class for decoding and encoding ADX files, pass the either adx file or wav file in bytes to either decode or encode respectively.

NOTE: Direct usage of this class is not recommended, use the ADXCodec wrapper instead.

static decode(data: bytes) bytes[source]

Decodes ADX to WAV.

static encode(data: bytes, BitDepth=4, Blocksize=18, Encoding=3, AdxVersion=4, Highpass_Frequency=500, Filter=0, force_not_looping=False) bytes[source]

Encodes WAV to ADX.

class PyCriCodecsEx.adx.ADXCodec(stream: str | bytes, filename: str = 'default.adx', bitdepth: int = 4, **kwargs)[source]

Bases: ADX

Use this class for encoding and decoding ADX files, from and to WAV.

__init__(stream: str | bytes, filename: str = 'default.adx', bitdepth: int = 4, **kwargs)[source]

Initializes the ADX encoder/decoder

Parameters:
  • stream (str | bytes) – Path to the ADX or WAV file, or a BinaryIO stream. WAV files will be automatically encoded with the given settings first.

  • filename (str, optional) – Output filename. Defaults to “default.adx”.

  • bitdepth (int, optional) – Audio bit depth within [2,15]. Defaults to 4.

get_encoded() bytes[source]

Gets the encoded ADX audio data.

save(filepath: str | BinaryIO)[source]

Saves the decoded WAV audio to filepath or a writable stream

HCA Audio Codec

class PyCriCodecsEx.hca.HCA(stream: str | BinaryIO, key: int = 0, subkey: int = 0)[source]

Bases: object

HCA class for decoding and encoding HCA files

NOTE: Direct usage of this class is not recommended, use the HCACodec wrapper instead.

__init__(stream: str | BinaryIO, key: int = 0, subkey: int = 0) None[source]

Initializes the HCA encoder/decoder

Parameters:
  • stream (str | BinaryIO) – Path to the HCA or WAV file, or a BinaryIO stream.

  • key (int, optional) – HCA key. Defaults to 0.

  • subkey (int, optional) – HCA subkey. Defaults to 0.

decode() bytes[source]

Decodes the HCA or WAV file to WAV bytes.

encode(force_not_looping: bool = False, encrypt: bool = False, keyless: bool = False, quality_level: CriHcaQuality = CriHcaQuality.High) bytes[source]

Encodes the WAV file to HCA bytes.

get_frames()[source]

Generator function to yield Frame number, and Frame data.

get_hca() bytes[source]

Get the HCA file bytes after encrypting or decrypting.

get_header() bytes[source]

Get the HCA Header.

info() dict[source]

Returns info related to the input file.

class PyCriCodecsEx.hca.HCACodec(stream: str | bytes, filename: str = 'default.hca', quality: CriHcaQuality = CriHcaQuality.High, key=0, subkey=0, **kwargs)[source]

Bases: HCA

Use this class for encoding and decoding HCA files, from and to WAV.

__init__(stream: str | bytes, filename: str = 'default.hca', quality: CriHcaQuality = CriHcaQuality.High, key=0, subkey=0, **kwargs)[source]

Initializes the HCA encoder/decoder

Parameters:
  • stream (str | bytes) – Path to the HCA or WAV file, or a BinaryIO stream. WAV files will be automatically encoded with the given settings first.

  • filename (str, optional) – USM filename. Defaults to “default.hca”.

  • quality (CriHcaQuality, optional) – Encoding quality. Defaults to CriHcaQuality.High.

  • key (int, optional) – HCA key. Defaults to 0.

  • subkey (int, optional) – HCA subkey. Defaults to 0.

get_encoded() bytes[source]

Gets the encoded HCA audio data.

save(filepath: str | BinaryIO)[source]

Saves the decoded WAV audio to filepath or a writable stream

AWB File Blobs

class PyCriCodecsEx.awb.AWB(stream: str | BinaryIO)[source]

Bases: object

Use this class to return any AWB data with the getfiles function.

__init__(stream: str | BinaryIO) None[source]

Initializes the AWB object

Parameters:

stream (str | BinaryIO) – Source file path or binary stream

get_file_at(index) bytes[source]

Gets you a file at specific index.

get_files() Generator[bytes, None, None][source]

Generator function to yield all data blobs from an AWB.

class PyCriCodecsEx.awb.AWBBuilder(infiles: list[bytes], subkey: int = 0, version: int = 2, id_intsize=2, align: int = 32)[source]

Bases: object

Use this class to build AWB files from a list of bytes.

__init__(infiles: list[bytes], subkey: int = 0, version: int = 2, id_intsize=2, align: int = 32) None[source]

Initializes the AWB builder.

Parameters:
  • infiles (list[bytes]) – List of bytes to be included in the AWB file.

  • subkey (int, optional) – AWB subkey. Defaults to 0.

  • version (int, optional) – AWB version. Defaults to 2.

  • id_intsize (hexadecimal, optional) – Integer size (in bytes) for string lengths. Defaults to 0x2.

  • align (int, optional) – Alignment. Defaults to 0x20.

build() bytes[source]

Builds the AWB file from the provided infiles bytes.

UTF Tables

class PyCriCodecsEx.utf.UTF(stream: str | BinaryIO, recursive=False)[source]

Bases: object

Use this class to unpack @UTF table binary payload.

__init__(stream: str | BinaryIO, recursive=False)[source]

Unpacks UTF table binary payload

Parameters:
  • stream (Union[str | BinaryIO]) – The input stream or file path to read the UTF table from.

  • recursive (bool) – Whether to recursively unpack nested UTF tables.

property dictarray: list[dict]

Returns a list representation of the UTF table.

property table: dict

Returns a dictionary representation of the UTF table.

Effectively, this retrieves a transposed version of the dictarray. Whilst discarding type info.

This is mostly here for cpk.py compatibility.

class PyCriCodecsEx.utf.UTFBuilder(dictarray_src: list[dict], encrypt: bool = False, encoding: str = 'utf-8', table_name: str = 'PyCriCodecs_table', ignore_recursion: bool = False)[source]

Bases: object

Use this class to build UTF table binary payloads from a dictarray.

__init__(dictarray_src: list[dict], encrypt: bool = False, encoding: str = 'utf-8', table_name: str = 'PyCriCodecs_table', ignore_recursion: bool = False) None[source]

Packs UTF payload back into their binary form

Parameters:
  • dictarray_src – list[dict]: A list of dictionaries representing the UTF table.

  • encrypt – Whether to encrypt the table (default: False).

  • encoding – The character encoding to use (default: “utf-8”).

  • table_name – The name of the table (default: “PyCriCodecs_table”).

  • ignore_recursion – Whether to ignore recursion when packing (default: False).

bytes() bytearray[source]

Returns a @UTF bytearray Table from the provided payload dict.

class PyCriCodecsEx.utf.UTFViewer(payload: list | dict, **args)[source]

Bases: object

Use this class to create dataclass-like access to `dictarray`s.

class ListView(clazz: Type[Ty], payload: list[Ty])[source]

Bases: list

__init__(clazz: Type[Ty], payload: list[Ty])[source]
append(o: UTFViewer)[source]

Append object to the end of the list.

clear()[source]

Remove all items from list.

count(value)[source]

Return number of occurrences of value.

extend(iterable)[source]

Extend list by appending elements from the iterable.

insert(index, o: UTFViewer)[source]

Insert object before index.

pop(index=-1)[source]

Remove and return item at index (default last).

Raises IndexError if list is empty or index is out of range.

remove(value)[source]

Remove first occurrence of value.

Raises ValueError if the value is not present.

sort(key: callable)[source]

Sort the list in ascending order and return None.

The sort is in-place (i.e. the list itself is modified) and stable (i.e. the order of two equal elements is maintained).

If a key function is given, apply it once to each list item and sort them, ascending or descending, according to their function values.

The reverse flag can be set to sort in descending order.

__init__(payload)[source]

Construct a non-owning read-write, deletable view of a UTF table dictarray.

Nested classes are supported.

Sorting (using .sort()) is done in-place and affects the original payload.

Enums and Constants

class PyCriCodecsEx.chunk.AWBType(value)[source]

Bases: Enum

AFS2 = b'AFS2'
class PyCriCodecsEx.chunk.AcbEncodeTypes(value)[source]

Bases: Enum

AACM4A = 17
ADX = 0
ADX_ALT = 3
ATRAC3 = 8
ATRAC9 = 11
CWACDSP = 14
CWAV = 9
DSP = 13
HCA = 2
HCAMX = 6
HEVAG = 10
NDSDSP = 5
PCM = 1
PS4ATRAC9 = 16
PS4HEVAG = 15
SwitchOpus = 18
VAG = 7
WiiDSP = 4
X360XMA = 12
class PyCriCodecsEx.chunk.CPKChunkHeaderType(value)[source]

Bases: Enum

CPK = b'CPK '
ETOC = b'ETOC'
GTOC = b'GTOC'
HGTOC = b'HGTOC'
HTOC = b'HTOC'
ITOC = b'ITOC'
TOC = b'TOC '
class PyCriCodecsEx.chunk.CriHcaQuality(value)[source]

Bases: Enum

High = 1
Highest = 0
Low = 3
Lowest = 5
Middle = 2
class PyCriCodecsEx.chunk.HCAType(value)[source]

Bases: Enum

EHCA = b'\xc8\xc3\xc1\x00'
HCA = b'HCA\x00'
class PyCriCodecsEx.chunk.USMChunckHeaderType(value)[source]

Bases: Enum

AHX = b'@AHX'
ALP = b'@ALP'
CRID = b'CRID'
CUE = b'@CUE'
PST = b'@PST'
SBT = b'@SBT'
SFA = b'@SFA'
SFSH = b'SFSH'
SFV = b'@SFV'
USR = b'@USR'
class PyCriCodecsEx.chunk.UTFType(value)[source]

Bases: Enum

EUTF = b'\x1f\x9e\xf3\xf5'
UTF = b'@UTF'
class PyCriCodecsEx.chunk.UTFTypeValues(value)[source]

Bases: Enum

bytes = 11
char = 1
double = 9
float = 8
int = 5
llong = 7
short = 3
string = 10
uchar = 0
uint = 4
ullong = 6
ushort = 2

Examples

Examples are available at Tests.