m3u8 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +89 -0
  4. data/lib/m3u8/attribute_formatter.rb +17 -0
  5. data/lib/m3u8/bitrate_item.rb +2 -0
  6. data/lib/m3u8/byte_range.rb +2 -0
  7. data/lib/m3u8/cli/diff_command.rb +61 -0
  8. data/lib/m3u8/cli/inspect_command.rb +9 -1
  9. data/lib/m3u8/cli/validate_command.rb +16 -0
  10. data/lib/m3u8/cli.rb +45 -11
  11. data/lib/m3u8/content_steering_item.rb +1 -0
  12. data/lib/m3u8/date_range_item.rb +6 -5
  13. data/lib/m3u8/define_item.rb +1 -0
  14. data/lib/m3u8/discontinuity_item.rb +2 -0
  15. data/lib/m3u8/encryptable.rb +10 -0
  16. data/lib/m3u8/gap_item.rb +2 -0
  17. data/lib/m3u8/key_item.rb +1 -8
  18. data/lib/m3u8/map_item.rb +1 -0
  19. data/lib/m3u8/media_item.rb +1 -0
  20. data/lib/m3u8/part_inf_item.rb +1 -0
  21. data/lib/m3u8/part_item.rb +2 -1
  22. data/lib/m3u8/playback_start.rb +1 -0
  23. data/lib/m3u8/playlist.rb +236 -2
  24. data/lib/m3u8/playlist_item.rb +1 -0
  25. data/lib/m3u8/preload_hint_item.rb +1 -0
  26. data/lib/m3u8/reader.rb +15 -2
  27. data/lib/m3u8/rendition_report_item.rb +1 -0
  28. data/lib/m3u8/segment_item.rb +3 -1
  29. data/lib/m3u8/serializable.rb +43 -0
  30. data/lib/m3u8/server_control_item.rb +1 -0
  31. data/lib/m3u8/session_data_item.rb +1 -0
  32. data/lib/m3u8/session_key_item.rb +1 -8
  33. data/lib/m3u8/skip_item.rb +1 -0
  34. data/lib/m3u8/time_item.rb +1 -0
  35. data/lib/m3u8/variable_resolver.rb +83 -0
  36. data/lib/m3u8/version.rb +1 -1
  37. data/lib/m3u8.rb +2 -0
  38. data/m3u8.gemspec +1 -0
  39. data/spec/lib/m3u8/cli/diff_command_spec.rb +49 -0
  40. data/spec/lib/m3u8/cli/inspect_command_spec.rb +12 -0
  41. data/spec/lib/m3u8/cli/validate_command_spec.rb +17 -1
  42. data/spec/lib/m3u8/cli_spec.rb +47 -1
  43. data/spec/lib/m3u8/conformance_spec.rb +123 -0
  44. data/spec/lib/m3u8/date_range_item_spec.rb +20 -0
  45. data/spec/lib/m3u8/part_item_spec.rb +7 -0
  46. data/spec/lib/m3u8/reader_spec.rb +35 -0
  47. data/spec/lib/m3u8/round_trip_spec.rb +110 -0
  48. data/spec/lib/m3u8/segment_item_spec.rb +11 -0
  49. data/spec/lib/m3u8/serializable_spec.rb +133 -0
  50. data/spec/lib/m3u8/time_item_spec.rb +13 -0
  51. data/spec/lib/m3u8/variable_resolver_spec.rb +104 -0
  52. metadata +24 -3
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe M3u8::VariableResolver do
6
+ def resolve(content, **opts)
7
+ M3u8::Playlist.read(content).resolve_variables(**opts)
8
+ end
9
+
10
+ it 'substitutes NAME/VALUE references in URIs and quoted attributes' do
11
+ content = <<~M3U8
12
+ #EXTM3U
13
+ #EXT-X-DEFINE:NAME="host",VALUE="https://cdn.example.com"
14
+ #EXT-X-DEFINE:NAME="grp",VALUE="audio-aac"
15
+ #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="{$grp}",NAME="EN",URI="{$host}/a.m3u8"
16
+ #EXT-X-STREAM-INF:BANDWIDTH=1000,AUDIO="{$grp}"
17
+ {$host}/video.m3u8
18
+ M3U8
19
+ resolved = resolve(content)
20
+ expect(resolved.playlists.first.uri)
21
+ .to eq('https://cdn.example.com/video.m3u8')
22
+ expect(resolved.playlists.first.audio).to eq('audio-aac')
23
+ media = resolved.media_items.first
24
+ expect(media.group_id).to eq('audio-aac')
25
+ expect(media.uri).to eq('https://cdn.example.com/a.m3u8')
26
+ end
27
+
28
+ it 'leaves references untouched when not resolved' do
29
+ content = <<~M3U8
30
+ #EXTM3U
31
+ #EXT-X-DEFINE:NAME="host",VALUE="https://cdn.example.com"
32
+ #EXT-X-TARGETDURATION:10
33
+ #EXTINF:5.0,
34
+ {$host}/seg.ts
35
+ #EXT-X-ENDLIST
36
+ M3U8
37
+ playlist = M3u8::Playlist.read(content)
38
+ expect(playlist.segments.first.segment).to eq('{$host}/seg.ts')
39
+ end
40
+
41
+ it 'resolves IMPORT values from the imported hash' do
42
+ content = <<~M3U8
43
+ #EXTM3U
44
+ #EXT-X-DEFINE:IMPORT="host"
45
+ #EXT-X-TARGETDURATION:10
46
+ #EXTINF:5.0,
47
+ {$host}/seg.ts
48
+ #EXT-X-ENDLIST
49
+ M3U8
50
+ resolved = resolve(content, imported: { 'host' => 'https://x' })
51
+ expect(resolved.segments.first.segment).to eq('https://x/seg.ts')
52
+ end
53
+
54
+ it 'raises when an IMPORT value is missing' do
55
+ content = <<~M3U8
56
+ #EXTM3U
57
+ #EXT-X-DEFINE:IMPORT="host"
58
+ #EXT-X-TARGETDURATION:10
59
+ #EXTINF:5.0,
60
+ {$host}/seg.ts
61
+ #EXT-X-ENDLIST
62
+ M3U8
63
+ expect { resolve(content) }
64
+ .to raise_error(M3u8::InvalidPlaylistError, /IMPORT variable not found/)
65
+ end
66
+
67
+ it 'resolves QUERYPARAM values from the query hash' do
68
+ content = <<~M3U8
69
+ #EXTM3U
70
+ #EXT-X-DEFINE:QUERYPARAM="tok"
71
+ #EXT-X-TARGETDURATION:10
72
+ #EXTINF:5.0,
73
+ seg.ts?t={$tok}
74
+ #EXT-X-ENDLIST
75
+ M3U8
76
+ resolved = resolve(content, query: { 'tok' => 'abc' })
77
+ expect(resolved.segments.first.segment).to eq('seg.ts?t=abc')
78
+ end
79
+
80
+ it 'raises on an undefined variable reference' do
81
+ content = <<~M3U8
82
+ #EXTM3U
83
+ #EXT-X-TARGETDURATION:10
84
+ #EXTINF:5.0,
85
+ {$nope}/seg.ts
86
+ #EXT-X-ENDLIST
87
+ M3U8
88
+ expect { resolve(content) }
89
+ .to raise_error(M3u8::InvalidPlaylistError, /Undefined variable: nope/)
90
+ end
91
+
92
+ it 'raises when a reference precedes its definition' do
93
+ content = <<~M3U8
94
+ #EXTM3U
95
+ #EXT-X-TARGETDURATION:10
96
+ #EXTINF:5.0,
97
+ {$host}/seg.ts
98
+ #EXT-X-DEFINE:NAME="host",VALUE="https://x"
99
+ #EXT-X-ENDLIST
100
+ M3U8
101
+ expect { resolve(content) }
102
+ .to raise_error(M3u8::InvalidPlaylistError, /Undefined variable: host/)
103
+ end
104
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: m3u8
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seth Deckard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-07 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2026-05-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: Generate and parse m3u8 playlists for HTTP Live Streaming (HLS).
14
28
  email:
