Serving video and images¶
ZERO-Z3 serves objects directly to browsers and players. Egress is billed per GB in volume tiers with no ratio to the stored volume, throughput is best effort on our own backbone. This page is the setup for delivery workloads: video platforms, image serving, downloads.
1. Access model¶
| Content | Setting |
|---|---|
| Public assets (thumbnails, images, public video) | bucket policy preset public-read, see Geofencing and policies |
| Paid or private video | keep the bucket private and hand out presigned URLs with a short expiry from your application |
| Mixed | one bucket per account: use two accounts, one public and one private |
2. Custom domain and TLS¶
Enable static hosting, enter the domain (media.example.com, subdomain only), create the
CNAME to <bucket>.<endpoint host> and request the Let's Encrypt certificate. Details:
Custom domain and TLS. Static hosting only adds the index-document
rewrite for paths ending in /; object URLs are unchanged, so
https://media.example.com/videos/intro/index.m3u8 serves the object videos/intro/index.m3u8.
3. Cache-Control¶
Set caching in two places:
- Per object at upload time, for example
aws s3 cp --cache-control "public, max-age=31536000, immutable"for versioned filenames. - As a default on the custom domain:
max_ageup to 31536000 seconds,mode: fallbackadds the header only when the object has none,mode: overwritereplaces it. Directives frompublic,private,no-cache,no-store,no-transform,must-revalidate,proxy-revalidate,immutable. See Static hosting, CORS and cache-control.
Use short max_age for playlists that change (live.m3u8) and long, immutable values for
segments and images with a content hash in the name.
4. CORS for players and canvases¶
Video players and image editors that run in the browser fetch across origins. Add a CORS rule on the bucket (CORS):
| Field | Value for media |
|---|---|
allowed_origins |
your site origins, for example https://app.example.com |
allowed_methods |
GET, HEAD |
allowed_headers |
Range, If-Match, If-None-Match, If-Modified-Since, Origin, Accept |
expose_headers |
Content-Range, ETag, Content-Disposition |
max_age_seconds |
86400 |
The rules apply to the S3 endpoint and the custom domain alike.
5. Range requests and HLS¶
Players seek with HTTP Range requests; RGW answers them with 206 Partial Content and
Content-Range, on the S3 endpoint and on the custom domain. Nothing to configure.
HLS is plain objects: upload the playlist and the segments with the right Content-Type
(application/vnd.apple.mpegurl for .m3u8, video/mp2t for .ts, video/mp4 or
video/iso.segment for fMP4) and point the player at the playlist URL on the custom domain.
Set Content-Type at upload; RGW stores what the client sends.
aws --profile zero-z3 --endpoint-url https://fra.s3.zeroservices.eu s3 cp ./hls/ s3://my-bucket/videos/intro/ \
--recursive --exclude "*" --include "*.m3u8" \
--content-type application/vnd.apple.mpegurl --cache-control "public, max-age=60"
aws --profile zero-z3 --endpoint-url https://fra.s3.zeroservices.eu s3 cp ./hls/ s3://my-bucket/videos/intro/ \
--recursive --exclude "*" --include "*.ts" \
--content-type video/mp2t --cache-control "public, max-age=31536000, immutable"
6. Images¶
Serve originals or pre-rendered sizes from the bucket with long Cache-Control. On-the-fly
resizing (imgproxy, Thumbor and similar) works against ZERO-Z3 like against any S3
endpoint: configure the endpoint URL, the region name and path-style addressing as their
documentation describes, and give them a key pair of the account.
7. Geofencing and licensing¶
Country restrictions for licensed content are set per account in
Geofencing: allow or deny with ISO country codes. Blocked
requests get 403, on the custom domain as well as on the S3 endpoint.
8. ZERO-PROTECT in front¶
For a domain that is attacked or needs an edge cache for images, put
ZERO-PROTECT in front: custom domain TLS mode upstream, origin lock
zero-protect, and the PROTECT service pointing at the custom domain as origin. The edge
cache holds objects up to 5 MB for up to 3600 seconds (Cache and headers),
so images and thumbnails are served from the edge while video segments stream through it.
Geofence such domains at the edge, not on the bucket.
9. What to watch¶
- Bill: the billing model averages daily storage peaks and meters egress per GB.
- Object size: objects below 64 KB are billed as 64 KB; bundle tiny assets (sprites, icons).
- Request-rate limits exist per user and bucket (Limits); sustained
503 SlowDownmeans a ticket, not a retry loop.