m3u8 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3797c5f6de3b71d0ea5974be7aef7dc416cf0977
4
- data.tar.gz: cf67c30e9e26e611a55d5908de78497453181947
3
+ metadata.gz: 54599784eb3cf885ed988991d50590eb1190b63d
4
+ data.tar.gz: ca8ce3a4faf778a961fd937057702ecba30a9905
5
5
  SHA512:
6
- metadata.gz: 000f3f17395510b0af051895793cb0a48019e5848b5419dc6c771c987f597cc9da68aab90e0ae7eb031fbde014ab032a78361e3ae638c567797ab2cd1acd6b27
7
- data.tar.gz: b1320f06d435c05b174aa19113fe41bc75b11150f6ca097e6dd38bf518ebe3a94b273e2fd8ae59fc305e361610862a315d0b36a72e6b1948cc435c7dc8412aeb
6
+ metadata.gz: db42bd190ed77c6595b8ba4f42ccbdb28a8d42a4e0f0f840ab0d5b2b7fb480fb9e99b3415dbc3a172dd29126c08647ebf2e234c8d0d47d4b56afe0f9c6e34590
7
+ data.tar.gz: 5ac8f0fa3f99a83bf088435be2ff0625bc9d5db5f3159f88f575fe8c5d7a6e4561c671ec999c9359533a1c8c69685ce034c606ceae9c61acbc1a751388ff28b9
@@ -1,17 +1,19 @@
1
- ### 0.5.0 (2/10/2015) - BREAKING: renamed PlaylistItem.playlist to PlaylistItem.uri, MediaItem.group to MediaItem.group_id, and PlaylistItem.bitrate to PlaylistItem.bandwidth so attributes more closely match the spec. Added support for EXT-X-I-FRAME-STREAM-INF, EXT-X-I-FRAMES-ONLY, EXT-X-BYTERANGE, and EXT-X-SESSION-DATA.
2
-
3
- ### 0.4.0 (1/20/2015) - BREAKING: Playlist.audio is now Playlist.audio_codec, audio now represents the newly supported AUDIO attribute, please update your code accordingly. Added support for all EXT-X-MEDIA attributes as well as the following EXT-X-STREAM-INF attributes: AVERAGE-BANDWIDTH, AUDIO, VIDEO, SUBTILES, and CLOSED-CAPTIONS. This means the library now supports alternate audio / camera angles as well as subtitles and closed captions. The EXT-X-PLAYLIST-TYPE attribute is now supported as Playlist.type. SegmentItems now support comments (Thanks @elsurudo). A bug was also fixed in Reader that prevented reuse of the instance.
4
-
5
- ### 0.3.2 (1/16/2015) - PROGRAM-ID was removed in protocol version 6, if not provided it will now be omitted. Thanks @elsurudo
6
-
7
- ### 0.3.1 (1/15/2015) - Added duration method to Playlist to get the total length of segments contained within it. Thanks @DaKaZ
8
-
9
- ### 0.3.0 (11/26/2014) - DEPRECIATED add_playlist and add_segment on Playlist, manipulate the items array directly instead. Extracted writing of playlists to it's own Writer class (only use directly if you want more control over the process). Added read convience method to Playlist so Reader doesn't have to be used directly unless more control is desired. Simplified validation and other aspects during this refactoring.
10
-
11
- ### 0.2.1 (11/26/2014) - Moved codec generation / validation to PlaylistItem, allowing for the flexibility to either specify :audio, :level, :profile when creating new instances (codecs value will be automatically generated) or just set the codecs attribute directly.
12
-
13
- ### 0.2.0 (11/25/2014) - Added ability to parse m3u8 playlists with new Reader class. Introduced two new classes to represent the items that make up a Playlist: PlaylistItem and SegmentItem.
14
-
15
- ### 0.1.3 (11/23/2014) - Fixed bug in codec string generation.
16
-
17
- ### 0.1.0 (10/06/2014) - Initial release, provides ability to generate m3u8 playlists (master and segments).
1
+ #### 0.5.1 (2/16/2015) - [takashisite](https://github.com/takashisite) added support for [EXT-X-DISCONTINUITY](https://tools.ietf.org/html/draft-pantos-http-live-streaming-14#section-4.3.2.3). Added support for [EXT-X-KEY](https://tools.ietf.org/html/draft-pantos-http-live-streaming-14#section-4.3.2.4) (keys for encrypted segments).
2
+ ***
3
+ #### 0.5.0 (2/10/2015) - BREAKING: renamed PlaylistItem.playlist to PlaylistItem.uri, MediaItem.group to MediaItem.group_id, and PlaylistItem.bitrate to PlaylistItem.bandwidth so attributes more closely match the spec. Added support for EXT-X-I-FRAME-STREAM-INF, EXT-X-I-FRAMES-ONLY, EXT-X-BYTERANGE, and EXT-X-SESSION-DATA.
4
+ ***
5
+ #### 0.4.0 (1/20/2015) - BREAKING: Playlist.audio is now Playlist.audio_codec, audio now represents the newly supported AUDIO attribute, please update your code accordingly. Added support for all EXT-X-MEDIA attributes as well as the following EXT-X-STREAM-INF attributes: AVERAGE-BANDWIDTH, AUDIO, VIDEO, SUBTILES, and CLOSED-CAPTIONS. This means the library now supports alternate audio / camera angles as well as subtitles and closed captions. The EXT-X-PLAYLIST-TYPE attribute is now supported as Playlist.type. [elsurudo](https://github.com/elsurudo) added support for comments/titles in SegmentItems. A bug was also fixed in Reader that prevented reuse of the instance.
6
+ ***
7
+ #### 0.3.2 (1/16/2015) - PROGRAM-ID was removed in protocol version 6, if not provided it will now be omitted with a fix implemented by [elsurudo](https://github.com/elsurudo).
8
+ ***
9
+ #### 0.3.1 (1/15/2015) - [DaKaZ](https://github.com/DaKaZ) added duration method to Playlist to get the total length of segments contained within it.
10
+ ***
11
+ #### 0.3.0 (11/26/2014) - DEPRECIATED add_playlist and add_segment on Playlist, manipulate the items array directly instead. Extracted writing of playlists to it's own Writer class (only use directly if you want more control over the process). Added read convience method to Playlist so Reader doesn't have to be used directly unless more control is desired. Simplified validation and other aspects during this refactoring.
12
+ ***
13
+ #### 0.2.1 (11/26/2014) - Moved codec generation / validation to PlaylistItem, allowing for the flexibility to either specify :audio, :level, :profile when creating new instances (codecs value will be automatically generated) or just set the codecs attribute directly.
14
+ ***
15
+ #### 0.2.0 (11/25/2014) - Added ability to parse m3u8 playlists with new Reader class. Introduced two new classes to represent the items that make up a Playlist: PlaylistItem and SegmentItem.
16
+ ***
17
+ #### 0.1.3 (11/23/2014) - Fixed bug in codec string generation.
18
+ ***
19
+ #### 0.1.0 (10/06/2014) - Initial release, provides ability to generate m3u8 playlists (master and segments).
data/README.md CHANGED
@@ -34,9 +34,8 @@ playlist = M3u8::Playlist.new
34
34
 
