Skip to content

Video streaming

Nexo plays the MP4 videos of a bucket as HLS streams, packaged on the fly: there is no transcoding and nothing to prepare. A video uploaded with nexoctl cp, the console or any S3 client plays at once in the console, and a stream link shares it with people who have no account, in a browser or in any HLS player.

Supported videos

Container MP4 and its variants (.mp4, .m4v, .mov), with the index (moov) at the start or at the end
Video H.264 (AVC) or H.265 (HEVC)
Audio AAC, optional

Fragmented MP4 files, objects encrypted with SSE-C and other codecs are refused with 400: share them as files. Objects encrypted with SSE-S3 or SSE-KMS stream like the others.

The segments are cut at the keyframes of the video, about every 6 seconds: a video encoded with a keyframe every 1-2 seconds (the default of most encoders and cameras) seeks precisely.

In the console

The preview of an MP4 video in the object browser is an HLS stream: playback starts at once and seeking does not download the file. Browsers without HLS support fall back to the file.

A stream link is a managed share link: it belongs to its owner, expires (at most 7 days) and is revoked like any share. It gives two URLs:

  • the player page of the server, for people: https://s3.example.com/nexo/media/player/#/nexo/media/v1/…;
  • the HLS playlist, for players (VLC, Safari, mobile apps) and for pages that embed the video with hls.js: https://s3.example.com/nexo/media/v1/<bucket>/master.m3u8?….

In the console, Share on a video offers Stream as a video (on by default for MP4 files). With the CLI:

$ nexoctl share download --stream --expire 7d local/videos/talk.mp4
URL: local/videos/talk.mp4
Expire: 7d
Share: https://s3.example.com/nexo/media/v1/videos/master.m3u8?key=talk.mp4&X-Amz-Algorithm=…
Player: https://s3.example.com/nexo/media/player/#/nexo/media/v1/videos/master.m3u8?key=talk.mp4&X-Amz-Algorithm=…
ID: 2xk4m7q9fz3a (revoke with: nexoctl share revoke local 2xk4m7q9fz3a)

Revoking the share stops the playback: the playlists and the segments are signed by the share, until it expires. A link pins the version of the video it was created for: when the object is overwritten, an open player stops (412) and a new link plays the new version.

The player page and the playlists are served by the S3 listener, so a stream link works when only the S3 API is exposed to the Internet. The page holds no data: the playlist travels in the fragment of its URL (after #), which browsers never send to a server.

HLS API

The streams follow the authorization of GetObject: whoever may read an object may stream it.

Path (S3 listener) Content
/nexo/media/v1/{bucket}/master.m3u8?key=…[&versionId=…] master playlist
/nexo/media/v1/{bucket}/media.m3u8?key=…&rev=… media playlist (VOD)
/nexo/media/v1/{bucket}/init.mp4?key=…&rev=… fMP4 initialization segment
/nexo/media/v1/{bucket}/segment.m4s?key=…&rev=…&n=… fMP4 media segment n
/nexo/media/player/ public player page

A request may be anonymous (a bucket readable by everyone), signed in its headers or presigned. The URIs of a presigned master playlist are presigned in turn with the same credentials, until the same expiry: any presigned master playlist (nexoctl share download --raw of the master path, an SDK) plays in a player without credentials. rev is the ETag of the object: the URIs answer 412 once it changes.

The console serves the same presentation to its users under /api/v1/buckets/{bucket}/objects/hls/ with their session (Admin API).

The video streams count against the rate limits of the S3 API, unlike the other /nexo/ paths (health probes, metrics).