m3u8 0.7.0 → 0.7.1

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +1 -0
  4. data/Guardfile +1 -0
  5. data/Rakefile +1 -0
  6. data/lib/m3u8.rb +6 -1
  7. data/lib/m3u8/byte_range.rb +1 -0
  8. data/lib/m3u8/date_range_item.rb +113 -0
  9. data/lib/m3u8/discontinuity_item.rb +1 -3
  10. data/lib/m3u8/encryptable.rb +1 -0
  11. data/lib/m3u8/error.rb +1 -0
  12. data/lib/m3u8/key_item.rb +1 -0
  13. data/lib/m3u8/map_item.rb +1 -0
  14. data/lib/m3u8/media_item.rb +1 -0
  15. data/lib/m3u8/playback_start.rb +1 -0
  16. data/lib/m3u8/playlist.rb +1 -0
  17. data/lib/m3u8/playlist_item.rb +12 -18
  18. data/lib/m3u8/reader.rb +17 -9
  19. data/lib/m3u8/segment_item.rb +1 -0
  20. data/lib/m3u8/session_data_item.rb +1 -0
  21. data/lib/m3u8/session_key_item.rb +1 -0
  22. data/lib/m3u8/time_item.rb +1 -0
  23. data/lib/m3u8/version.rb +2 -1
  24. data/lib/m3u8/writer.rb +1 -0
  25. data/spec/fixtures/date_range_scte35.m3u8 +16 -0
  26. data/spec/lib/m3u8/byte_range_spec.rb +1 -0
  27. data/spec/lib/m3u8/date_range_item_spec.rb +124 -0
  28. data/spec/lib/m3u8/discontinuity_item_spec.rb +1 -0
  29. data/spec/lib/m3u8/key_item_spec.rb +1 -0
  30. data/spec/lib/m3u8/map_item_spec.rb +2 -5
  31. data/spec/lib/m3u8/media_item_spec.rb +1 -0
  32. data/spec/lib/m3u8/playback_start_spec.rb +1 -0
  33. data/spec/lib/m3u8/playlist_item_spec.rb +1 -0
  34. data/spec/lib/m3u8/playlist_spec.rb +1 -0
  35. data/spec/lib/m3u8/reader_spec.rb +254 -236
  36. data/spec/lib/m3u8/segment_item_spec.rb +4 -14
  37. data/spec/lib/m3u8/session_data_item_spec.rb +1 -0
  38. data/spec/lib/m3u8/session_key_item_spec.rb +1 -0
  39. data/spec/lib/m3u8/time_item_spec.rb +1 -0
  40. data/spec/lib/m3u8/writer_spec.rb +174 -171
  41. data/spec/lib/m3u8_spec.rb +1 -0
  42. data/spec/spec_helper.rb +1 -0
  43. metadata +8 -3
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::DiscontinuityItem do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::KeyItem do
@@ -1,13 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::MapItem do
4
5
  it 'should provide m3u8 format representation' do
5
6
  hash = { uri: 'frelo/prog_index.m3u8',
6
- byterange: {
7
- length: 4500,
8
- start: 600
9
- }
10
- }
7
+ byterange: { length: 4500, start: 600 } }
11
8
  item = M3u8::MapItem.new(hash)
12
9
  output = item.to_s