35
35
  Create a new playlist item with options:
36
36
  ```ruby
37
- options = { program_id: 1, width: 1920, height: 1080, width: 1920, height: 1080,
38
- profile: 'high', level: 4.1, audio_codec: 'aac-lc', bandwidth: 540,
39
- playlist: 'test.url' }
37
+ options = { width: 1920, height: 1080, profile: 'high', level: 4.1,
38
+ audio_codec: 'aac-lc', bandwidth: 540, uri: 'test.url' }
40
39
  item = M3u8::PlaylistItem.new options
41
40
  playlist.items.push item
42
41
  ```
@@ -74,8 +73,8 @@ M3u8::Writer is the class that handles generating the playlist output.
74
73
 
75
74
  Alternatively you can set codecs rather than having it generated automatically:
76
75
  ```ruby
77
- options = { program_id: 1, width: 1920, height: 1080, width: 1920, height: 1080,
78
- codecs: 'avc1.66.30,mp4a.40.2', bandwidth: 540, playlist: 'test.url' }
76
+ options = { width: 1920, height: 1080, codecs: 'avc1.66.30,mp4a.40.2',
77
+ bandwidth: 540, uri: 'test.url' }
79
78
  item = M3u8::PlaylistItem.new options
80
79
  ```
81
80
  Just get the codec string for custom use:
