lib/m3uzi.rb in m3uzi-0.4.3 vs lib/m3uzi.rb in m3uzi-0.5.0
- old
+ new
@@ -7,18 +7,22 @@
require 'm3uzi/version'
class M3Uzi
attr_accessor :header_tags, :playlist_items
- attr_accessor :final_media_file
- attr_accessor :version
+ attr_accessor :playlist_type, :final_media_file
+ attr_accessor :version, :initial_media_sequence, :sliding_window_duration
def initialize
@header_tags = {}
@playlist_items = []
@final_media_file = true
@version = 1
+ @initial_media_sequence = 0
+ @sliding_window_duration = nil
+ @removed_file_count = 0
+ @playlist_type = :live
end
#-------------------------------------
# Read/Write M3U8 Files
@@ -72,10 +76,12 @@
reset_byterange_history
check_version_restrictions
io_stream << "#EXTM3U\n"
io_stream << "#EXT-X-VERSION:#{@version.to_i}\n" if @version > 1
+ io_stream << "#EXT-X-MEDIA-SEQUENCE:#{@initial_media_sequence+@removed_file_count}\n" if @playlist_type == :live
+ io_stream << "#EXT-X-PLAYLIST-TYPE:#{@playlist_type.to_s.upcase}\n" if [:event,:vod].include?(@playlist_type)
if items(File).length > 0
max_duration = valid_items(File).map { |f| f.duration.to_f }.max || 10.0
io_stream << "#EXT-X-TARGETDURATION:#{max_duration.ceil}\n"
end
@@ -96,11 +102,11 @@
end
io_stream << (item.format + "\n")
end
- io_stream << "#EXT-X-ENDLIST\n" if items(File).length > 0 && @final_media_file
+ io_stream << "#EXT-X-ENDLIST\n" if items(File).length > 0 && (@final_media_file || @playlist_type == :vod)
end
def write(path)
::File.open(path, "w") { |f| write_to_io(f) }
end
@@ -190,10 +196,11 @@
new_file = M3Uzi::File.new
new_file.path = path if path
new_file.duration = duration if duration
yield(new_file) if block_given?
@playlist_items << new_file
+ cleanup_sliding_window
end
def filenames
items(File).map { |file| file.path }
end
@@ -320,9 +327,22 @@
#
# def self.parse_stream_tag(line)
# match = line.match(/^#EXT-X-STREAM-INF:(.*)$/)[1]
# match.scan(/([A-Z-]+)\s*=\s*("[^"]*"|[^,]*)/) # return attributes as array of arrays
# end
+
+ def cleanup_sliding_window
+ return unless @sliding_window_duration && @playlist_type == :live
+ while total_duration > @sliding_window_duration
+ first_file = @playlist_items.detect { |item| item.kind_of?(File) && item.valid? }
+ @playlist_items.delete(first_file)
+ @removed_file_count += 1
+ end
+ end
+
+ def total_duration
+ valid_items(File).inject(0.0) { |d,f| d + f.duration.to_f }
+ end
def self.format_iv(num)
'0x' + num.to_s(16).rjust(32,'0')
end