def variant_m3u8(self, cid=None, r=None, tag=None, **kwargs): """ Special endpoint for shaping direct variqnt playlists""" seeded_content_id = conf.common.get_seeded_cid(cid) fake_master_playlist_url = "" fake_master_playlist = """ #EXTM3U #EXT-X-VERSION:2 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=0,RESOLUTION=0x0 {0} """.format( conf.data.provider.master_m3u8_url(cid, kwargs) ) varient_playlists = httpls_client.get_variant_playlist_urls(fake_master_playlist, fake_master_playlist_url) rules = shaper.parse_hls_rules(r, varient_playlists) info = shaper.hls_cache_and_shape(fake_master_playlist, seeded_content_id, rules, fake_master_playlist_url) info["url"] = conf.common.get_final_url("playlist.m3u8","p=m_{0}".format(seeded_content_id)) # if we have a tag, store if tag: self.store_tag(cid, r, tag, kwargs) cached_cid = info['variants'][info['variants'].keys()[0]] with open("{0}/playlists/m_{1}.m3u8".format(shaper.shaper_store_path, cached_cid), "r") as pf: master_content = pf.read() # return the rewritten master cherrypy.response.headers['Content-Type'] = "application/vnd.apple.mpegurl" cherrypy.response.headers['Content-Disposition'] = "inline; filename={0}.m3u8".format(cid) cherrypy.response.headers['Last-Modified'] = httputil.HTTPDate() return master_content
def test_hls_segment_rule_match_vplaylist(self): v_playlists_desc = httpls_client.get_variant_playlist_urls(self.master_playlist) p4000k = next( v_playlists_desc["4000000"].itervalues()) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("4000k~e404"), p4000k, p4000k) != None ) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("650k~e404"), p4000k, p4000k) == None ) master_cdn_playlist = open(self.test_path + "/wt_suite/basic/wt_master_cdn_fallback.m3u8","r").read() v_playlists_cdn_desc = httpls_client.get_variant_playlist_urls(master_cdn_playlist) p4000k_a = v_playlists_cdn_desc["4000000"]["a"] self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("b.4000k~e404"), p4000k_a, p4000k_a) == None ) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("a.4000k~e404"), p4000k_a, p4000k_a) != None ) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("4000k~e404"), p4000k_a, p4000k_a) != None ) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("*~e404"), p4000k_a, p4000k_a) != None ) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("1000k.s0~e404,1000k~e500"), self.v_playlist_1000k, self.v_playlist_1000k) != None )
def test_pull_master_playlist(self): master_playlist = open(self.test_path + "/wt_suite/wt_dripls/wt.m3u8","r").read() v_playlists = httpls_client.get_variant_playlist_urls(master_playlist) #test with a master playlist c = 0 for bandwidth in v_playlists.iterkeys(): for cdn in v_playlists[bandwidth].iterkeys(): self.assertTrue(v_playlists[bandwidth][cdn]["type"] == "vplaylist") self.assertTrue(v_playlists[bandwidth][cdn]["url"] != None) c += 1 self.assertTrue( c > 0) # test with a non-master playlist not_master_playlist = open(self.test_path + "/wt_suite/wt_dripls/wt_1700k.m3u8","r").read() v_playlists = httpls_client.get_variant_playlist_urls(not_master_playlist) for bandwidth in v_playlists.iterkeys(): for cdn in v_playlists[bandwidth].iterkeys(): self.fail("found a variable playlist inside a vplaylist") return
def test_hls_segment_rule_match_vplaylist(self): v_playlists_desc = httpls_client.get_variant_playlist_urls( self.master_playlist) p4000k = next(v_playlists_desc["4000000"].itervalues()) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("4000k~e404"), p4000k, p4000k) != None) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("650k~e404"), p4000k, p4000k) == None) master_cdn_playlist = open( self.test_path + "/wt_suite/basic/wt_master_cdn_fallback.m3u8", "r").read() v_playlists_cdn_desc = httpls_client.get_variant_playlist_urls( master_cdn_playlist) p4000k_a = v_playlists_cdn_desc["4000000"]["a"] self.assertTrue( shaper.hls_segment_rule_match( shaper.parse_hls_rules("b.4000k~e404"), p4000k_a, p4000k_a) == None) self.assertTrue( shaper.hls_segment_rule_match( shaper.parse_hls_rules("a.4000k~e404"), p4000k_a, p4000k_a) != None) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("4000k~e404"), p4000k_a, p4000k_a) != None) self.assertTrue( shaper.hls_segment_rule_match(shaper.parse_hls_rules("*~e404"), p4000k_a, p4000k_a) != None) self.assertTrue( shaper.hls_segment_rule_match( shaper.parse_hls_rules("1000k.s0~e404,1000k~e500"), self.v_playlist_1000k, self.v_playlist_1000k) != None)
def hls_cache_and_shape(master_playlist, seeded_content_id, rules, master_playlist_url = ''): """Returns shaped m3u8 playlist Process and shape a m3u8 playlist based on a set of rules """ shape_info = {} shape_info["id"] = seeded_content_id shape_info["variants"] = {} shape_port_session = {} variant_playlists = httpls_client.get_variant_playlist_urls(master_playlist, master_playlist_url) for bitrate in variant_playlists.iterkeys(): for alt in variant_playlists[bitrate].iterkeys(): variant_playlist_desc = variant_playlists[bitrate][alt] variant_playlist = httpls_client.pull_variant_playlist( variant_playlist_desc["url"]) # perform rewrite on the variant playlist url to local url or a rule matched url seg_rewrite_url = hls_segment_rule_rewrite(rules, variant_playlist_desc, variant_playlist_desc, shape_port_session) local_rewrite_url = conf.common.get_final_url("playlist.m3u8","p=m_{0}_{1}_{2}".format(seeded_content_id, bitrate, alt)) shape_info["variants"]["{0}_{1}".format(bitrate, alt)] = "{0}_{1}_{2}".format(seeded_content_id, bitrate, alt) master_playlist = httpls_client.switch_segment( master_playlist, variant_playlist_desc["original_url"], seg_rewrite_url if seg_rewrite_url else local_rewrite_url ) # don't process a playlist if it hit a rule (ie has been errored out) if seg_rewrite_url: shape_info["{0}.{1}".format(bitrate, alt)] = seg_rewrite_url continue # perform rule rewrite on segments within the variant playlist for s in variant_playlist["segments"].iterkeys(): seg_rewrite_url = hls_segment_rule_rewrite(rules, variant_playlist_desc, variant_playlist["segments"][s], shape_port_session) # rewrite local to full url playlist if variant_playlist["segments"][s]["original_url"] != variant_playlist["segments"][s]["url"]: variant_playlist["content"] = httpls_client.switch_segment(variant_playlist["content"], variant_playlist["segments"][s]["original_url"], variant_playlist["segments"][s]["url"]) # replace segment with shaped url if seg_rewrite_url: variant_playlist["content"] = httpls_client.switch_segment(variant_playlist["content"], variant_playlist["segments"][s]["url"], seg_rewrite_url) variant_playlist["segments"][s]["url"] = seg_rewrite_url shape_info["{0}.{1}.s{2}".format( bitrate, alt, s)] = seg_rewrite_url httpls_client.store_playlist(variant_playlist["content"], shaper_store_path + "playlists/m_{0}_{1}_{2}.m3u8".format(seeded_content_id, bitrate, alt)) shape_port_session = {} httpls_client.store_playlist(master_playlist, shaper_store_path + "playlists/m_{0}.m3u8".format(seeded_content_id)) return shape_info
def test_switch_segment(self): # test switch with master playlist master_playlist = open(self.test_path + "/wt_suite/wt_dripls/wt.m3u8","r").read() v_playlists = httpls_client.get_variant_playlist_urls(master_playlist) c = 0 for bandwidth in v_playlists.iterkeys(): for cdn in v_playlists[bandwidth].iterkeys(): c += 1 replace_segment = "http://testsegment" + str(c) master_playlist = httpls_client.switch_segment(master_playlist, v_playlists[bandwidth][cdn]["url"], replace_segment) self.assertTrue( master_playlist.find(v_playlists[bandwidth][cdn]["url"]) == -1 ) self.assertTrue( master_playlist.find( replace_segment) != -1 ) variant_playlist = open(self.test_path + "/wt_suite/wt_dripls/wt_1700k.m3u8","r").read() return
def cache_stream(self, cid=None, r=None, tag=None, kwargs=None): """ Perform the actual caching and shaping of the stream """ seeded_content_id = conf.common.get_seeded_cid(cid) master_playlist_url = conf.data.provider.master_m3u8_url(cid, kwargs) master_playlist = conf.data.provider.pull_master_m3u8(cid, kwargs) varient_playlists = httpls_client.get_variant_playlist_urls(master_playlist, master_playlist_url) rules = shaper.parse_hls_rules(r, varient_playlists) info = shaper.hls_cache_and_shape(master_playlist, seeded_content_id, rules, master_playlist_url) info["url"] = conf.common.get_final_url("playlist.m3u8","p=m_{0}".format(seeded_content_id)) # if we have a tag, store if tag: self.store_tag(cid, r, tag, kwargs) return info