@@ -109,9 +108,8 @@ playlist.items.first
109
108
  ```
110
109
  Create a new playlist item with options:
111
110
  ```ruby
112
- options = { program_id: 1, width: 1920, height: 1080, width: 1920, height: 1080,
113
- profile: 'high', level: 4.1, audio_codec: 'aac-lc', bandwidth: 540,
114
- playlist: 'test.url' }
111
+ options = { width: 1920, height: 1080, profile: 'high', level: 4.1,
112
+ audio_codec: 'aac-lc', bandwidth: 540, uri: 'test.url' }
115
113
  item = M3u8::PlaylistItem.new options
116
114
  #add it to the top of the playlist
117
115
  playlist.items.insert 0, item
@@ -126,19 +124,18 @@ M3u8::Reader is the class handles parsing if you want more control over the proc
126
124
  * Supports I-Frames (Intra frames) and Byte Ranges in Segments.
127
125
  * Supports subtitles, closed captions, alternate audio and video, and comments.
128
126
  # Supports Session Data in master playlists.
127
+ * Supports keys for encrypted media segments (EXT-X-KEY).
128
+ * Supports EXT-X-DISCONTINUITY in media segments.
129
129
  * Can write playlist to an IO object (StringIO/File, etc) or access string via to_s.
130
130
  * Can read playlists into a model (Playlist and Items) from an IO object.
131
131
  * Any tag or attribute supported by the object model is supported both parsing and generation of m3u8 playlists.
132
132
 
133
133
  ## Missing (but planned) Features
134
- * Support for encrypted segments.
135
134
  * Validation of all attributes and their values to match the rules defined in the spec.
136
135
  * Still missing support for a few tags and attributes.
137
136
 
138
137
  ## Contributing
139
138
 
