# Public: Asynchronsoly downloads .m3u8 playlist files from specified URLs. # # # Examples # # Spider.new(["http://host.tld/video1/playlist_1.m3u8", "http://host.tld/video1/playlist_2.m3u8"]) # # => # # # Spider.new("http://host.tld/video1/parent_playlist.m3u8") # # => # module HLSpider class Spider class InvalidPlaylist < StandardError; end; # Public: Gets Array of urls. attr_reader :urls # Public: Gets Array of valid playlists. attr_reader :playlists # Public: Initialize a Playlist Spider. # # urls - An Array containing multiple String urls to playlist files. # Also accepts single String url that points to parent playlist. def initialize(urls) @urls = Array(urls) end # Public: Starts the download of Array urls # # # Examples # # crawl # # => [#, #] # # Returns Array of Playlists def crawl! @playlists = dive(@urls) end # Public: Checks if playlists' segments are aligned. # # # Examples # # aligned? # # => true # # Returns Boolean. def aligned? last_segments.uniq.size == 1 end # Public: playlist getter. # # # Examples # # playlists # # => [#, #] # # Returns Array of Playlists def playlists @playlists ||= crawl! end # Public: Get Array of last segments across playlists. # # # Examples # # last_segments # # => ['video_05.ts', 'video_05.ts', 'video_05.ts'] # # Returns Array of Strings def last_segments playlists.collect { |p| p.media_sequence } end private include Downloader # Internal: Download playlists from Array urls. # # # Examples # # dive(["http://host.tld/video1/playlist_1.m3u8", "http://host.tld/video1/playlist_2.m3u8"]) # # => [#, #] # # Returns Array of Playlists. # Raises HLSpider::Spider::InvalidPlaylist if an invalid playlist is downloaded. def dive(urls = []) playlists = [] responses = download(urls) responses.each do |response| playlist = Playlist.new(response.body, response.url) if playlist.valid? if playlist.variable_playlist? playlists << dive(playlist.playlists) else playlists << playlist end else raise InvalidPlaylist, "#{playlist.source} was an invalid playlist." end end playlists.flatten end end end