15
29
  - seth@deckard.me
@@ -34,6 +48,7 @@ files:
34
48
  - lib/m3u8/builder.rb
35
49
  - lib/m3u8/byte_range.rb
36
50
  - lib/m3u8/cli.rb
51
+ - lib/m3u8/cli/diff_command.rb
37
52
  - lib/m3u8/cli/inspect_command.rb
38
53
  - lib/m3u8/cli/validate_command.rb
39
54
  - lib/m3u8/codecs.rb
@@ -62,11 +77,13 @@ files:
62
77
  - lib/m3u8/scte35_splice_null.rb
63
78
  - lib/m3u8/scte35_time_signal.rb
64
79
  - lib/m3u8/segment_item.rb
80
+ - lib/m3u8/serializable.rb
65
81
  - lib/m3u8/server_control_item.rb
66
82
  - lib/m3u8/session_data_item.rb
67
83
  - lib/m3u8/session_key_item.rb
68
84
  - lib/m3u8/skip_item.rb
69
85
  - lib/m3u8/time_item.rb
86
+ - lib/m3u8/variable_resolver.rb
70
87
  - lib/m3u8/version.rb
71
88
  - lib/m3u8/writer.rb
72
89
  - m3u8.gemspec
@@ -94,9 +111,11 @@ files:
94
111
  - spec/lib/m3u8/bitrate_item_spec.rb
95
112
  - spec/lib/m3u8/builder_spec.rb
96
113
  - spec/lib/m3u8/byte_range_spec.rb
114
+ - spec/lib/m3u8/cli/diff_command_spec.rb
97
115
  - spec/lib/m3u8/cli/inspect_command_spec.rb
98
116
  - spec/lib/m3u8/cli/validate_command_spec.rb
99
117
  - spec/lib/m3u8/cli_spec.rb
118
+ - spec/lib/m3u8/conformance_spec.rb
100
119
  - spec/lib/m3u8/content_steering_item_spec.rb
101
120
  - spec/lib/m3u8/date_range_item_spec.rb
102
121
  - spec/lib/m3u8/define_item_spec.rb
@@ -121,11 +140,13 @@ files:
121
140
  - spec/lib/m3u8/scte35_splice_null_spec.rb
122
141
  - spec/lib/m3u8/scte35_time_signal_spec.rb
123
142
  - spec/lib/m3u8/segment_item_spec.rb
143
+ - spec/lib/m3u8/serializable_spec.rb
124
144
  - spec/lib/m3u8/server_control_item_spec.rb
125
145
  - spec/lib/m3u8/session_data_item_spec.rb
126
146
  - spec/lib/m3u8/session_key_item_spec.rb
127
147
  - spec/lib/m3u8/skip_item_spec.rb
128
148
  - spec/lib/m3u8/time_item_spec.rb
149
+ - spec/lib/m3u8/variable_resolver_spec.rb
129
150
  - spec/lib/m3u8/writer_spec.rb
130
151
  - spec/lib/m3u8_spec.rb
131
152
  - spec/spec_helper.rb