140
- (Be sure to check to dev branch to make sure I'm not already working on it)
141
-
142
139
  1. Fork it ( https://github.com/sethdeckard/m3u8/fork )
143
140
  2. Create your feature branch (`git checkout -b my-new-feature`)
144
141
  3. Run the specs, make sure they pass and that new features are covered
@@ -3,14 +3,16 @@ require 'm3u8/version'
3
3
  require 'm3u8/playlist'
4
4
  require 'm3u8/playlist_item'
5
5
  require 'm3u8/segment_item'
6
+ require 'm3u8/discontinuity_item'
7
+ require 'm3u8/key_item'
6
8
  require 'm3u8/media_item'
7
9
  require 'm3u8/session_data_item'
8
10
  require 'm3u8/reader'
9
11
  require 'm3u8/writer'
10
12
  require 'm3u8/error'
11
13
 
14
+ # M3u8 provides parsing, generation, and validation of m3u8 playlists
12
15
  module M3u8
13
-
14
16
  def parse_attributes(line)
15
17
  array = line.scan(/([A-z-]+)\s*=\s*("[^"]*"|[^,]*)/)
16
18
  Hash[array.map { |key, value| [key, value.gsub('"', '')] }]
@@ -0,0 +1,14 @@
1
+ module M3u8
2
+ # DiscontinuityItem represents a EXT-X-DISCONTINUITY tag to indicate a
3
+ # discontinuity between the SegmentItems that proceed and follow it.
4
+ class DiscontinuityItem
5
+ attr_accessor :tag
6
+
7
+ def initialize
8
+ end
9
+
10
+ def to_s
11
+ "#EXT-X-DISCONTINUITY\n"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,54 @@
1
+ module M3u8
2
+ # KeyItem represents a set of EXT-X-KEY attributes
3
+ class KeyItem
4
+ extend M3u8
5
+ attr_accessor :method, :uri, :iv, :key_format, :key_format_versions
6
+
7
+ def initialize(params = {})
8
+ params.each do |key, value|
9
+ instance_variable_set("@#{key}", value)
10
+ end
11
+ end
12
+
13
+ def self.parse(text)
14
+ attributes = parse_attributes text
15
+ options = { method: attributes['METHOD'], uri: attributes['URI'],
16
+ iv: attributes['IV'], key_format: attributes['KEYFORMAT'],
17
+ key_format_versions: attributes['KEYFORMATVERSIONS'] }
18
+ KeyItem.new options
19
+ end
20
+
21
+ def to_s
22
+ attributes = [method_format,
23
+ uri_format,
24
+ iv_format,
25
+ key_format_format,
26
+ key_format_versions_format].compact.join(',')
27
+ "#EXT-X-KEY:#{attributes}"
28
+ end
29
+
30
+ private
31
+
32
+ def method_format
33
+ "METHOD=#{method}"
34
+ end
35
+
36
+ def uri_format
37
+ %(URI="#{uri}") unless uri.nil?
38
+ end
39
+
40
+ def iv_format
41
+ "IV=#{iv}" unless iv.nil?
42
+ end
43
+
44
+ def key_format_format
45
+ %(KEYFORMAT="#{key_format}") unless key_format.nil?
46
+ end
47
+
48
+ def key_format_versions_format
49
+ return if key_format_versions.nil?
50
+
51
+ %(KEYFORMATVERSIONS="#{key_format_versions}")
52
+ end
53
+ end
54
+ end
@@ -1,4 +1,5 @@
1
1
  module M3u8
2
+ # Reader provides parsing of m3u8 playlists
2
3
  class Reader
3
4
  attr_accessor :playlist, :item, :open, :master
4
5
  PLAYLIST_START = '#EXTM3U'
@@ -12,7 +13,9 @@ module M3u8
12
13
  STREAM_IFRAME_START = '#EXT-X-I-FRAME-STREAM-INF:'
13
14
  MEDIA_START = '#EXT-X-MEDIA:'
14
15
  SESSION_DATA_START = '#EXT-X-SESSION-DATA:'
16
+ KEY_START = '#EXT-X-KEY:'
15
17
  SEGMENT_START = '#EXTINF:'
18
+ SEGMENT_DISCONTINUITY_TAG_START = '#EXT-X-DISCONTINUITY'
16
19
  BYTERANGE_START = '#EXT-X-BYTERANGE:'
17
20
  RESOLUTION = 'RESOLUTION'
18
21
  BANDWIDTH = 'BANDWIDTH'
@@ -33,27 +36,13 @@ module M3u8
33
36
 
34
37
  def parse_line(line)
35
38
  return if line.start_with? PLAYLIST_START
36
-
37
- if line.start_with? STREAM_START
38
- parse_stream line
39
- elsif line.start_with? STREAM_IFRAME_START
40
- parse_iframe_stream line
41
- elsif line.start_with? SEGMENT_START
42
- parse_segment line
43
- elsif line.start_with? MEDIA_START
44
- parse_media line
45
- elsif line.start_with? BYTERANGE_START
46
- parse_byterange line
47
- elsif line.start_with? SESSION_DATA_START
48
- parse_session_data line
49
- elsif !item.nil? && open
50
- parse_next_line line
51
- else
52
- parse_header line
53
- end
39
+ return if parse_master_playlist_tags line
40
+ return if parse_segment_tags line
41
+ return if parse_header_tags line
42
+ parse_next_line line if !item.nil? && open
54
43
  end
55
44
 
56
- def parse_header(line)
45
+ def parse_header_tags(line)
57
46
  if line.start_with? PLAYLIST_TYPE_START
58
47
  parse_playlist_type line
59
48
  elsif line.start_with? VERSION_START
@@ -66,6 +55,36 @@ module M3u8
66
55
  parse_target line
67
56
  elsif line.start_with? IFRAME_START
68
57
  playlist.iframes_only = true
58
+ else
59
+ return false
60
+ end
61
+ end
62
+
63
+ def parse_master_playlist_tags(line)
64
+ if line.start_with? STREAM_START
65
+ parse_stream line
66
+ elsif line.start_with? STREAM_IFRAME_START
67
+ parse_iframe_stream line
68
+ elsif line.start_with? MEDIA_START
69
+ parse_media line
70
+ elsif line.start_with? SEGMENT_DISCONTINUITY_TAG_START
71
+ parse_segment_discontinuity_tag line
72
+ elsif line.start_with? SESSION_DATA_START
73
+ parse_session_data line
74
+ else
75
+ return false
76
+ end
77
+ end
78
+
79
+ def parse_segment_tags(line)
80
+ if line.start_with? KEY_START
81
+ parse_key line
82
+ elsif line.start_with? SEGMENT_START
83
+ parse_segment line
84
+ elsif line.start_with? BYTERANGE_START
85
+ parse_byterange line
86
+ else
87
+ return false
69
88
  end
70
89
  end
71
90
 
@@ -129,11 +148,24 @@ module M3u8
129
148
  end
130
149
  end
131
150
 
151
+ def parse_segment_discontinuity_tag(*)
152
+ self.master = false
153
+ self.open = false
154
+
155
+ self.item = M3u8::DiscontinuityItem.new
156
+ playlist.items.push item
157
+ end
158
+
132
159
  def parse_resolution(resolution)
133
160
  item.width = resolution.split('x')[0].to_i
134
161
  item.height = resolution.split('x')[1].to_i
135
162
  end
136
163
 
164
+ def parse_key(line)
165
+ item = M3u8::KeyItem.parse line
166
+ playlist.items.push item
167
+ end
168
+
137
169
  def parse_segment(line)
138
170
  self.item = M3u8::SegmentItem.new
139
171
  values = line.gsub(SEGMENT_START, '').gsub("\n", ',').split(',')
@@ -1,4 +1,6 @@
1
1
  module M3u8
2
+ # SegmentItem represents EXTINF attributes with the URI that follows,
3
+ # optionally allowing an EXT-X-BYTERANGE tag to be set.
2
4
  class SegmentItem
3
5
  attr_accessor :duration, :segment, :comment, :byterange_length,
4
6
  :byterange_start
@@ -1,3 +1,4 @@
1
+ # M3u8 provides parsing, generation, and validation of m3u8 playlists
1
2
  module M3u8
2
- VERSION = '0.5.0'
3
+ VERSION = '0.5.1'
3
4
  end
@@ -1,4 +1,5 @@
1
1
  module M3u8
2
+ # Writer provides generation of text output of playlists in m3u8 format
2
3
  class Writer
3
4
  attr_accessor :io
4
5
 
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe M3u8::DiscontinuityItem do
4
+ it 'should provide m3u8 format representation' do
5
+ item = M3u8::DiscontinuityItem.new
6
+ output = item.to_s
7
+ expected = "#EXT-X-DISCONTINUITY\n"
8
+ expect(output).to eq expected
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ #EXTM3U
2
+ #EXT-X-VERSION:3
3
+ #EXT-X-MEDIA-SEQUENCE:7794
4
+ #EXT-X-TARGETDURATION:15
5
+
6
+ #EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52"
7
+
8
+ #EXTINF:2.833,
9
+ http://media.example.com/fileSequence52-A.ts
10
+ #EXTINF:15.0,
11
+ http://media.example.com/fileSequence52-B.ts
12
+ #EXTINF:13.333,
13
+ http://media.example.com/fileSequence52-C.ts
14
+
15
+ #EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=53"
16
+
17
+ #EXTINF:15.0,
18
+ http://media.example.com/fileSequence53-A.ts
@@ -6,6 +6,7 @@
6
6
  #EXT-X-TARGETDURATION:12
7
7
  #EXTINF:11.344644,
8
8
  1080-7mbps00000.ts
9
+ #EXT-X-DISCONTINUITY
9
10
  #EXTINF:11.261233,
10
11
  1080-7mbps00001.ts
11
12
  #EXTINF:7.507489,
@@ -6,6 +6,7 @@
6
6
  #EXT-X-TARGETDURATION:12
7
7
  #EXTINF:11.344644,anything
8
8
  1080-7mbps00000.ts
9
+ #EXT-X-DISCONTINUITY
9
10
  #EXTINF:11.261233,anything
10
11
  1080-7mbps00001.ts
11
12
  #EXTINF:7.507489,anything
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe M3u8::KeyItem do
4
+ it 'should initialize with hash' do
5
+ hash = { method: 'AES-128', uri: 'http://test.key',
6
+ iv: 'D512BBF', key_format: 'identity',
7
+ key_format_versions: '1/3' }
8
+ item = M3u8::KeyItem.new(hash)
9
+ expect(item.method).to eq 'AES-128'
10
+ expect(item.uri).to eq 'http://test.key'
11
+ expect(item.iv).to eq 'D512BBF'
12
+ expect(item.key_format).to eq 'identity'
13
+ expect(item.key_format_versions).to eq '1/3'
14
+ end
15
+
16
+ it 'should provide m3u8 format representation' do
17
+ hash = { method: 'AES-128', uri: 'http://test.key',
18
+ iv: 'D512BBF', key_format: 'identity',
19
+ key_format_versions: '1/3' }
20
+ item = M3u8::KeyItem.new(hash)
21
+ expected = %(#EXT-X-KEY:METHOD=AES-128,URI="http://test.key",) +
22
+ %(IV=D512BBF,KEYFORMAT="identity",KEYFORMATVERSIONS="1/3")
23
+ expect(item.to_s).to eq expected
24
+
25
+ hash = { method: 'AES-128', uri: 'http://test.key' }
26
+ item = M3u8::KeyItem.new(hash)
27
+ expected = %(#EXT-X-KEY:METHOD=AES-128,URI="http://test.key")
28
+ expect(item.to_s).to eq expected
29
+
30
+ hash = { method: 'NONE' }
31
+ item = M3u8::KeyItem.new(hash)
32
+ expected = '#EXT-X-KEY:METHOD=NONE'
33
+ expect(item.to_s).to eq expected
34
+ end
35
+
36
+ it 'should parse m3u8 format into instance' do
37
+ format = %(#EXT-X-KEY:METHOD=AES-128,URI="http://test.key",) +
38
+ %(IV=D512BBF,KEYFORMAT="identity",KEYFORMATVERSIONS="1/3")
39
+ item = M3u8::KeyItem.parse format
40
+ expect(item.method).to eq 'AES-128'
41
+ expect(item.uri).to eq 'http://test.key'
42
+ expect(item.iv).to eq 'D512BBF'
43
+ expect(item.key_format).to eq 'identity'
44
+ expect(item.key_format_versions).to eq '1/3'
45
+ end
46
+ end
@@ -55,7 +55,7 @@ describe M3u8::Reader do
55
55
  expect(item.duration).to eq 11.344644
56
56
  expect(item.comment).to be_nil
57
57
 
58
- expect(playlist.items.size).to eq 138
58
+ expect(playlist.items.size).to eq 139
59
59
  end
60
60
 
61
61
  it 'should parse I-Frame playlist' do
@@ -94,7 +94,10 @@ describe M3u8::Reader do
94
94
  expect(item.duration).to eq 11.344644
95
95
  expect(item.comment).to eq 'anything'
96
96
 
97
- expect(playlist.items.size).to eq 138
97
+ item = playlist.items[1]
98
+ expect(item).to be_a(M3u8::DiscontinuityItem)
99
+
100
+ expect(playlist.items.size).to eq 139
98
101
  end
99
102
 
100
103
  it 'should parse variant playlist with audio options and groups' do
@@ -169,4 +172,17 @@ describe M3u8::Reader do
169
172
  expect(item.data_id).to eq 'com.example.lyrics'
170
173
  expect(item.uri).to eq 'lyrics.json'
171
174
  end
175
+
176
+ it 'should parse encrypted playlist' do
177
+ file = File.open 'spec/fixtures/encrypted.m3u8'
178
+ reader = M3u8::Reader.new
179
+ playlist = reader.read file
180
+
181
+ expect(playlist.items.size).to eq 6
182
+
183
+ item = playlist.items[0]
184
+ expect(item).to be_a M3u8::KeyItem
185
+ expect(item.method).to eq 'AES-128'
186
+ expect(item.uri).to eq 'https://priv.example.com/key.php?r=52'
187
+ end
172
188
  end
@@ -97,20 +97,28 @@ describe M3u8::Writer do
97
97
  writer.write playlist
98
98
  expect(io.string).to eq output
99
99
 
100
+ options = { method: 'AES-128', uri: 'http://test.key',
101
+ iv: 'D512BBF', key_format: 'identity',
102
+ key_format_versions: '1/3' }
103
+ item = M3u8::KeyItem.new options
104
+ playlist.items.push item
105
+
100
106
  options = { duration: 11.261233, segment: '1080-7mbps00001.ts' }
101
107
  item = M3u8::SegmentItem.new options
102
108
  playlist.items.push item
103
109
 
104
110
  output = "#EXTM3U\n" \
105
- "#EXT-X-VERSION:3\n" \
106
- "#EXT-X-MEDIA-SEQUENCE:0\n" \
107
- "#EXT-X-ALLOW-CACHE:YES\n" \
108
- "#EXT-X-TARGETDURATION:10\n" \
109
- "#EXTINF:11.344644,\n" \
110
- "1080-7mbps00000.ts\n" \
111
- "#EXTINF:11.261233,\n" \
112
- "1080-7mbps00001.ts\n" \
113
- "#EXT-X-ENDLIST\n"
111
+ "#EXT-X-VERSION:3\n" \
112
+ "#EXT-X-MEDIA-SEQUENCE:0\n" \
113
+ "#EXT-X-ALLOW-CACHE:YES\n" \
114
+ "#EXT-X-TARGETDURATION:10\n" \
115
+ "#EXTINF:11.344644,\n" \
116
+ "1080-7mbps00000.ts\n" +
117
+ %(#EXT-X-KEY:METHOD=AES-128,URI="http://test.key",) +
118
+ %(IV=D512BBF,KEYFORMAT="identity",KEYFORMATVERSIONS="1/3"\n) +
119
+ "#EXTINF:11.261233,\n" +
120
+ "1080-7mbps00001.ts\n" \
121
+ "#EXT-X-ENDLIST\n"
114
122
  io = StringIO.open
115
123
  writer = M3u8::Writer.new io
116
124
  writer.write playlist
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: m3u8
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seth Deckard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-10 00:00:00.000000000 Z
11
+ date: 2015-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,7 +70,9 @@ files:
70
70
  - README.md
71
71
  - Rakefile
72
72
  - lib/m3u8.rb
73
+ - lib/m3u8/discontinuity_item.rb
73
74
  - lib/m3u8/error.rb
75
+ - lib/m3u8/key_item.rb
74
76
  - lib/m3u8/media_item.rb
75
77
  - lib/m3u8/playlist.rb
76
78
  - lib/m3u8/playlist_item.rb
@@ -80,6 +82,8 @@ files:
80
82
  - lib/m3u8/version.rb
81
83
  - lib/m3u8/writer.rb
82
84
  - m3u8.gemspec
85
+ - spec/discontinuity_item_spec.rb
86
+ - spec/fixtures/encrypted.m3u8
83
87
  - spec/fixtures/iframes.m3u8
84
88
  - spec/fixtures/master.m3u8
85
89
  - spec/fixtures/master_iframes.m3u8
@@ -88,6 +92,7 @@ files:
88
92
  - spec/fixtures/session_data.m3u8
89
93
  - spec/fixtures/variant_angles.m3u8
90
94
  - spec/fixtures/variant_audio.m3u8
95
+ - spec/key_item_spec.rb
91
96
  - spec/m3u8_spec.rb
92
97
  - spec/media_item_spec.rb
93
98
  - spec/playlist_item_spec.rb
@@ -122,6 +127,8 @@ signing_key:
122
127
  specification_version: 4
123
128
  summary: Generate and parse m3u8 playlists for HTTP Live Streaming (HLS).
124
129
  test_files:
130
+ - spec/discontinuity_item_spec.rb
131
+ - spec/fixtures/encrypted.m3u8
125
132
  - spec/fixtures/iframes.m3u8
126
133
  - spec/fixtures/master.m3u8
127
134
  - spec/fixtures/master_iframes.m3u8
@@ -130,6 +137,7 @@ test_files:
130
137
  - spec/fixtures/session_data.m3u8
131
138
  - spec/fixtures/variant_angles.m3u8
132
139
  - spec/fixtures/variant_audio.m3u8
140
+ - spec/key_item_spec.rb
133
141
  - spec/m3u8_spec.rb
134
142
  - spec/media_item_spec.rb
135
143
  - spec/playlist_item_spec.rb