Cython bindings for libquicr - Python library for Media over QUIC (MoQ) protocol.
- Python 3.9+
- C++20 compatible compiler (GCC 10+, Clang 12+, or MSVC 2019+)
- CMake 3.20+
- Cython 3.0+
# Clone the repository with submodules
git clone --recursive https://github.com/cisco/quicr-py.git
cd quicr-py
# Run the build script (creates venv, installs deps, builds package)
./build.sh
# Activate the virtual environment
source venv/bin/activate # Linux/macOS
# source venv/Scripts/activate # WindowsIf you prefer manual setup:
# Clone the repository with submodules
git clone --recursive https://github.com/cisco/quicr-py.git
cd quicr-py
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # Linux/macOS
# source venv/Scripts/activate # Windows
# Install build dependencies
pip install cython cmake scikit-build-core
# Build and install
pip install -e .pip install quicr-cythonimport asyncio
from quicr_cython import AsyncClient, ClientConfig, TrackName
async def main():
# Configure the client
config = ClientConfig(
connect_uri="moqt://relay.example.com:443",
endpoint_id="my-client"
)
# Connect to the relay
async with AsyncClient(config) as client:
track = TrackName(["example", "chat"], "messages")
# Subscribe to messages
async with client.subscriber(track) as sub:
async for obj in sub:
print(f"Received: {obj.data.decode()}")
if obj.data == b"quit":
break
asyncio.run(main())import asyncio
from quicr_cython import AsyncClient, ClientConfig, TrackName, TrackMode
async def publish_messages():
config = ClientConfig(connect_uri="moqt://relay.example.com:443")
async with AsyncClient(config) as client:
track = TrackName(["example", "chat"], "messages")
async with client.publisher(track, track_mode=TrackMode.STREAM) as pub:
# Publish with auto-sequencing
await pub.publish(b"Hello, world!")
await pub.publish(b"Another message")
# Start a new group
await pub.new_group()
await pub.publish(b"First message in new group")
asyncio.run(publish_messages())import asyncio
from quicr_cython import AsyncClient, ClientConfig, TrackName
async def fetch_history():
config = ClientConfig(connect_uri="moqt://relay.example.com:443")
async with AsyncClient(config) as client:
track = TrackName(["example", "chat"], "messages")
# Fetch groups 0-10
async with client.fetcher(track, start_group=0, end_group=10) as fetch:
async for obj in fetch:
print(f"Historical message: {obj.data.decode()}")
asyncio.run(fetch_history())For simpler use cases or integration with non-async code:
from quicr_cython import (
Client, ClientConfig, TrackName, TrackMode,
ObjectHeaders, PublishObjectStatus
)
# Create and connect client
config = ClientConfig(connect_uri="moqt://relay.example.com:443")
client = Client(config)
client.connect()
# Create a publish track
track_name = TrackName(["example", "video"], "stream1")
publisher = client.create_publish_track(
track_name,
track_mode=TrackMode.STREAM,
default_priority=1,
default_ttl=5000
)
# Activate publishing
client.publish_track(publisher)
# Publish objects
headers = ObjectHeaders(group_id=0, object_id=0, payload_length=100)
data = b"video frame data..."
status = publisher.publish_object(headers, data)
if status == PublishObjectStatus.OK:
print("Published successfully")
# Cleanup
client.unpublish_track(publisher)
client.disconnect()See the examples/ directory for complete working examples:
simple_publisher.py- Basic publishing examplesimple_subscriber.py- Basic subscription example
# Make sure virtual environment is activated
source venv/bin/activate # Linux/macOS
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# Run with coverage
pytest tests/ --cov=quicr_cython --cov-report=html# Make sure virtual environment is activated
source venv/bin/activate # Linux/macOS
pip install -e ".[docs]"
cd docs
make htmlContributions are welcome! Please see CONTRIBUTING.md for guidelines.
BSD-2-Clause - See LICENSE file for details.