Skip to main content

Read and write Annotation PRO .antx files (XML format)

Project description

annotationpro-format

Python library for reading and writing Annotation PRO .antx files (XML annotation format used by the Annotation PRO application).

About ANTX files

ANTX files are XML documents that store speech or audio annotations: layers, segments (with labels and time bounds), and project configuration. They are produced and consumed by Annotation PRO.

Time in ANTX is stored in samples, not in seconds. Each annotation file has a samplerate (e.g. 44100 Hz) in its configuration. Segment start and duration in the file are sample counts. To work in seconds you can use the samplerate from the annotation and the helper functions provided by this library (see below).

Requirements

  • Python 3.9+

Installation

From PyPI:

pip install annotationpro-format

From source (development):

pip install -e .

Usage

Reading an ANTX file

from annotationpro_format import deserialize_annotation

with open("project.antx", "r", encoding="utf-8") as f:
    xml_content = f.read()

annotation = deserialize_annotation(xml_content)
samplerate = int(annotation.configuration["Samplerate"])

for layer in annotation.layers:
    print(f"Layer: {layer.name}")
    for seg in layer.segments:
        print(f"  {seg.start}{seg.duration} (samples) – {seg.label}")

Writing an ANTX file (using samples)

Segment start and duration are stored in samples. You can set them directly when you work in sample counts:

from annotationpro_format import Annotation, Layer, Segment, serialize_annotation

annotation = Annotation(samplerate=44100)
layer = Layer("Transcription")
# start=0, duration=66150 means 0 to 1.5 seconds at 44100 Hz
layer.segments.append(Segment("hello", start=0.0, duration=66150.0))
annotation.layers.append(layer)

xml_str = serialize_annotation(annotation)
with open("output.antx", "w", encoding="utf-8") as f:
    f.write(xml_str)

Working with time in seconds (helpers)

To avoid manual sample math, use the seconds helpers. They use the annotation’s samplerate to convert between seconds and samples.

Writing segments with start/duration in seconds:

from annotationpro_format import (
    Annotation,
    Layer,
    Segment,
    serialize_annotation,
    set_segment_start_seconds,
    set_segment_duration_seconds,
)

annotation = Annotation(samplerate=44100)
layer = Layer("Transcription")

# Create segment (start/duration in samples will be set by helpers)
seg = Segment("hello", start=0.0, duration=0.0)
set_segment_start_seconds(annotation, seg, 0.0)   # 0 seconds
set_segment_duration_seconds(annotation, seg, 1.5)  # 1.5 seconds
layer.segments.append(seg)

# Another segment: from 2.5 s to 4.0 s (duration 1.5 s)
seg2 = Segment("world", start=0.0, duration=0.0)
set_segment_start_seconds(annotation, seg2, 2.5)
set_segment_duration_seconds(annotation, seg2, 1.5)
layer.segments.append(seg2)

annotation.layers.append(layer)
with open("output.antx", "w", encoding="utf-8") as f:
    f.write(serialize_annotation(annotation))

Reading segment times in seconds:

from annotationpro_format import (
    deserialize_annotation,
    get_segment_start_seconds,
    get_segment_duration_seconds,
)

with open("project.antx", "r", encoding="utf-8") as f:
    annotation = deserialize_annotation(f.read())

for layer in annotation.layers:
    for seg in layer.segments:
        start_sec = get_segment_start_seconds(annotation, seg)
        duration_sec = get_segment_duration_seconds(annotation, seg)
        print(f"{start_sec:.2f}s – {start_sec + duration_sec:.2f}s: {seg.label}")

Low-level conversion (seconds ↔ samples):

from annotationpro_format import seconds_to_samples, samples_to_seconds

samplerate = 44100
samples = seconds_to_samples(1.5, samplerate)  # 66150.0
seconds = samples_to_seconds(66150, samplerate)  # 1.5

Model overview

  • Annotation – Root object: configuration (dict, includes Samplerate), layers (list).
  • Layer – One annotation layer: name, id, segments (list-like SegmentCollection), plus display options (colors, height, etc.).
  • Segment – One segment: label, start, duration (in samples), and optional fields (feature, language, group, etc.).
  • SegmentCollection – List of segments for a layer; setting id_layer on the collection is handled when you append segments.
  • AudioFile – Model for audio file references (not used in the current serialization).

Publishing to PyPI (for maintainers)

Publishing the library to PyPI is fully automated via GitHub Actions.

  • A release is published when a tag matching vX.Y.Z is pushed to GitHub, e.g.:

    git tag v0.1.1
    git push origin v0.1.1
    
  • Before creating the tag, bump the version in pyproject.toml:

    [project]
    version = "0.1.1"
    
  • The tag name (e.g. v0.1.1) and the version in pyproject.toml (e.g. 0.1.1) must match.

When the tag is pushed:

  1. The workflow in .github/workflows/publish-pypi.yml runs.
  2. It checks out the code at that tag.
  3. It builds the package with python -m build (sdist + wheel).
  4. It uploads the artifacts in dist/ to PyPI using twine upload dist/* and the PYPI_API_TOKEN secret configured in the repository.

If the workflow succeeds, the new version is immediately available on PyPI as annotationpro-format.

License

MIT – see LICENSE.

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

annotationpro_format-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

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

annotationpro_format-0.1.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file annotationpro_format-0.1.0.tar.gz.

File metadata

  • Download URL: annotationpro_format-0.1.0.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for annotationpro_format-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4decade8c6dd2ec9fa5074553d2a3d6320ce8caade4ddbbf9e14c5a5893c20d6
MD5 9edc42ad3419d84f600e6e8f0e0b496f
BLAKE2b-256 223938ca070b7d8e584d99a6895f0635342abe43442827e0f0b5ff584de5147d

See more details on using hashes here.

File details

Details for the file annotationpro_format-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for annotationpro_format-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d24a211e9e5668ecc85cf8aaa4ab642a8ab6324e9bd6c1ce4a1642bb5c7e1b08
MD5 d603aaf65342251687382ccffd64f8fc
BLAKE2b-256 f6dd6cb74dc955bc17eca83e59a432c71b717a83fa78594cb39b215a20583ae4

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