Skip to main content

media-sdk-m8

Shared, settings-agnostic media primitives for the m8 media stack. Consumed by:

  • media-service-m8 — the live API (job producer)
  • media-worker-m8 — the async ARQ worker (job consumer)

The SDK is framework-agnostic (no FastAPI, no auth-sdk, no pydantic-settings) and imgtools-free. It owns no business logic, no database, and no preset knowledge — callers pass an explicit config object; the SDK never reads settings or env.

Contents

Object storage — media_sdk_m8.storage

ObjectStorage is a thin, provider-neutral wrapper over the Amazon S3 API (SigV4), built on boto3/botocore — the reference client every S3-compatible server is tested against. It never depends on a particular implementation: the validated backends are SeaweedFS 4.x (default reference implementation), Garage 2.x (validated fallback), and any other S3-compatible provider, including MinIO. It is constructed from an explicit ObjectStorageConfig (also exported as S3StorageConfig; endpoint, credentials, region, TLS, and the default presigned-URL lifetime), so it has no dependency on any service's settings module.

from media_sdk_m8 import ObjectStorage, ObjectStorageConfig

config = ObjectStorageConfig(
    endpoint="storage:9000",
    access_key="...",
    secret_key="...",
    secure=False,
    region="us-east-1",
    presigned_expire_seconds=300,
)
storage = ObjectStorage(config)

data = storage.get_object(bucket="private-media", object_key="key")
storage.put_object(
    bucket="public-media",
    object_key="key/variants/thumb_webp/thumb.webp",
    data=variant_bytes,
    content_type="image/webp",
)

Methods: stat_object, remove_object, get_object_head, get_object, stream_object, list_object_keys, put_object, put_object_stream, set_object_content_type, copy_object, post_upload_url, presigned_post_object, presigned_get_object.

list_object_keys(*, bucket, prefix="") recursively yields stored keys — the read primitive an orphan reconciler uses to find bytes that have no DB row.

stream_object and put_object_stream are the unbuffered pair. The first yields an object's bytes in chunks; the second writes length bytes from an open file-like object, for a payload the caller has already assembled on disk (an archive export, say) that put_object's bytes argument would force resident in memory.

Presigned-URL expiry defaults to config.presigned_expire_seconds and can be overridden per call via expires_seconds.

Browser-direct presigned URLs (public endpoint)

When the browser cannot resolve the internal storage host (e.g. storage:9000 in a container stack), set the two optional endpoint fields:

config = ObjectStorageConfig(
    endpoint="storage:9000",  # internal — service and worker only
    access_key="...",
    secret_key="...",
    secure=False,
    region="us-east-1",
    public_endpoint="127.0.0.1:9005",  # host:port, no scheme — browser-reachable
    public_secure=False,  # scheme for public URLs; falls back to `secure` when None
)
  • public_endpoint — the host the browser hits, in host:port form (no scheme). post_upload_url returns a URL built from this host/scheme; presigned_get_object is signed by a client bound to this endpoint (SigV4 GET signatures bind the Host, so the signing client must match the endpoint the browser sends the request to).
  • public_secure — TLS flag for the public endpoint. Falls back to secure when omitted.

All internal ops (stat_object, get_object, copy_object, etc.) always use endpoint, not public_endpoint. When public_endpoint is None (default), post_upload_url and presigned_get_object behave identically to before — compatible with proxy-through deployments and media-worker-m8.

Reverse-proxy requirement: a proxy (e.g. Traefik) forwarding requests to the storage backend must preserve the Host header (passHostHeader: true in Traefik, which is its default) so the SigV4 signature validates on arrival.

Job contracts — media_sdk_m8.contracts

Self-contained Pydantic v2 models that form the producer↔consumer contract. The service builds and enqueues them; the worker deserializes and acts on them.

  • ScanJobPayload{ object_id, bucket, object_key, owner_user_id }
  • VariantSpec{ variant_name, output_options, target_bucket, target_key }; output_options is the imgtools-shaped dict (one format + name) built by the service, so the worker needs no preset or key knowledge.
  • VariantJobPayload{ job_id, media_object_id, source_bucket, source_object_key, specs }
  • ExportArchiveEntry — one validated, traversal-safe source-object → ZIP-entry mapping; ExportArchiveJobPayload carries the authorized manifest, entries, target, chunk size and presign lifetime for delegated archive assembly.
  • OutboxEventPayload{ event_id, event_type, object_id, payload, created_at }; the outbound webhook contract. media-service-m8 writes one per state change to its transactional outbox and POSTs this HMAC-signed body to subscriber URLs, so a subscriber needs only this shape to verify and consume an event.

Development

pip install -e ".[dev]"
ruff format . && ruff check .
mypy media_sdk_m8 --ignore-missing-imports
bandit -r media_sdk_m8 --severity-level medium
pytest --cov=media_sdk_m8 --cov-report=term-missing --cov-fail-under=100

Published to PyPI on tagged release.

Download files

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

Source Distribution

media_sdk_m8-1.0.0.tar.gz (105.9 kB view details)

Uploaded Source

Built Distribution

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

media_sdk_m8-1.0.0-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

File details

Details for the file media_sdk_m8-1.0.0.tar.gz.

File metadata

  • Download URL: media_sdk_m8-1.0.0.tar.gz
  • Upload date:
  • Size: 105.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for media_sdk_m8-1.0.0.tar.gz
Algorithm Hash digest
SHA256 8f5cf98bfda102670087aeb96e9932ff38a7dc763c00572f920f3210f793de81
MD5 a628f38db2a6ed3e72a2b78fd29f1278
BLAKE2b-256 3121cad78d58c82b207ebbc2fad6b49d9dc027e9ed6c727040e11e4c4fadc97e

See more details on using hashes here.

Provenance

The following attestation bundles were made for media_sdk_m8-1.0.0.tar.gz:

Publisher: PiPy.yml on mano8/media-sdk-m8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file media_sdk_m8-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: media_sdk_m8-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 23.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for media_sdk_m8-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed34182d36773e6ad9790ed7d2c9719414c0660dd6d109fae4c7c11838d7824b
MD5 27e13d93b918c40ff77e143ff547a9f1
BLAKE2b-256 1dfc6bf4bf99df2901395328c43d9157df6eaa39f9ca1f760c4698824c4262a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for media_sdk_m8-1.0.0-py3-none-any.whl:

Publisher: PiPy.yml on mano8/media-sdk-m8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

0.7.0

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page