13
10
  expected = '#EXT-X-MAP:URI="frelo/prog_index.m3u8",' \
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::MediaItem do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::PlaybackStart do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::PlaylistItem do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::Playlist do
@@ -1,241 +1,259 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  describe M3u8::Reader do
4
- it 'should parse master playlist' do
5
- file = File.open 'spec/fixtures/master.m3u8'
6
- reader = M3u8::Reader.new
7
- playlist = reader.read file
8
- expect(playlist.master?).to be true
9
-
10
- expect(playlist.independent_segments).to be true
11
-
12
- item = playlist.items[0]
13
- expect(item).to be_a(M3u8::SessionKeyItem)
14
- expect(item.method).to eq('AES-128')
15
- expect(item.uri).to eq('https://priv.example.com/key.php?r=52')
16
-
17
- item = playlist.items[1]
18
- expect(item).to be_a(M3u8::PlaybackStart)
19
- expect(item.time_offset).to eq(20.2)
20
-
21
- item = playlist.items[2]
22
- expect(item).to be_a(M3u8::PlaylistItem)
23
- expect(item.uri).to eq('hls/1080-7mbps/1080-7mbps.m3u8')
24
- expect(item.program_id).to eq('1')
25
- expect(item.width).to eq(1920)
26
- expect(item.height).to eq(1080)
27
- expect(item.resolution).to eq('1920x1080')
28
- expect(item.codecs).to eq('avc1.640028,mp4a.40.2')
29
- expect(item.bandwidth).to eq(5_042_000)
30
- expect(item.iframe).to be false
31
- expect(item.average_bandwidth).to be_nil
32
-
33
- item = playlist.items[7]
34
- expect(item).to be_a(M3u8::PlaylistItem)
35
- expect(item.uri).to eq('hls/64k/64k.m3u8')
36
- expect(item.program_id).to eq('1')
37
- expect(item.width).to be_nil
38
- expect(item.height).to be_nil
39
- expect(item.resolution).to be_nil
40
- expect(item.codecs).to eq('mp4a.40.2')
41
- expect(item.bandwidth).to eq(6400)
42
- expect(item.iframe).to be false
43
- expect(item.average_bandwidth).to be_nil
44
-
45
- expect(playlist.items.size).to eq(8)
46
-
47
- item = playlist.items.last
48
- expect(item.resolution).to be_nil
49
- end
50
-
51
- it 'should parse master playlist with I-Frames' do
52
- file = File.open 'spec/fixtures/master_iframes.m3u8'
53
- reader = M3u8::Reader.new
54
- playlist = reader.read file
55
- expect(playlist.master?).to be true
56
-
57
- expect(playlist.items.size).to eq(7)
58
-
59
- item = playlist.items[1]
60
- expect(item).to be_a(M3u8::PlaylistItem)
61
- expect(item.bandwidth).to eq(86_000)
62
- expect(item.iframe).to be true
63
- expect(item.uri).to eq 'low/iframe.m3u8'
64
- end
65
-
66
- it 'should parse segment playlist' do
67
- file = File.open 'spec/fixtures/playlist.m3u8'
68
- reader = M3u8::Reader.new
69
- playlist = reader.read file
70
- expect(playlist.master?).to be false
71
- expect(playlist.version).to eq 4
72
- expect(playlist.sequence).to eq 1
73
- expect(playlist.cache).to be false
74
- expect(playlist.target).to eq 12
75
- expect(playlist.type).to eq 'VOD'
76
-
77
- item = playlist.items[0]
78
- expect(item).to be_a(M3u8::SegmentItem)
79
- expect(item.duration).to eq 11.344644
80
- expect(item.comment).to be_nil
81
-
82
- item = playlist.items[4]
83
- expect(item).to be_a(M3u8::TimeItem)
84
- expect(item.time).to eq(Time.iso8601('2010-02-19T14:54:23Z'))
85
-
86
- expect(playlist.items.size).to eq 140
87
- end
88
-
89
- it 'should parse I-Frame playlist' do
90
- file = File.open 'spec/fixtures/iframes.m3u8'
91
- reader = M3u8::Reader.new
92
- playlist = reader.read file
93
-
94
- expect(playlist.iframes_only).to be true
95
- expect(playlist.items.size).to eq 3
96
-
97
- item = playlist.items[0]
98
- expect(item).to be_a(M3u8::SegmentItem)
99
- expect(item.duration).to eq 4.12
100
- expect(item.byterange.length).to eq 9400
101
- expect(item.byterange.start).to eq 376
102
- expect(item.segment).to eq 'segment1.ts'
103
-
104
- item = playlist.items[1]
105
- expect(item.byterange.length).to eq 7144
106
- expect(item.byterange.start).to be_nil
107
- end
108
-
109
- it 'should parse segment playlist with comments' do
110
- file = File.open 'spec/fixtures/playlist_with_comments.m3u8'
111
- reader = M3u8::Reader.new
112
- playlist = reader.read file
113
- expect(playlist.master?).to be false
114
- expect(playlist.version).to be 4
115
- expect(playlist.sequence).to be 1
116
- expect(playlist.cache).to be false
117
- expect(playlist.target).to be 12
118
- expect(playlist.type).to eq 'VOD'
119
-
120
- item = playlist.items[0]
121
- expect(item).to be_a(M3u8::SegmentItem)
122
- expect(item.duration).to eq 11.344644
123
- expect(item.comment).to eq 'anything'
124
-
125
- item = playlist.items[1]
126
- expect(item).to be_a(M3u8::DiscontinuityItem)
127
-
128
- expect(playlist.items.size).to eq 139
129
- end
130
-
131
- it 'should parse variant playlist with audio options and groups' do
132
- file = File.open 'spec/fixtures/variant_audio.m3u8'
133
- reader = M3u8::Reader.new
134
- playlist = reader.read file
135
-
136
- expect(playlist.master?).to be true
137
- expect(playlist.items.size).to eq 10
138
-
139
- item = playlist.items[0]
140
- expect(item).to be_a M3u8::MediaItem
141
- expect(item.type).to eq 'AUDIO'
142
- expect(item.group_id).to eq 'audio-lo'
143
- expect(item.language).to eq 'eng'
144
- expect(item.assoc_language).to eq 'spoken'
145
- expect(item.name).to eq 'English'
146
- expect(item.autoselect).to be true
147
- expect(item.default).to be true
148
- expect(item.uri).to eq 'englo/prog_index.m3u8'
149
- expect(item.forced).to be true
150
- end
151
-
152
- it 'should parse variant playlist with camera angles' do
153
- file = File.open 'spec/fixtures/variant_angles.m3u8'
154
- reader = M3u8::Reader.new
155
- playlist = reader.read file
156
-
157
- expect(playlist.master?).to be true
158
- expect(playlist.items.size).to eq 11
159
-
160
- item = playlist.items[1]
161
- expect(item).to be_a M3u8::MediaItem
162
- expect(item.type).to eq 'VIDEO'
163
- expect(item.group_id).to eq '200kbs'
164
- expect(item.language).to be_nil
165
- expect(item.name).to eq 'Angle2'
166
- expect(item.autoselect).to be true
167
- expect(item.default).to be false
168
- expect(item.uri).to eq 'Angle2/200kbs/prog_index.m3u8'
169
-
170
- item = playlist.items[9]
171
- expect(item.average_bandwidth).to eq 300_001
172
- expect(item.audio).to eq 'aac'
173
- expect(item.video).to eq '200kbs'
174
- expect(item.closed_captions).to eq 'captions'
175
- expect(item.subtitles).to eq 'subs'
176
- end
177
-
178
- it 'should process multiple reads as separate playlists' do
179
- file = File.open 'spec/fixtures/master.m3u8'
180
- reader = M3u8::Reader.new
181
- playlist = reader.read file
182
-
183
- expect(playlist.items.size).to eq(8)
184
-
185
- file = File.open 'spec/fixtures/master.m3u8'
186
- playlist = reader.read file
187
-
188
- expect(playlist.items.size).to eq(8)
189
- end
190
-
191
- it 'should parse playlist with session data' do
192
- file = File.open 'spec/fixtures/session_data.m3u8'
193
- reader = M3u8::Reader.new
194
- playlist = reader.read file
195
-
196
- expect(playlist.items.size).to eq 3
197
-
198
- item = playlist.items[0]
199
- expect(item).to be_a M3u8::SessionDataItem
200
- expect(item.data_id).to eq 'com.example.lyrics'
201
- expect(item.uri).to eq 'lyrics.json'
202
- end
203
-
204
- it 'should parse encrypted playlist' do
205
- file = File.open 'spec/fixtures/encrypted.m3u8'
206
- reader = M3u8::Reader.new
207
- playlist = reader.read file
208
-
209
- expect(playlist.items.size).to eq 6
210
-
211
- item = playlist.items[0]
212
- expect(item).to be_a M3u8::KeyItem
213
- expect(item.method).to eq 'AES-128'
214
- expect(item.uri).to eq 'https://priv.example.com/key.php?r=52'
215
- end
216
-
217
- it 'should parse map (media intialization section) playlists' do
218
- file = File.open 'spec/fixtures/map_playlist.m3u8'
219
- reader = M3u8::Reader.new
220
- playlist = reader.read file
221
-
222
- expect(playlist.items.size).to eq 1
223
-
224
- item = playlist.items[0]
225
- expect(item).to be_a M3u8::MapItem
226
- expect(item.uri).to eq 'frelo/prog_index.m3u8'
227
- expect(item.byterange.length).to eq 4500
228
- expect(item.byterange.start).to eq 600
229
- end
230
-
231
- it 'should read segment with timestamp' do
232
- file = File.open 'spec/fixtures/timestamp_playlist.m3u8'
233
- reader = M3u8::Reader.new
234
- playlist = reader.read file
235
- expect(playlist.items.count).to eq 6
236
-
237
- item_date_time = playlist.items.first.program_date_time
238
- expect(item_date_time).to be_a M3u8::TimeItem
239
- expect(item_date_time.time).to eq Time.iso8601('2016-04-11T15:24:31Z')
5
+ describe '#read' do
6
+ it 'should parse master playlist' do
7
+ file = File.open('spec/fixtures/master.m3u8')
8
+ reader = M3u8::Reader.new
9
+ playlist = reader.read(file)
10
+ expect(playlist.master?).to be true
11
+
12
+ expect(playlist.independent_segments).to be true
13
+
14
+ item = playlist.items[0]
15
+ expect(item).to be_a(M3u8::SessionKeyItem)
16
+ expect(item.method).to eq('AES-128')
17
+ expect(item.uri).to eq('https://priv.example.com/key.php?r=52')
18
+
19
+ item = playlist.items[1]
20
+ expect(item).to be_a(M3u8::PlaybackStart)
21
+ expect(item.time_offset).to eq(20.2)
22
+
23
+ item = playlist.items[2]
24
+ expect(item).to be_a(M3u8::PlaylistItem)
25
+ expect(item.uri).to eq('hls/1080-7mbps/1080-7mbps.m3u8')
26
+ expect(item.program_id).to eq('1')
27
+ expect(item.width).to eq(1920)
28
+ expect(item.height).to eq(1080)
29
+ expect(item.resolution).to eq('1920x1080')
30
+ expect(item.codecs).to eq('avc1.640028,mp4a.40.2')
31
+ expect(item.bandwidth).to eq(5_042_000)
32
+ expect(item.iframe).to be false
33
+ expect(item.average_bandwidth).to be_nil
34
+
35
+ item = playlist.items[7]
36
+ expect(item).to be_a(M3u8::PlaylistItem)
37
+ expect(item.uri).to eq('hls/64k/64k.m3u8')
38
+ expect(item.program_id).to eq('1')
39
+ expect(item.width).to be_nil
40
+ expect(item.height).to be_nil
41
+ expect(item.resolution).to be_nil
42
+ expect(item.codecs).to eq('mp4a.40.2')
43
+ expect(item.bandwidth).to eq(6400)
44
+ expect(item.iframe).to be false
45
+ expect(item.average_bandwidth).to be_nil
46
+
47
+ expect(playlist.items.size).to eq(8)
48
+
49
+ item = playlist.items.last
50
+ expect(item.resolution).to be_nil
51
+ end
52
+
53
+ it 'should parse master playlist with I-Frames' do
54
+ file = File.open('spec/fixtures/master_iframes.m3u8')
55
+ reader = M3u8::Reader.new
56
+ playlist = reader.read(file)
57
+ expect(playlist.master?).to be true
58
+
59
+ expect(playlist.items.size).to eq(7)
60
+
61
+ item = playlist.items[1]
62
+ expect(item).to be_a(M3u8::PlaylistItem)
63
+ expect(item.bandwidth).to eq(86_000)
64
+ expect(item.iframe).to be true
65
+ expect(item.uri).to eq('low/iframe.m3u8')
66
+ end
67
+
68
+ it 'should parse segment playlist' do
69
+ file = File.open('spec/fixtures/playlist.m3u8')
70
+ reader = M3u8::Reader.new
71
+ playlist = reader.read(file)
72
+ expect(playlist.master?).to be false
73
+ expect(playlist.version).to eq(4)
74
+ expect(playlist.sequence).to eq(1)
75
+ expect(playlist.cache).to be false
76
+ expect(playlist.target).to eq(12)
77
+ expect(playlist.type).to eq('VOD')
78
+
79
+ item = playlist.items[0]
80
+ expect(item).to be_a(M3u8::SegmentItem)
81
+ expect(item.duration).to eq(11.344644)
82
+ expect(item.comment).to be_nil
83
+
84
+ item = playlist.items[4]
85
+ expect(item).to be_a(M3u8::TimeItem)
86
+ expect(item.time).to eq(Time.iso8601('2010-02-19T14:54:23Z'))
87
+
88
+ expect(playlist.items.size).to eq(140)
89
+ end
90
+
91
+ it 'should parse I-Frame playlist' do
92
+ file = File.open('spec/fixtures/iframes.m3u8')
93
+ reader = M3u8::Reader.new
94
+ playlist = reader.read(file)
95
+
96
+ expect(playlist.iframes_only).to be true
97
+ expect(playlist.items.size).to eq(3)
98
+
99
+ item = playlist.items[0]
100
+ expect(item).to be_a(M3u8::SegmentItem)
101
+ expect(item.duration).to eq(4.12)
102
+ expect(item.byterange.length).to eq(9400)
103
+ expect(item.byterange.start).to eq(376)
104
+ expect(item.segment).to eq('segment1.ts')
105
+
106
+ item = playlist.items[1]
107
+ expect(item.byterange.length).to eq(7144)
108
+ expect(item.byterange.start).to be_nil
109
+ end
110
+
111
+ it 'should parse segment playlist with comments' do
112
+ file = File.open('spec/fixtures/playlist_with_comments.m3u8')
113
+ reader = M3u8::Reader.new
114
+ playlist = reader.read(file)
115
+ expect(playlist.master?).to be false
116
+ expect(playlist.version).to eq(4)
117
+ expect(playlist.sequence).to eq(1)
118
+ expect(playlist.cache).to be false
119
+ expect(playlist.target).to eq(12)
120
+ expect(playlist.type).to eq('VOD')
121
+
122
+ item = playlist.items[0]
123
+ expect(item).to be_a(M3u8::SegmentItem)
124
+ expect(item.duration).to eq(11.344644)
125
+ expect(item.comment).to eq('anything')
126
+
127
+ item = playlist.items[1]
128
+ expect(item).to be_a(M3u8::DiscontinuityItem)
129
+
130
+ expect(playlist.items.size).to eq(139)
131
+ end
132
+
133
+ it 'should parse variant playlist with audio options and groups' do
134
+ file = File.open('spec/fixtures/variant_audio.m3u8')
135
+ reader = M3u8::Reader.new
136
+ playlist = reader.read(file)
137
+
138
+ expect(playlist.master?).to be true
139
+ expect(playlist.items.size).to eq(10)
140
+
141
+ item = playlist.items[0]
142
+ expect(item).to be_a(M3u8::MediaItem)
143
+ expect(item.type).to eq('AUDIO')
144
+ expect(item.group_id).to eq('audio-lo')
145
+ expect(item.language).to eq('eng')
146
+ expect(item.assoc_language).to eq('spoken')
147
+ expect(item.name).to eq('English')
148
+ expect(item.autoselect).to be true
149
+ expect(item.default).to be true
150
+ expect(item.uri).to eq('englo/prog_index.m3u8')
151
+ expect(item.forced).to be true
152
+ end
153
+
154
+ it 'should parse variant playlist with camera angles' do
155
+ file = File.open('spec/fixtures/variant_angles.m3u8')
156
+ reader = M3u8::Reader.new
157
+ playlist = reader.read(file)
158
+
159
+ expect(playlist.master?).to be true
160
+ expect(playlist.items.size).to eq(11)
161
+
162
+ item = playlist.items[1]
163
+ expect(item).to be_a(M3u8::MediaItem)
164
+ expect(item.type).to eq('VIDEO')
165
+ expect(item.group_id).to eq('200kbs')
166
+ expect(item.language).to be_nil
167
+ expect(item.name).to eq('Angle2')
168
+ expect(item.autoselect).to be true
169
+ expect(item.default).to be false
170
+ expect(item.uri).to eq('Angle2/200kbs/prog_index.m3u8')
171
+
172
+ item = playlist.items[9]
173
+ expect(item.average_bandwidth).to eq(300_001)
174
+ expect(item.audio).to eq('aac')
175
+ expect(item.video).to eq('200kbs')
176
+ expect(item.closed_captions).to eq('captions')
177
+ expect(item.subtitles).to eq('subs')
178
+ end
179
+
180
+ it 'should process multiple reads as separate playlists' do
181
+ file = File.open('spec/fixtures/master.m3u8')
182
+ reader = M3u8::Reader.new
183
+ playlist = reader.read(file)
184
+
185
+ expect(playlist.items.size).to eq(8)
186
+
187
+ file = File.open('spec/fixtures/master.m3u8')
188
+ playlist = reader.read(file)
189
+
190
+ expect(playlist.items.size).to eq(8)
191
+ end
192
+
193
+ it 'should parse playlist with session data' do
194
+ file = File.open('spec/fixtures/session_data.m3u8')
195
+ reader = M3u8::Reader.new
196
+ playlist = reader.read(file)
197
+
198
+ expect(playlist.items.size).to eq(3)
199
+
200
+ item = playlist.items[0]
201
+ expect(item).to be_a(M3u8::SessionDataItem)
202
+ expect(item.data_id).to eq('com.example.lyrics')
203
+ expect(item.uri).to eq('lyrics.json')
204
+ end
205
+
206
+ it 'should parse encrypted playlist' do
207
+ file = File.open('spec/fixtures/encrypted.m3u8')
208
+ reader = M3u8::Reader.new
209
+ playlist = reader.read(file)
210
+
211
+ expect(playlist.items.size).to eq(6)
212
+
213
+ item = playlist.items[0]
214
+ expect(item).to be_a(M3u8::KeyItem)
215
+ expect(item.method).to eq('AES-128')
216
+ expect(item.uri).to eq('https://priv.example.com/key.php?r=52')
217
+ end
218
+
219
+ it 'should parse map (media intialization section) playlists' do
220
+ file = File.open('spec/fixtures/map_playlist.m3u8')
221
+ reader = M3u8::Reader.new
222
+ playlist = reader.read(file)
223
+
224
+ expect(playlist.items.size).to eq(1)
225
+
226
+ item = playlist.items[0]
227
+ expect(item).to be_a(M3u8::MapItem)
228
+ expect(item.uri).to eq('frelo/prog_index.m3u8')
229
+ expect(item.byterange.length).to eq(4500)
230
+ expect(item.byterange.start).to eq(600)
231
+ end
232
+
233
+ it 'should read segment with timestamp' do
234
+ file = File.open('spec/fixtures/timestamp_playlist.m3u8')
235
+ reader = M3u8::Reader.new
236
+ playlist = reader.read(file)
237
+ expect(playlist.items.count).to eq(6)
238
+
239
+ item_date_time = playlist.items.first.program_date_time
240
+ expect(item_date_time).to be_a(M3u8::TimeItem)
241
+ expect(item_date_time.time).to eq(Time.iso8601('2016-04-11T15:24:31Z'))
242
+ end
243
+
244
+ context 'playlist with daterange' do
245
+ it 'parses playlist' do
246
+ file = File.open('spec/fixtures/date_range_scte35.m3u8')
247
+ reader = M3u8::Reader.new
248
+ playlist = reader.read(file)
249
+ expect(playlist.items.count).to eq(5)
250
+
251
+ item = playlist.items[0]
252
+ expect(item).to be_a(M3u8::DateRangeItem)
253
+
254
+ item = playlist.items[4]
255
+ expect(item).to be_a(M3u8::DateRangeItem)
256
+ end
257
+ end
240
258
  end
241
259
  end