Class: HLS::Manifest
- Inherits:
-
Object
- Object
- HLS::Manifest
- Defined in:
- lib/hls/manifest.rb
Overview
Reads an HLS bundle out of an S3-compatible bucket and returns signed-URL playlists ready to hand to a video player.
The Manifest is the read-side counterpart to ApplicationVideo. A profile class hands one to its caller via ‘profile.manifest(path)`, but Manifest can also be used directly with any bucket.
Example:
manifest = CourseVideo.manifest("phlex/forms/overview")
manifest.master_playlist # => M3u8::Playlist with rewritten URIs
manifest.poster_url # => pre-signed URL string
‘master_playlist` rewrites variant URIs from ffmpeg’s flat ‘0/index.m3u8` form to a controller-routable `<path>/0.m3u8` shape so the host app’s controller can serve each variant by name.
Defined Under Namespace
Classes: Variant
Constant Summary collapse
- DEFAULT_POSTER =
"poster"- MASTER_PLAYLIST =
"index.m3u8"- VARIANT_PLAYLIST =
"index.m3u8"- DEFAULT_VARIANT_URI =
->(path:, variant_index:) { "#{::File.basename(path)}/#{variant_index}.m3u8" }
Instance Attribute Summary collapse
-
#cache ⇒ Object
readonly
Returns the value of attribute cache.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#segment_duration ⇒ Object
readonly
Returns the value of attribute segment_duration.
-
#storage ⇒ Object
readonly
Returns the value of attribute storage.
Instance Method Summary collapse
-
#expires_in ⇒ Object
Default presigned-URL TTL for this manifest.
-
#initialize(storage:, path:, segment_duration: 4, variant_uri: nil, cache: nil) ⇒ Manifest
constructor
- storage
-
An HLS::Storage adapter (S3, Memory, …).
-
#master_playlist ⇒ Object
Master playlist with variant URIs rewritten from ffmpeg’s ‘<index>/index.m3u8` form to whatever the configured `variant_uri` callable returns.
-
#poster_url(name = DEFAULT_POSTER) ⇒ Object
Pre-signed URL for a poster image.
-
#presigned_url(*parts, expires_in: self.expires_in) ⇒ Object
Pre-signs an arbitrary key under this manifest’s path.
-
#variant(variant_path) ⇒ Object
Look up a variant by ffmpeg’s path identifier (“0”, “1”, …).
-
#variants ⇒ Object
All variants discovered in the master playlist, indexed by ffmpeg’s variant path (‘“0”`, `“1”`, …).
Constructor Details
#initialize(storage:, path:, segment_duration: 4, variant_uri: nil, cache: nil) ⇒ Manifest
- storage
-
An HLS::Storage adapter (S3, Memory, …). Owns the bucket and the default signing TTL.
- path
-
key prefix where the bundle lives
segment_duration: HLS segment length, drives Variant#duration math
- variant_uri
-
callable taking (path:, variant_index:) and returning the URI string to put in the master playlist for that variant. Default produces ‘<basename(path)>/<index>.m3u8`, which matches a `/videos/*path/:id/:variant` Rails route shape.
- cache
-
an HLS::Cache (or any object responding to ‘fetch(key, &block)`). When set, raw playlists are read through it instead of being fetched on every request. nil disables caching.
42 43 44 45 46 47 48 49 50 |
# File 'lib/hls/manifest.rb', line 42 def initialize(storage:, path:, segment_duration: 4, variant_uri: nil, cache: nil) @storage = storage @path = path @segment_duration = Integer(segment_duration) @variant_uri = variant_uri || DEFAULT_VARIANT_URI @cache = cache end |
Instance Attribute Details
#cache ⇒ Object (readonly)
Returns the value of attribute cache.
27 28 29 |
# File 'lib/hls/manifest.rb', line 27 def cache @cache end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
27 28 29 |
# File 'lib/hls/manifest.rb', line 27 def path @path end |
#segment_duration ⇒ Object (readonly)
Returns the value of attribute segment_duration.
27 28 29 |
# File 'lib/hls/manifest.rb', line 27 def segment_duration @segment_duration end |
#storage ⇒ Object (readonly)
Returns the value of attribute storage.
27 28 29 |
# File 'lib/hls/manifest.rb', line 27 def storage @storage end |
Instance Method Details
#expires_in ⇒ Object
Default presigned-URL TTL for this manifest. Reads from the storage adapter so signing config lives in one place.
54 55 56 |
# File 'lib/hls/manifest.rb', line 54 def expires_in storage.signing_ttl end |
#master_playlist ⇒ Object
Master playlist with variant URIs rewritten from ffmpeg’s ‘<index>/index.m3u8` form to whatever the configured `variant_uri` callable returns. The default produces `<id>/<index>.m3u8` where `<id>` is the last segment of the manifest’s path — relative to the master playlist’s URL, so a player fetching ‘/videos/<path>/<id>.m3u8` resolves the variant URI to `/videos/<path>/<id>/<index>.m3u8`.
Returns a fresh M3u8::Playlist on each call (does not mutate the cached raw playlist).
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/hls/manifest.rb', line 79 def master_playlist list = M3u8::Playlist.new list.items = raw_master_playlist.items.map do |item| rewritten = item.clone rewritten.uri = @variant_uri.call( path: path, variant_index: ::File.dirname(item.uri) ) rewritten end list end |
#poster_url(name = DEFAULT_POSTER) ⇒ Object
Pre-signed URL for a poster image. With no argument, returns ‘<path>/poster.jpg` (back-compat with the legacy `HLS::Poster` filename). With a name, returns `<path>/<name>.jpg`.
65 66 67 |
# File 'lib/hls/manifest.rb', line 65 def poster_url(name = DEFAULT_POSTER) presigned_url("#{name}.jpg") end |
#presigned_url(*parts, expires_in: self.expires_in) ⇒ Object
Pre-signs an arbitrary key under this manifest’s path.
108 109 110 |
# File 'lib/hls/manifest.rb', line 108 def presigned_url(*parts, expires_in: self.expires_in) object(*parts).presigned_url(:get, expires_in: Integer(expires_in)) end |
#variant(variant_path) ⇒ Object
Look up a variant by ffmpeg’s path identifier (“0”, “1”, …).
103 104 105 |
# File 'lib/hls/manifest.rb', line 103 def variant(variant_path) variants.find { |v| v.variant_path == variant_path } end |
#variants ⇒ Object
All variants discovered in the master playlist, indexed by ffmpeg’s variant path (‘“0”`, `“1”`, …).
94 95 96 97 98 99 100 |
# File 'lib/hls/manifest.rb', line 94 def variants @variants ||= raw_master_playlist.items.map do |item| variant_path = ::File.dirname(item.uri) variant_playlist = read_playlist(variant_path, VARIANT_PLAYLIST) Variant.new(manifest: self, variant_path: variant_path, items: variant_playlist.items) end end |