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, includesSamplerate),layers(list). - Layer – One annotation layer:
name,id,segments(list-likeSegmentCollection), 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_layeron 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.Zis 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 inpyproject.toml(e.g.0.1.1) must match.
When the tag is pushed:
- The workflow in
.github/workflows/publish-pypi.ymlruns. - It checks out the code at that tag.
- It builds the package with
python -m build(sdist + wheel). - It uploads the artifacts in
dist/to PyPI usingtwine upload dist/*and thePYPI_API_TOKENsecret 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4decade8c6dd2ec9fa5074553d2a3d6320ce8caade4ddbbf9e14c5a5893c20d6
|
|
| MD5 |
9edc42ad3419d84f600e6e8f0e0b496f
|
|
| BLAKE2b-256 |
223938ca070b7d8e584d99a6895f0635342abe43442827e0f0b5ff584de5147d
|
File details
Details for the file annotationpro_format-0.1.0-py3-none-any.whl.
File metadata
- Download URL: annotationpro_format-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d24a211e9e5668ecc85cf8aaa4ab642a8ab6324e9bd6c1ce4a1642bb5c7e1b08
|
|
| MD5 |
d603aaf65342251687382ccffd64f8fc
|
|
| BLAKE2b-256 |
f6dd6cb74dc955bc17eca83e59a432c71b717a83fa78594cb39b215a20583ae4
|