diff --git a/- COMANDS -.txt b/- COMANDS -.txt new file mode 100644 index 0000000..5d9c64e --- /dev/null +++ b/- COMANDS -.txt @@ -0,0 +1,40 @@ +Proxy en cofig: +set https_proxy=https://IP:PORT + +..:: NETFLIX ::.. + +* Download MOVIE 1080p + AUDIO + SUBS: +python netflix.py -t TITLE -q X -a en,es -o X + +* Download SERIES 1080p + AUDIO + SUBS: +python netflix.py -t TITLE -q X -s X -a en,es +python netflix.py -t TITLE -q X -s X -e XX -a en,es + +..:: COMANDS ::.. + +-q X = Quality 720p or 1080p +-o X = Tittle movie " EXAMPLE.MOVIE.2018 " Only put comand in movies +-s X = Season select +-e XX = Episode select + +-a en,es = Select audio: +English: 'en' +French: 'fr' +German: 'de' +Italian: 'it' +Spanish: 'es' +Flemish: 'nl-BE' +Finnish: 'fi' +No Dialogue: 'zxx' +Czech: 'cs' +European Spanish: 'es-ES' +Japanese: 'ja' +Brazilian Portuguese: 'pt-BR' +Polish: 'pl' +Turkish: 'tr' +Mandarin: 'zh' +Cantonese: 'yue' +Arabic: 'ar' +Korean: 'ko' +Hebrew: 'he' +Norwegian: 'nb' \ No newline at end of file diff --git a/MyFrame.py b/MyFrame.py new file mode 100644 index 0000000..3ad16ac --- /dev/null +++ b/MyFrame.py @@ -0,0 +1,719 @@ +# -*- coding: utf-8 -*- + +########################################################################### +## Python code generated with wxFormBuilder (version Oct 26 2018) +## http://www.wxformbuilder.org/ +## +## PLEASE DO *NOT* EDIT THIS FILE! +########################################################################### + +import wx +import wx.xrc +import subprocess +import threading +import sys +import os + +########################################################################### +## Class MyFrame +########################################################################### + +class MyFrame ( wx.Frame ): + + def __init__( self, parent ): + wx.Frame.__init__ ( self,parent,id = -1,title='',pos = wx.Point(1,1),size = wx.Size(740,740),style = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX,name = 'frame' ) + + self.SetTitle('NFTool Gui by flix88') + self.Show(False) + + self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) + + + #codec + self.chc54c = wx.Choice(self,-1,wx.Point(10,30),wx.Size(120,41),[r'H264',r'HEVC',r'HDR']) + self.chc54c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + + #reslution + self.chc64c = wx.Choice(self,-1,wx.Point(150,30),wx.Size(120,41),[r'SD',r'720p',r'1080p']) + self.chc64c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + + + #series + + self.chc74c = wx.Choice(self,-1,wx.Point(290,30),wx.Size(120,41),[r'1',r'2',r'3',r'4',r'5',r'6',r'7',r'8',r'9',r'10',r'11',r'12',r'13',r'14',r'15',r'16',r'17',r'18',r'19',r'20']) + self.chc74c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + + + #episode + + self.chc84c = wx.Choice(self,-1,wx.Point(420,30),wx.Size(120,41),[r'1',r'2',r'3',r'4',r'5',r'6',r'7',r'8',r'9',r'10',r'11',r'12',r'13',r'14',r'15',r'16',r'17',r'18',r'19',r'20']) + self.chc84c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + + + #audio + self.lc7c = wx.CheckListBox(self,-1,wx.Point(550,30),wx.Size(120,120),[r'de',r'en',r'es-ES',r'es',r'fr',r'it',r'ja',r'pl',r'pt-BR',r'ru',r'tr',r'nl-BE',r'nb',r'fi',r'cs',r'zh',r'yue',r'ko',r'ar',r'he',r'zxx']) + + + self.st64c = wx.StaticText(self,-1,"",wx.Point(50,10),wx.Size(104,20),wx.ST_NO_AUTORESIZE) + self.st64c.SetLabel("Codec") + self.st64c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.st74c = wx.StaticText(self,-1,"",wx.Point(180,10),wx.Size(104,20),wx.ST_NO_AUTORESIZE) + self.st74c.SetLabel("Resolution") + self.st74c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.st84c = wx.StaticText(self,-1,"",wx.Point(330,10),wx.Size(104,20),wx.ST_NO_AUTORESIZE) + self.st84c.SetLabel("Series") + self.st84c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.st94c = wx.StaticText(self,-1,"",wx.Point(455,10),wx.Size(104,20),wx.ST_NO_AUTORESIZE) + self.st94c.SetLabel("Episode") + self.st94c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.st54c = wx.StaticText(self,-1,"",wx.Point(590,10),wx.Size(104,20),wx.ST_NO_AUTORESIZE) + self.st54c.SetLabel("Audio") + self.st54c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.st44c = wx.StaticText(self,-1,"",wx.Point(50,65),wx.Size(104,15),wx.ST_NO_AUTORESIZE) + self.st44c.SetLabel("Url") + self.st44c.SetFont(wx.Font(9,74,90,90,0,"Tahoma")) + + + self.txm17c = wx.TextCtrl(self,-1,"",wx.Point(10,85),wx.Size(320,55),wx.TE_MULTILINE) + self.txm17c.SetFont(wx.Font(11,74,90,90,0,"Tahoma")) + + self.txm23c = wx.TextCtrl(self,-1,"",wx.Point(10,155),wx.Size(660,450),wx.FULL_REPAINT_ON_RESIZE|wx.VSCROLL|wx.HSCROLL|wx.TE_MULTILINE) + self.txm23c.SetFont(wx.Font(10,74,90,90,0,"Tahoma")) + + + + + self.bt55c = wx.Button(self,-1,"",wx.Point(10,620),wx.Size(150,60)) + self.bt55c.SetLabel("Download") + self.bt55c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + self.Bind(wx.EVT_BUTTON,self.bt55c_VwXEvOnButtonClick,self.bt55c) + + self.bt65c = wx.Button(self,-1,"",wx.Point(180,620),wx.Size(150,60)) + self.bt65c.SetLabel("Playlist") + self.bt65c.SetFont(wx.Font(12,74,90,90,0,"Tahoma")) + self.Bind(wx.EVT_BUTTON,self.bt65c_VwXEvOnButtonClick,self.bt65c) + + + self.ck66c = wx.CheckBox(self,-1,"",wx.Point(470,80),wx.Size(18,21)) + self.st66c = wx.StaticText(self,-1,"",wx.Point(460,60),wx.Size(90,22),wx.ST_NO_AUTORESIZE) + self.st66c.SetLabel("Debug") + + + #self.SetSizer( bSizer2 ) + self.Layout() + + self.Centre( wx.BOTH ) + + + def __del__( self ): + pass + + + def get_playlist(self, event): + + if self.chc54c.GetSelection() == 0: + #self.txm23c.SetValue('h264') + codec = 'h264' + if self.chc54c.GetSelection() == 1: + #self.txm23c.SetValue('hevc') + codec = 'hevc' + if self.chc54c.GetSelection() == 2: + #self.txm23c.SetValue('hdr') + codec = 'hdr' + + if self.chc64c.GetSelection() == 0: + #self.txm23c.SetValue('sd') + res = 'sd' + if self.chc64c.GetSelection() == 1: + #self.txm23c.SetValue('720p') + res = '720p' + if self.chc64c.GetSelection() == 2: + #self.txm23c.SetValue('1080p') + res = '1080p' + + if self.chc74c.GetSelection() == 0: + #self.txm23c.SetValue('1') + series = '1' + if self.chc74c.GetSelection() == 1: + #self.txm23c.SetValue('2') + series = '2' + if self.chc74c.GetSelection() == 2: + #self.txm23c.SetValue('3') + series = '3' + if self.chc74c.GetSelection() == 3: + #self.txm23c.SetValue('4') + series = '4' + if self.chc74c.GetSelection() == 4: + #self.txm23c.SetValue('5') + series = '5' + if self.chc74c.GetSelection() == 5: + #self.txm23c.SetValue('6') + series = '6' + if self.chc74c.GetSelection() == 6: + #self.txm23c.SetValue('7') + series = '7' + if self.chc74c.GetSelection() == 7: + #self.txm23c.SetValue('8') + series = '8' + if self.chc74c.GetSelection() == 8: + #self.txm23c.SetValue('9') + series = '9' + if self.chc74c.GetSelection() == 9: + #self.txm23c.SetValue('10') + series = '10' + if self.chc74c.GetSelection() == 10: + #self.txm23c.SetValue('11') + series = '11' + if self.chc74c.GetSelection() == 11: + #self.txm23c.SetValue('12') + series = '12' + if self.chc74c.GetSelection() == 12: + #self.txm23c.SetValue('13') + series = '13' + if self.chc74c.GetSelection() == 13: + #self.txm23c.SetValue('14') + series = '14' + if self.chc74c.GetSelection() == 14: + #self.txm23c.SetValue('15') + series = '15' + if self.chc74c.GetSelection() == 15: + #self.txm23c.SetValue('16') + series = '16' + if self.chc74c.GetSelection() == 16: + #self.txm23c.SetValue('17') + series = '17' + if self.chc74c.GetSelection() == 17: + #self.txm23c.SetValue('18') + series = '18' + if self.chc74c.GetSelection() == 18: + #self.txm23c.SetValue('19') + series = '19' + if self.chc74c.GetSelection() == 19: + #self.txm23c.SetValue('20') + series = '20' + + + if self.chc84c.GetSelection() == 0: + #self.txm23c.SetValue('1') + episode = '1' + if self.chc84c.GetSelection() == 1: + #self.txm23c.SetValue('2') + episode = '2' + if self.chc84c.GetSelection() == 2: + #self.txm23c.SetValue('3') + episode = '3' + if self.chc84c.GetSelection() == 3: + #self.txm23c.SetValue('4') + episode = '4' + if self.chc84c.GetSelection() == 4: + #self.txm23c.SetValue('5') + episode = '5' + if self.chc84c.GetSelection() == 5: + #self.txm23c.SetValue('6') + episode = '6' + if self.chc84c.GetSelection() == 6: + #self.txm23c.SetValue('7') + episode = '7' + if self.chc84c.GetSelection() == 7: + #self.txm23c.SetValue('8') + episode = '8' + if self.chc84c.GetSelection() == 8: + #self.txm23c.SetValue('9') + episode = '9' + if self.chc84c.GetSelection() == 9: + #self.txm23c.SetValue('10') + episode = '10' + if self.chc84c.GetSelection() == 10: + #self.txm23c.SetValue('11') + episode = '11' + if self.chc84c.GetSelection() == 11: + #self.txm23c.SetValue('12') + episode = '12' + if self.chc84c.GetSelection() == 12: + #self.txm23c.SetValue('13') + episode = '13' + if self.chc84c.GetSelection() == 13: + #self.txm23c.SetValue('14') + episode = '14' + if self.chc84c.GetSelection() == 14: + #self.txm23c.SetValue('15') + episode = '15' + if self.chc84c.GetSelection() == 15: + #self.txm23c.SetValue('16') + episode = '16' + if self.chc84c.GetSelection() == 16: + #self.txm23c.SetValue('17') + episode = '17' + if self.chc84c.GetSelection() == 17: + #self.txm23c.SetValue('18') + episode = '18' + if self.chc84c.GetSelection() == 18: + #self.txm23c.SetValue('19') + episode = '19' + if self.chc84c.GetSelection() == 19: + #self.txm23c.SetValue('20') + episode = '20' + + audio = [] + #self.txm23c.SetValue(str(self.lc7c.GetCheckedItems())) + if self.lc7c.IsChecked(0): + audio.append('de') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(1): + audio.append('en') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(2): + audio.append('es-ES') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(3): + audio.append('es') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(4): + audio.append('fr') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(5): + audio.append('it') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(6): + audio.append('ja') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(7): + audio.append('pl') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(8): + audio.append('pt-BR') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(9): + audio.append('ru') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(10): + audio.append('tr') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(11): + audio.append('nl-BE') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(12): + audio.append('nb') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(13): + audio.append('fi') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(14): + audio.append('cs') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(15): + audio.append('zh') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(16): + audio.append('yue') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(17): + audio.append('ko') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(18): + audio.append('ar') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(19): + audio.append('he') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(20): + audio.append('zxx') + #self.txm23c.SetValue(str(audio)) + print(audio) + + #cmd = "python netflix.py -t 80149092 -q sd -p h264 -a de" + cmd = "python netflix.py -i" + if self.ck66c.IsChecked(): + cmd1 = " -d" + else: + cmd1 = "" + #https://www.netflix.com/de/title/80200571 + title = self.txm17c.GetValue() + + cmd0 = title.split('title/') + cmd0 = " -t " + cmd0[1] + cmd2 = " -p " + codec + cmd3 = " -q " + res + cmd4 = " -a " + ','.join(audio) + + se = self.chc74c.GetSelection() + ep = self.chc84c.GetSelection() + + if se == -1 and ep == -1: + cmd5 = "" + + if se >= 0 and ep == -1: + cmd5 = " -s " + series + + if se >= 0 and ep >= 0: + cmd5 = " -s " + series + " -e " + episode + + cmdd = cmd + cmd0 + cmd2 + cmd3 + cmd1 + cmd4 + cmd5 + print(cmdd) + + popenobj = subprocess.Popen(cmdd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + while not popenobj.poll(): + stdoutdata = popenobj.stdout.readline() + if stdoutdata: + #sys.stdout.write(stdoutdata.decode('cp1252')) + wx.CallAfter(self.txm23c.AppendText, stdoutdata.decode('cp1252').encode('utf-8')) + else: + break + print("Return code", popenobj.returncode) + + + + def get_download(self, event): + + if self.chc54c.GetSelection() == 0: + #self.txm23c.SetValue('h264') + codec = 'h264' + if self.chc54c.GetSelection() == 1: + #self.txm23c.SetValue('hevc') + codec = 'hevc' + if self.chc54c.GetSelection() == 2: + #self.txm23c.SetValue('hdr') + codec = 'hdr' + + if self.chc64c.GetSelection() == 0: + #self.txm23c.SetValue('sd') + res = 'sd' + if self.chc64c.GetSelection() == 1: + #self.txm23c.SetValue('720p') + res = '720p' + if self.chc64c.GetSelection() == 2: + #self.txm23c.SetValue('1080p') + res = '1080p' + + if self.chc74c.GetSelection() == 0: + #self.txm23c.SetValue('1') + series = '1' + if self.chc74c.GetSelection() == 1: + #self.txm23c.SetValue('2') + series = '2' + if self.chc74c.GetSelection() == 2: + #self.txm23c.SetValue('3') + series = '3' + if self.chc74c.GetSelection() == 3: + #self.txm23c.SetValue('4') + series = '4' + if self.chc74c.GetSelection() == 4: + #self.txm23c.SetValue('5') + series = '5' + if self.chc74c.GetSelection() == 5: + #self.txm23c.SetValue('6') + series = '6' + if self.chc74c.GetSelection() == 6: + #self.txm23c.SetValue('7') + series = '7' + if self.chc74c.GetSelection() == 7: + #self.txm23c.SetValue('8') + series = '8' + if self.chc74c.GetSelection() == 8: + #self.txm23c.SetValue('9') + series = '9' + if self.chc74c.GetSelection() == 9: + #self.txm23c.SetValue('10') + series = '10' + if self.chc74c.GetSelection() == 10: + #self.txm23c.SetValue('11') + series = '11' + if self.chc74c.GetSelection() == 11: + #self.txm23c.SetValue('12') + series = '12' + if self.chc74c.GetSelection() == 12: + #self.txm23c.SetValue('13') + series = '13' + if self.chc74c.GetSelection() == 13: + #self.txm23c.SetValue('14') + series = '14' + if self.chc74c.GetSelection() == 14: + #self.txm23c.SetValue('15') + series = '15' + if self.chc74c.GetSelection() == 15: + #self.txm23c.SetValue('16') + series = '16' + if self.chc74c.GetSelection() == 16: + #self.txm23c.SetValue('17') + series = '17' + if self.chc74c.GetSelection() == 17: + #self.txm23c.SetValue('18') + series = '18' + if self.chc74c.GetSelection() == 18: + #self.txm23c.SetValue('19') + series = '19' + if self.chc74c.GetSelection() == 19: + #self.txm23c.SetValue('20') + series = '20' + + + if self.chc84c.GetSelection() == 0: + #self.txm23c.SetValue('1') + episode = '1' + if self.chc84c.GetSelection() == 1: + #self.txm23c.SetValue('2') + episode = '2' + if self.chc84c.GetSelection() == 2: + #self.txm23c.SetValue('3') + episode = '3' + if self.chc84c.GetSelection() == 3: + #self.txm23c.SetValue('4') + episode = '4' + if self.chc84c.GetSelection() == 4: + #self.txm23c.SetValue('5') + episode = '5' + if self.chc84c.GetSelection() == 5: + #self.txm23c.SetValue('6') + episode = '6' + if self.chc84c.GetSelection() == 6: + #self.txm23c.SetValue('7') + episode = '7' + if self.chc84c.GetSelection() == 7: + #self.txm23c.SetValue('8') + episode = '8' + if self.chc84c.GetSelection() == 8: + #self.txm23c.SetValue('9') + episode = '9' + if self.chc84c.GetSelection() == 9: + #self.txm23c.SetValue('10') + episode = '10' + if self.chc84c.GetSelection() == 10: + #self.txm23c.SetValue('11') + episode = '11' + if self.chc84c.GetSelection() == 11: + #self.txm23c.SetValue('12') + episode = '12' + if self.chc84c.GetSelection() == 12: + #self.txm23c.SetValue('13') + episode = '13' + if self.chc84c.GetSelection() == 13: + #self.txm23c.SetValue('14') + episode = '14' + if self.chc84c.GetSelection() == 14: + #self.txm23c.SetValue('15') + episode = '15' + if self.chc84c.GetSelection() == 15: + #self.txm23c.SetValue('16') + episode = '16' + if self.chc84c.GetSelection() == 16: + #self.txm23c.SetValue('17') + episode = '17' + if self.chc84c.GetSelection() == 17: + #self.txm23c.SetValue('18') + episode = '18' + if self.chc84c.GetSelection() == 18: + #self.txm23c.SetValue('19') + episode = '19' + if self.chc84c.GetSelection() == 19: + #self.txm23c.SetValue('20') + episode = '20' + + audio = [] + #self.txm23c.SetValue(str(self.lc7c.GetCheckedItems())) + if self.lc7c.IsChecked(0): + audio.append('de') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(1): + audio.append('en') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(2): + audio.append('es-ES') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(3): + audio.append('es') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(4): + audio.append('fr') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(5): + audio.append('it') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(6): + audio.append('ja') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(7): + audio.append('pl') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(8): + audio.append('pt-BR') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(9): + audio.append('ru') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(10): + audio.append('tr') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(11): + audio.append('nl-BE') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(12): + audio.append('nb') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(13): + audio.append('fi') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(14): + audio.append('cs') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(15): + audio.append('zh') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(16): + audio.append('yue') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(17): + audio.append('ko') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(18): + audio.append('ar') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(19): + audio.append('he') + #self.txm23c.SetValue(str(audio)) + print(audio) + + if self.lc7c.IsChecked(20): + audio.append('zxx') + #self.txm23c.SetValue(str(audio)) + print(audio) + + #cmd = "python netflix.py -t 80149092 -q sd -p h264 -a de" + cmd = "python netflix.py" + if self.ck66c.IsChecked(): + cmd1 = " -d" + else: + cmd1 = "" + #https://www.netflix.com/de/title/80200571 + title = self.txm17c.GetValue() + + cmd0 = title.split('title/') + cmd0 = " -t " + cmd0[1] + cmd2 = " -p " + codec + cmd3 = " -q " + res + cmd4 = " -a " + ','.join(audio) + + se = self.chc74c.GetSelection() + ep = self.chc84c.GetSelection() + + if se == -1 and ep == -1: + cmd5 = "" + + if se >= 0 and ep == -1: + cmd5 = " -s " + series + + if se >= 0 and ep >= 0: + cmd5 = " -s " + series + " -e " + episode + + cmdd = cmd + cmd0 + cmd2 + cmd3 + cmd1 + cmd4 + cmd5 + print(cmdd) + + popenobj = subprocess.Popen(cmdd, stdout=subprocess.PIPE) + while not popenobj.poll(): + stdoutdata = popenobj.stdout.readline() + if stdoutdata: + #sys.stdout.write(stdoutdata.decode('cp1252')) + wx.CallAfter(self.txm23c.AppendText, stdoutdata.decode('cp1252').encode('utf-8')) + else: + break + print("Return code", popenobj.returncode) + + + def bt65c_VwXEvOnButtonClick(self,event): + + th = threading.Thread(target=self.get_playlist, args=(event,)) + th.start() + return + + def bt55c_VwXEvOnButtonClick(self,event): + + th = threading.Thread(target=self.get_download, args=(event,)) + th.start() + return \ No newline at end of file diff --git a/WEBDL_NF_MOVIE.cmd b/WEBDL_NF_MOVIE.cmd new file mode 100644 index 0000000..9ce17d7 --- /dev/null +++ b/WEBDL_NF_MOVIE.cmd @@ -0,0 +1,3 @@ +python netflix.py -t 80230399 -q 2160p -p hdr +echo. +pause diff --git a/WEBDL_NF_SERIES.bat b/WEBDL_NF_SERIES.bat new file mode 100644 index 0000000..f40fa31 --- /dev/null +++ b/WEBDL_NF_SERIES.bat @@ -0,0 +1,4 @@ +python netflix.py -t 80215488 -q 2160p -p hdr -s 1 -e 1 -a en +echo *** PROCESO FINALIZADO *** +echo. +pause diff --git a/__pycache__/MyFrame.cpython-37.pyc b/__pycache__/MyFrame.cpython-37.pyc new file mode 100644 index 0000000..686deac Binary files /dev/null and b/__pycache__/MyFrame.cpython-37.pyc differ diff --git a/__pycache__/netflix.cpython-36.pyc b/__pycache__/netflix.cpython-36.pyc new file mode 100644 index 0000000..75333c2 Binary files /dev/null and b/__pycache__/netflix.cpython-36.pyc differ diff --git a/addressprotecmac b/addressprotecmac new file mode 100644 index 0000000..2e24b44 --- /dev/null +++ b/addressprotecmac @@ -0,0 +1,108 @@ +important comment=D0-17-C2-95-00-BE + +.vscode/settings.json +binaries/* +cookies/* +output/* +temp/* +pywidevine/clients/*/*config.py + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/binaries/.gitignore b/binaries/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/binaries/Bento4CDll.dll b/binaries/Bento4CDll.dll new file mode 100644 index 0000000..3f3ea2e Binary files /dev/null and b/binaries/Bento4CDll.dll differ diff --git a/binaries/aria2c_nf.exe b/binaries/aria2c_nf.exe new file mode 100644 index 0000000..8f4c73d Binary files /dev/null and b/binaries/aria2c_nf.exe differ diff --git a/binaries/avcodec-58.dll b/binaries/avcodec-58.dll new file mode 100644 index 0000000..b42638a Binary files /dev/null and b/binaries/avcodec-58.dll differ diff --git a/binaries/avcodec.lib b/binaries/avcodec.lib new file mode 100644 index 0000000..0a02e66 Binary files /dev/null and b/binaries/avcodec.lib differ diff --git a/binaries/avconv.exe b/binaries/avconv.exe new file mode 100644 index 0000000..048ec24 Binary files /dev/null and b/binaries/avconv.exe differ diff --git a/binaries/avdevice-57.dll b/binaries/avdevice-57.dll new file mode 100644 index 0000000..a5b3188 Binary files /dev/null and b/binaries/avdevice-57.dll differ diff --git a/binaries/avdevice.lib b/binaries/avdevice.lib new file mode 100644 index 0000000..a7f1046 Binary files /dev/null and b/binaries/avdevice.lib differ diff --git a/binaries/avfilter-7.dll b/binaries/avfilter-7.dll new file mode 100644 index 0000000..7a826ad Binary files /dev/null and b/binaries/avfilter-7.dll differ diff --git a/binaries/avfilter.lib b/binaries/avfilter.lib new file mode 100644 index 0000000..b7ea2bd Binary files /dev/null and b/binaries/avfilter.lib differ diff --git a/binaries/avformat-58.dll b/binaries/avformat-58.dll new file mode 100644 index 0000000..fe90d3a Binary files /dev/null and b/binaries/avformat-58.dll differ diff --git a/binaries/avformat.lib b/binaries/avformat.lib new file mode 100644 index 0000000..3dfdf82 Binary files /dev/null and b/binaries/avformat.lib differ diff --git a/binaries/avplay.exe b/binaries/avplay.exe new file mode 100644 index 0000000..4423068 Binary files /dev/null and b/binaries/avplay.exe differ diff --git a/binaries/avprobe.exe b/binaries/avprobe.exe new file mode 100644 index 0000000..b80e295 Binary files /dev/null and b/binaries/avprobe.exe differ diff --git a/binaries/avresample-4.dll b/binaries/avresample-4.dll new file mode 100644 index 0000000..a2581fd Binary files /dev/null and b/binaries/avresample-4.dll differ diff --git a/binaries/avresample.lib b/binaries/avresample.lib new file mode 100644 index 0000000..e9e9c05 Binary files /dev/null and b/binaries/avresample.lib differ diff --git a/binaries/avutil-56.dll b/binaries/avutil-56.dll new file mode 100644 index 0000000..3570f75 Binary files /dev/null and b/binaries/avutil-56.dll differ diff --git a/binaries/avutil.lib b/binaries/avutil.lib new file mode 100644 index 0000000..b17cc55 Binary files /dev/null and b/binaries/avutil.lib differ diff --git a/binaries/ffmpeg.exe b/binaries/ffmpeg.exe new file mode 100644 index 0000000..84b1819 Binary files /dev/null and b/binaries/ffmpeg.exe differ diff --git a/binaries/ffplay.exe b/binaries/ffplay.exe new file mode 100644 index 0000000..6c532ca Binary files /dev/null and b/binaries/ffplay.exe differ diff --git a/binaries/ffprobe.exe b/binaries/ffprobe.exe new file mode 100644 index 0000000..79c8e3a Binary files /dev/null and b/binaries/ffprobe.exe differ diff --git a/binaries/libbento4.dll b/binaries/libbento4.dll new file mode 100644 index 0000000..e758b68 Binary files /dev/null and b/binaries/libbento4.dll differ diff --git a/binaries/libexpat-1.dll b/binaries/libexpat-1.dll new file mode 100644 index 0000000..6c41904 Binary files /dev/null and b/binaries/libexpat-1.dll differ diff --git a/binaries/libfdk-aac-0.dll b/binaries/libfdk-aac-0.dll new file mode 100644 index 0000000..008f5cf Binary files /dev/null and b/binaries/libfdk-aac-0.dll differ diff --git a/binaries/libgmp-10.dll b/binaries/libgmp-10.dll new file mode 100644 index 0000000..2a16a7a Binary files /dev/null and b/binaries/libgmp-10.dll differ diff --git a/binaries/libgmpxx-4.dll b/binaries/libgmpxx-4.dll new file mode 100644 index 0000000..c22bb7c Binary files /dev/null and b/binaries/libgmpxx-4.dll differ diff --git a/binaries/libjpeg-62.dll b/binaries/libjpeg-62.dll new file mode 100644 index 0000000..629e898 Binary files /dev/null and b/binaries/libjpeg-62.dll differ diff --git a/binaries/libmp3lame-0.dll b/binaries/libmp3lame-0.dll new file mode 100644 index 0000000..1a6a8b5 Binary files /dev/null and b/binaries/libmp3lame-0.dll differ diff --git a/binaries/libogg-0.dll b/binaries/libogg-0.dll new file mode 100644 index 0000000..cf8a8e9 Binary files /dev/null and b/binaries/libogg-0.dll differ diff --git a/binaries/libopencore-amrnb-0.dll b/binaries/libopencore-amrnb-0.dll new file mode 100644 index 0000000..46b9192 Binary files /dev/null and b/binaries/libopencore-amrnb-0.dll differ diff --git a/binaries/libopencore-amrwb-0.dll b/binaries/libopencore-amrwb-0.dll new file mode 100644 index 0000000..339d4c0 Binary files /dev/null and b/binaries/libopencore-amrwb-0.dll differ diff --git a/binaries/libopus-0.dll b/binaries/libopus-0.dll new file mode 100644 index 0000000..f0861bb Binary files /dev/null and b/binaries/libopus-0.dll differ diff --git a/binaries/libpng16-16.dll b/binaries/libpng16-16.dll new file mode 100644 index 0000000..4d0a031 Binary files /dev/null and b/binaries/libpng16-16.dll differ diff --git a/binaries/libturbojpeg-0.dll b/binaries/libturbojpeg-0.dll new file mode 100644 index 0000000..ccab6ca Binary files /dev/null and b/binaries/libturbojpeg-0.dll differ diff --git a/binaries/libvo-aacenc-0.dll b/binaries/libvo-aacenc-0.dll new file mode 100644 index 0000000..b5ea1d9 Binary files /dev/null and b/binaries/libvo-aacenc-0.dll differ diff --git a/binaries/libvo-amrwbenc-0.dll b/binaries/libvo-amrwbenc-0.dll new file mode 100644 index 0000000..180c7d4 Binary files /dev/null and b/binaries/libvo-amrwbenc-0.dll differ diff --git a/binaries/libvorbis-0.dll b/binaries/libvorbis-0.dll new file mode 100644 index 0000000..0f697fe Binary files /dev/null and b/binaries/libvorbis-0.dll differ diff --git a/binaries/libvorbisenc-2.dll b/binaries/libvorbisenc-2.dll new file mode 100644 index 0000000..0e6d965 Binary files /dev/null and b/binaries/libvorbisenc-2.dll differ diff --git a/binaries/libvorbisfile-3.dll b/binaries/libvorbisfile-3.dll new file mode 100644 index 0000000..cffbcc3 Binary files /dev/null and b/binaries/libvorbisfile-3.dll differ diff --git a/binaries/libwebp-4.dll b/binaries/libwebp-4.dll new file mode 100644 index 0000000..3278a07 Binary files /dev/null and b/binaries/libwebp-4.dll differ diff --git a/binaries/libwebpdecoder-0.dll b/binaries/libwebpdecoder-0.dll new file mode 100644 index 0000000..b278e25 Binary files /dev/null and b/binaries/libwebpdecoder-0.dll differ diff --git a/binaries/libwebpdemux-0.dll b/binaries/libwebpdemux-0.dll new file mode 100644 index 0000000..b865484 Binary files /dev/null and b/binaries/libwebpdemux-0.dll differ diff --git a/binaries/libwebpmux-0.dll b/binaries/libwebpmux-0.dll new file mode 100644 index 0000000..7b4a8c2 Binary files /dev/null and b/binaries/libwebpmux-0.dll differ diff --git a/binaries/libx264-142.dll b/binaries/libx264-142.dll new file mode 100644 index 0000000..03d8bdb Binary files /dev/null and b/binaries/libx264-142.dll differ diff --git a/binaries/mkvmerge.exe b/binaries/mkvmerge.exe new file mode 100644 index 0000000..fc45da7 Binary files /dev/null and b/binaries/mkvmerge.exe differ diff --git a/binaries/mkvmerge1.exe b/binaries/mkvmerge1.exe new file mode 100644 index 0000000..ebf3c16 Binary files /dev/null and b/binaries/mkvmerge1.exe differ diff --git a/binaries/mkvmerge2.exe b/binaries/mkvmerge2.exe new file mode 100644 index 0000000..70146a7 Binary files /dev/null and b/binaries/mkvmerge2.exe differ diff --git a/binaries/mp4decrypt.exe b/binaries/mp4decrypt.exe new file mode 100644 index 0000000..4956c22 Binary files /dev/null and b/binaries/mp4decrypt.exe differ diff --git a/binaries/mp4decrypt1.exe b/binaries/mp4decrypt1.exe new file mode 100644 index 0000000..7ed00b4 Binary files /dev/null and b/binaries/mp4decrypt1.exe differ diff --git a/binaries/mp4dump.exe b/binaries/mp4dump.exe new file mode 100644 index 0000000..b2fab16 Binary files /dev/null and b/binaries/mp4dump.exe differ diff --git a/binaries/phantomjs.exe b/binaries/phantomjs.exe new file mode 100644 index 0000000..c644886 Binary files /dev/null and b/binaries/phantomjs.exe differ diff --git a/binaries/swscale-5.dll b/binaries/swscale-5.dll new file mode 100644 index 0000000..883aea8 Binary files /dev/null and b/binaries/swscale-5.dll differ diff --git a/binaries/swscale.lib b/binaries/swscale.lib new file mode 100644 index 0000000..0aa53f9 Binary files /dev/null and b/binaries/swscale.lib differ diff --git a/binaries/versions b/binaries/versions new file mode 100644 index 0000000..6ef6cac --- /dev/null +++ b/binaries/versions @@ -0,0 +1,3 @@ +mp4dump = 1.5.0.614 +phantomjs = 2.1.1 +mkvmerge = 11.0.0-64 \ No newline at end of file diff --git a/binaries/video b/binaries/video new file mode 100644 index 0000000..3771c25 --- /dev/null +++ b/binaries/video @@ -0,0 +1 @@ +generic 20170809T051653-05-1463071 diff --git a/binaries/widevinecdm.dll b/binaries/widevinecdm.dll new file mode 100644 index 0000000..82bec50 Binary files /dev/null and b/binaries/widevinecdm.dll differ diff --git a/binaries/wvDecrypter.rar b/binaries/wvDecrypter.rar new file mode 100644 index 0000000..5867cb5 Binary files /dev/null and b/binaries/wvDecrypter.rar differ diff --git a/binaries/wvDecrypter/challenge.bin b/binaries/wvDecrypter/challenge.bin new file mode 100644 index 0000000..5f74a29 Binary files /dev/null and b/binaries/wvDecrypter/challenge.bin differ diff --git a/binaries/wvDecrypter/libcurl.dll b/binaries/wvDecrypter/libcurl.dll new file mode 100644 index 0000000..dc0c1bb Binary files /dev/null and b/binaries/wvDecrypter/libcurl.dll differ diff --git a/binaries/wvDecrypter/libeay32.dll b/binaries/wvDecrypter/libeay32.dll new file mode 100644 index 0000000..263b705 Binary files /dev/null and b/binaries/wvDecrypter/libeay32.dll differ diff --git a/binaries/wvDecrypter/openssl.exe b/binaries/wvDecrypter/openssl.exe new file mode 100644 index 0000000..858b9c5 Binary files /dev/null and b/binaries/wvDecrypter/openssl.exe differ diff --git a/binaries/wvDecrypter/python36.dll b/binaries/wvDecrypter/python36.dll new file mode 100644 index 0000000..6f1e9e7 Binary files /dev/null and b/binaries/wvDecrypter/python36.dll differ diff --git a/binaries/wvDecrypter/ssleay32.dll b/binaries/wvDecrypter/ssleay32.dll new file mode 100644 index 0000000..32bd92e Binary files /dev/null and b/binaries/wvDecrypter/ssleay32.dll differ diff --git a/binaries/wvDecrypter/widevinecdm.dll b/binaries/wvDecrypter/widevinecdm.dll new file mode 100644 index 0000000..4d8f902 Binary files /dev/null and b/binaries/wvDecrypter/widevinecdm.dll differ diff --git a/binaries/wvDecrypter/wvDecrypter.exe b/binaries/wvDecrypter/wvDecrypter.exe new file mode 100644 index 0000000..f7583a9 Binary files /dev/null and b/binaries/wvDecrypter/wvDecrypter.exe differ diff --git a/binaries/wvdecrypt.exe b/binaries/wvdecrypt.exe new file mode 100644 index 0000000..e941e00 Binary files /dev/null and b/binaries/wvdecrypt.exe differ diff --git a/binaries/youtube-dl b/binaries/youtube-dl new file mode 100644 index 0000000..b87f23e Binary files /dev/null and b/binaries/youtube-dl differ diff --git a/binaries/youtube-dl.exe b/binaries/youtube-dl.exe new file mode 100644 index 0000000..772ac2c Binary files /dev/null and b/binaries/youtube-dl.exe differ diff --git a/binaries/zlib1.dll b/binaries/zlib1.dll new file mode 100644 index 0000000..d5322ea Binary files /dev/null and b/binaries/zlib1.dll differ diff --git a/cookies.txt b/cookies.txt new file mode 100644 index 0000000..202fac8 --- /dev/null +++ b/cookies.txt @@ -0,0 +1,15 @@ +# HTTP Cookie File for domains related to netflix.com. +# Downloaded with cookies.txt Chrome Extension (https://chrome.google.com/webstore/detail/njabckikapfpffapmjgojcnbfjonfjfg) +# Example: wget -x --load-cookies cookies.txt https://www.netflix.com/browse +# +.netflix.com TRUE / FALSE 1669278820 memclid e74b9e5e-91ca-4892-8632-0cb8c6603941 +.netflix.com TRUE / FALSE 1645518812 pas %7B%22supplementals%22%3A%7B%22muted%22%3Afalse%7D%7D +.netflix.com TRUE / FALSE 1645518812 playerPerfMetrics %7B%22uiValue%22%3A%7B%22throughput%22%3A1761.05%2C%22throughputNiqr%22%3A0.6072196932211776%7D%2C%22mostRecentValue%22%3A%7B%22throughput%22%3A1761.05%2C%22throughputNiqr%22%3A0.6072196932211776%7D%7D +.netflix.com TRUE / FALSE 0 clSharedContext 27ec0ee1-e55d-4fea-aa8a-dabceec64933 +.netflix.com TRUE / FALSE 1637744614 profilesNewSession 0 +.netflix.com TRUE / FALSE 1637753611 flwssn cbf22a14-2a7e-4600-9bdd-b1fa7066265a +.netflix.com TRUE / FALSE 1669278811 nfvdid BQFmAAEBEEr1G4bCRtYMy71LrGowUb9g2zSaS2Gfvil0m7U5Q4pu3WKx5yM4XwwfWihPLA7px_GvXKP635bGWUK6H24DcM6GK9bQOFp9905LYuNO8BRrdxs4BFQ37uGmInll8XPG6c37SWowfHP2ZLV2sEZ7n-Pe +.netflix.com TRUE / TRUE 1669278811 SecureNetflixId v%3D2%26mac%3DAQEAEQABABS2V1fpBFCM7yoXuwJ8HQonzDVujurxUxE.%26dt%3D1637742810595 +.netflix.com TRUE / TRUE 1669278811 NetflixId v%3D2%26ct%3DBQAOAAEBEHQhvoGIsgJ1s4AkHEfifJOB0OXHsrGk7wfJEIPW5AkQTvu73fMNWPKcPdATmNFwxzqdK5rGCqmjVwC1w71qsK_Y8DjjOcXHB3Zkmz2WUBUhF_JqAbEGvwW6HMo90mcoxWEExYHLudE6OJKeh_eeKvKsf-7c3iDxWVK1xBe1Q7ejeW6vv_iqFdV2qRC9JJi8dF4Vsz2omok0cu9ynaudFU0_BNHBxw4bBoqIQaqk5OHy2xEYk5nZRle-H1F7AshXstptrkvCVousFEOvA7_CWcu-GBoNckG8UtRfNnN8CMQi892E_LLRwYvVdOCl0VAW17TN4lExppSIPLO7QC9qqXrwGyeBkCOxdEkwGOeLlqVBQvEAcW9rsgjWKqnub2Cuy5wbF4xSF921NxeXRynPkD9HKWVWdOmO0s85cCsGIuZyeLAe0Zu0LxGLr5UApVF95uSREskq-51Y4kuVTHjnBAbZ6vXM4x5mqM1Mx4qa5S7QO1EYKPYuJjdcUuoPk8oSqZx4VSOL2kdz8r5qeqT-LTDBMtvRJII0y6JWu8SXcX8DY-9tMUKYWUn-eXKTCbrpDitls9aKM_CCknBSf4Tcw7ejaD7UBOWe8IKV_m1oLD8Es-P_qMPGg7xIOnnMI9AltmC1%26bt%3Ddbl%26ch%3DAQEAEAABABSMhx-Q3cKesfd5g62kOwDjP9LvfDg0j1Q.%26mac%3DAQEAEAABABSbl-uW04K698qYjACgMO4Te_COxD67puQ. +.www.netflix.com TRUE / FALSE 0 cL 1637742812398%7C163774279369203149%7C163774279395967530%7C%7C5%7CNQGTGSO5SRHXRPPBVPZMU6RUSA +.netflix.com TRUE / FALSE 1669278812 OptanonConsent isIABGlobal=false&datestamp=Wed+Nov+24+2021+14%3A03%3A32+GMT%2B0530+(India+Standard+Time)&version=6.6.0&consentId=995f08da-e373-45c0-afb5-94226bba5d02&interactionCount=1&landingPath=NotLandingPage&groups=C0001%3A1%2CC0002%3A1%2CC0004%3A1&hosts=H12%3A1%2CH13%3A1%2CH27%3A1%2CH28%3A1%2CH30%3A1&AwaitingReconsent=false diff --git a/cookies/msl.json b/cookies/msl.json new file mode 100644 index 0000000..45a3cf8 --- /dev/null +++ b/cookies/msl.json @@ -0,0 +1 @@ +{"encryption_key": "oPpCxzLmhnoq2j6yxDmDug==", "sign_key": "NhnmNhfx3W9+yJwoBR/O6AQSUVUOk/eAlB4pWs2CIq4=", "tokens": {"mastertoken": {"tokendata": "eyJzZXNzaW9uZGF0YSI6IkJRQ0FBQUVCRUpVcFNhU0NmRTRqUXFEYWxYYVpvMytCNEtFcCtjdXJwazlHYzh6NHIyRW1FYnVYVGY0T1RMVGlMQnlvQlZZTDJydjc1MW15bWxNQmI4U1dnbkpuaUZmK2MySjJMYjRQZEtGRUN5TEF6eitHb2lRa1pGOU1JazJRWXpKZG5HdjdxQ252dVA5UkJpUHo5VFFzaDllY2Fqa1IxWFViTTBGQ0tDdGVLNk0xMFlpWEY3MGVZZm1MQk5teW5MK2RYQm1VOWpEMDBPM1BJNitFSlFXa3FFT3ZwVXVYVUMxbHRzSDdOVFNkWExrTXhiUXFjUFB4MXYvL1VMT3dYUVMwaFBDL1lnR0Q2Sm1wQ2x3b0o2WXN1ejZqb1FMY0RwTnlDeVY1WU9GcUYwZkF6VlVFeWtZa3JDMFF1ZldEdlE3YmFtNTA4d1RqT0ZVMEc5TnpONTdGb3lTSUJWcm0rTUI2cTV4UmpmSWlGQUhDbVFRY1JGUnR4UEpoUU8vdk5ETGUwRFM2QmFJSEFRdkZ5VmpWSHZnMUc2SGUvZzVvSnZHRk5QbkYzL1d0VFI1SGQyVVB3N0pzYytuVFlaWGYrR0p6c3JQazU0bjVSVWdoZjRYZUhLeHhxK0pWUjJxRUt4bWc4UkVJWVVGQkpxQ0lxaGlJUTdONjlWdU8vZTVqTTh5VENic2NESFJic0dIeldla1N3cnQzR2gwR05TZXVwZU44SEkxb0hFS291U3l5cFZsV1hxTmJKVlpMYWFHdTY4cHp6amZzUXNUdVhMeWNwR1JTNGtWNytieDhrTG9wMncwdHhIdnhSQUd3K0RPU0xTVm5HcWdxSHQ0UlRjM1o4aHd6ZUZzdVFuYlRqSnJyN0kvUk1FRGhPTVBqK3NKSHl3PT0iLCJyZW5ld2Fsd2luZG93IjoxNjM3ODI5NTExLCJzZXJpYWxudW1iZXIiOjg4NjE3ODYxMDAwOTM2MDQsImV4cGlyYXRpb24iOjE2Mzg5NTI3MTEsInNlcXVlbmNlbnVtYmVyIjoyN30=", "signature": "AQEAgQABASBFZUtJcaaqs6+8UyjpafykZUeUYd6JEg3plZeCFlmZ+EwJ1ms="}}} \ No newline at end of file diff --git a/cookies/rsa.bin b/cookies/rsa.bin new file mode 100644 index 0000000..95bc9e0 --- /dev/null +++ b/cookies/rsa.bin @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAr8jT0KjVIKBQTocunmzU0e9lk+J20W4fuG3e4d+fTaOvfJFH +HPxQvcYIx6EBl/CVL8jYnq5b7Vn5FTJvLhJAyNZXkHNCR89qafoJu9EpiHfVE5rJ +pdpX/XJmR4RGIJ7mwjkqgKMnlZqLRPB193zIhOcvTP76hQMxJZ7D7rlsBRY1K95r +sU6UuZSJkXhVKao/VjTCfUUoYylHxeYh9FJ4E+MY0lenZD0anB3zCPTeJWuSy3tT +nfd9y1UeKXprc8uwtHN55sjwbTthyOosOvAwXlQmLj2RWaFOMgk2k5opTVIf4A3f +DVmKNTlSMrhFEAPPnobeZO9wJo5V9aoG/47bDQIDAQABAoIBAAZToVIBfZg8xN8q +rOIdUySSK/MAY9viTYh3Bd5VzNc/xK1kUi2oJCTMZ5z9vb+w9EGhxjAh4OOgSR96 +7vb2x7eixUiI6XIJtFAHpImKu+ayP2xC9i5+twuDbkx1JYv/hBkp8w5psN9Izmnn +CKvlZRcpdfGcvLoEVSTAO9eP+2QMawbSq6H9tSOaOEsRdIP3x3ghdLm7lHymQ8AQ +AVsL9AF87bNGh20gdKNO179irTv3pHw1jGX1EndOKt0Q9GX619HKNVy7Mq2uK/eV +HwZkttOJE72pwHQSpOSTslrFoKXQZkF4dtftaCA45d0UxCoPOws82a8MKwB4sEmK +VINMfrECgYEAyK3u5rgj/PE8pbgCfIkJu5+schNqMJXB7ffzc9RKmd7soGjMRLjo +lzxi10/QDkLM9a/W0qPEQucyFpqAzJhg6+5WgcidJB3Ll2UiXcwLlJWmHHmIEscJ +qeCKErBBb8qcgJyjAkDI3JM7jH/Mm8D/B6BXDKk5EczwB0QPy2SvY3ECgYEA4D4L +CYAksN/GQFd+TXh3Hci4PyLscec1ALfqVQPAcr1JQof2fBNzy8NrcJINp5O66yib +yE82CHbUn7jjYBQSXSpkzQmELhxje7sOzUPOlG5PbBddiy5vDfo6JfsQEjb54Zcu +KLOvJJHmGlsvd56xTxCDV9zikBjN1+9RPT7/610CgYAae+HgbwLI2elgEXW6i7dO +HJd8gpVsDgeG6UcmzSh/QA1IaiwzEZgYhW6h7bWOfEBiWC9ooxY+ohZZJ1DCL4Xy +/QRLoncikhARTdaIPGp21H0UmvFbUQs0cR6nsr0gDMQ0sPdOT9ByU7fzJdaR45mE +nyN910Nh1wMCYngXJpWC8QKBgDQhuGcpB16nZ2ul65MPIoImG89xyw5f9g6Is024 +ZZFHODTjbwZBb3Y7pEqzacE/swDgm/bhk2o8Vgob7aB0iiBmrrCMOdKOfwJQ5owJ +64jObGBwviqRTPgu6D3UNFRHu6gagXys6VbTJG+UK2Df39DFwgM3MuTVH2XIGVbn +wo9xAoGAM1kAWIipKpphWms/v874kUtI/aUeGrr1Qh0OghYxecJfOtWixQrngvSa +zQgnjfJwFxnD1J5E8Mv4AuXOOLmry2LIjq5OASmLlQpa7N9wTNFCPNAqo3m4yLJ0 +3dTSmRNeLP2Xnn37QxXjSOTBpWtUuJ3XEuyE5LN4rf8FQ02j188= +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/fonts/.gitignore b/fonts/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/fonts/OpenSans-Semibold.ttf b/fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..1a7679e Binary files /dev/null and b/fonts/OpenSans-Semibold.ttf differ diff --git a/license.json b/license.json new file mode 100644 index 0000000..e6bbfc7 --- /dev/null +++ b/license.json @@ -0,0 +1 @@ +{'version': 2, 'id': 16087085638925, 'serverTime': 1608708564066, 'from': 'nq_cadmium_pbo_licenses@2.56.0/pbo-client@2.56.0', 'result': [{'error': {'pboc': True, 'code': 'FAIL', 'detail': 'license/pbl-1044: IssueLicensePolicyError (E2-BQFRAAELEISgIsOLo2MW4GA3BfKAY06At4kVy6MrBAAzT82uyWw8qJdUSJPfOVf8gtcBZnzv_pPaZI2dRGRpdXoC1BlCmdYDWsLTB8k5ycO4z6rbgxHhaHo8H_ZDh11CZ3yNmzLiQL8-SGHqyrPaOLBBU_xvKwNsZtBbO6D5N4VL8oL2UV8uYy-9ADUH3uB8cVtyayaJL5cjZD6uQl_RaXYHh0e6GwEl_L-GJIsZFlOhj7jgwAWC9l0ANY8nG61SWkOJ7agmDYDwTFJ5Vvy0GA..) (nq_cadmium_pbo_licenses@2.56.0/pbo-client@2.56.0)', 'display': 'Dieser Titel steht nicht zum Streaming zur Verfügung. Bitte versuchen Sie einen anderen Titel. – 1044', 'alertTag': '', 'errorDisplayMessage': 'Dieser Titel steht nicht zum Streaming zur Verfügung. Bitte versuchen Sie einen anderen Titel. – 1044', 'errorActionId': 3, 'nccpError': {}, 'errorSubCode': 0, 'errorReasonCode': 0, 'errorNccpCode': 0, 'errorExternalCode': 0, 'bladeRunnerMessage': 'license/pbl-1044: IssueLicensePolicyError (E2-BQFRAAELEISgIsOLo2MW4GA3BfKAY06At4kVy6MrBAAzT82uyWw8qJdUSJPfOVf8gtcBZnzv_pPaZI2dRGRpdXoC1BlCmdYDWsLTB8k5ycO4z6rbgxHhaHo8H_ZDh11CZ3yNmzLiQL8-SGHqyrPaOLBBU_xvKwNsZtBbO6D5N4VL8oL2UV8uYy-9ADUH3uB8cVtyayaJL5cjZD6uQl_RaXYHh0e6GwEl_L-GJIsZFlOhj7jgwAWC9l0ANY8nG61SWkOJ7agmDYDwTFJ5Vvy0GA..) (nq_cadmium_pbo_licenses@2.56.0/pbo-client@2.56.0)', 'bladeRunnerCode': '1044'}, 'errorParams': {'sessionId': '123456'}}]} \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..05d3e93 --- /dev/null +++ b/manifest.json @@ -0,0 +1 @@ +{"version": 2, "id": 16377431109789, "serverTime": 1637743111385, "from": "nq_cadmium_pbo_manifests@2.107.0/pbo-client@2.107.0", "result": {"movieId": [80230399], "drmType": "widevine", "type": "standard", "drmVersion": 25, "dpsid": null, "clientIpAddress": "45.115.91.43", "bookmark": -1, "playbackContextId": "E3-BQFRAAELEFmYzYMCuFO8H5X7uhP8_TmBx8ihKvX9kq7rkPKvycso8lZA5WV3wVWMCTcqj62fdR5BvbNhsvX7LAf1X1ENI_HnhyGywtlPzBTNMQOULA3UdQfuhA0ZZJJuIWIQ55RMc5R7O9bPJ3Zj9o9RHT_u-tEJYj3Z8JPWS3JWL25AMebRCzwa9HrsQ6-7ouiJdc1VOEDugep6Ih_0htQT2yD43RZobiYu0cmQn4PYbR9s11lvwLD5gRs3X8AnHRMhJWduCioAVwp-xL2NdpPJvZ5qk4zhtGoABhgn_bmidjFBUnf9JwhX7Jjc2RmwCilhdlyRWkkeTrfFNEK1vcHcA6qimnMi82MAFKP8lmROMgRfry3qmGd_YlWNvX7TiMDI6zXmY8_cDE3R77i5Y5B0OOPRLRnOJ5GtXpG6pHArcFgQByd1V3S3KygEFb1knH7ucearm9ZBG0pskEnR9QoxCHZDyf3kc0crI408LaKmQTpmu_2Qe9E42Af4zbDL0tjk6lY-T7Z4S2mx24ooN7DbGQ4pzX8csn70z_3_uXwis8mBJmsF21yG8lTApsJUQFi-KcyR2-TmIJpj0UjbDEY7gT0FkYsR2V4udK-xVYi23xPoIKm-Y8-HNYTSZZmW", "links": {"events": {"rel": "events", "href": "/events?playbackContextId=E3-BQFRAAELEFmYzYMCuFO8H5X7uhP8_TmBx8ihKvX9kq7rkPKvycso8lZA5WV3wVWMCTcqj62fdR5BvbNhsvX7LAf1X1ENI_HnhyGywtlPzBTNMQOULA3UdQfuhA0ZZJJuIWIQ55RMc5R7O9bPJ3Zj9o9RHT_u-tEJYj3Z8JPWS3JWL25AMebRCzwa9HrsQ6-7ouiJdc1VOEDugep6Ih_0htQT2yD43RZobiYu0cmQn4PYbR9s11lvwLD5gRs3X8AnHRMhJWduCioAVwp-xL2NdpPJvZ5qk4zhtGoABhgn_bmidjFBUnf9JwhX7Jjc2RmwCilhdlyRWkkeTrfFNEK1vcHcA6qimnMi82MAFKP8lmROMgRfry3qmGd_YlWNvX7TiMDI6zXmY8_cDE3R77i5Y5B0OOPRLRnOJ5GtXpG6pHArcFgQByd1V3S3KygEFb1knH7ucearm9ZBG0pskEnR9QoxCHZDyf3kc0crI408LaKmQTpmu_2Qe9E42Af4zbDL0tjk6lY-T7Z4S2mx24ooN7DbGQ4pzX8csn70z_3_uXwis8mBJmsF21yG8lTApsJUQFi-KcyR2-TmIJpj0UjbDEY7gT0FkYsR2V4udK-xVYi23xPoIKm-Y8-HNYTSZZmW&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C"}, "license": {"rel": "license", "href": "/license?licenseType=standard&playbackContextId=E3-BQFRAAELEFmYzYMCuFO8H5X7uhP8_TmBx8ihKvX9kq7rkPKvycso8lZA5WV3wVWMCTcqj62fdR5BvbNhsvX7LAf1X1ENI_HnhyGywtlPzBTNMQOULA3UdQfuhA0ZZJJuIWIQ55RMc5R7O9bPJ3Zj9o9RHT_u-tEJYj3Z8JPWS3JWL25AMebRCzwa9HrsQ6-7ouiJdc1VOEDugep6Ih_0htQT2yD43RZobiYu0cmQn4PYbR9s11lvwLD5gRs3X8AnHRMhJWduCioAVwp-xL2NdpPJvZ5qk4zhtGoABhgn_bmidjFBUnf9JwhX7Jjc2RmwCilhdlyRWkkeTrfFNEK1vcHcA6qimnMi82MAFKP8lmROMgRfry3qmGd_YlWNvX7TiMDI6zXmY8_cDE3R77i5Y5B0OOPRLRnOJ5GtXpG6pHArcFgQByd1V3S3KygEFb1knH7ucearm9ZBG0pskEnR9QoxCHZDyf3kc0crI408LaKmQTpmu_2Qe9E42Af4zbDL0tjk6lY-T7Z4S2mx24ooN7DbGQ4pzX8csn70z_3_uXwis8mBJmsF21yG8lTApsJUQFi-KcyR2-TmIJpj0UjbDEY7gT0FkYsR2V4udK-xVYi23xPoIKm-Y8-HNYTSZZmW&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}, "ldl": {"rel": "ldl", "href": "/license?licenseType=limited&playbackContextId=E3-BQFRAAELEFmYzYMCuFO8H5X7uhP8_TmBx8ihKvX9kq7rkPKvycso8lZA5WV3wVWMCTcqj62fdR5BvbNhsvX7LAf1X1ENI_HnhyGywtlPzBTNMQOULA3UdQfuhA0ZZJJuIWIQ55RMc5R7O9bPJ3Zj9o9RHT_u-tEJYj3Z8JPWS3JWL25AMebRCzwa9HrsQ6-7ouiJdc1VOEDugep6Ih_0htQT2yD43RZobiYu0cmQn4PYbR9s11lvwLD5gRs3X8AnHRMhJWduCioAVwp-xL2NdpPJvZ5qk4zhtGoABhgn_bmidjFBUnf9JwhX7Jjc2RmwCilhdlyRWkkeTrfFNEK1vcHcA6qimnMi82MAFKP8lmROMgRfry3qmGd_YlWNvX7TiMDI6zXmY8_cDE3R77i5Y5B0OOPRLRnOJ5GtXpG6pHArcFgQByd1V3S3KygEFb1knH7ucearm9ZBG0pskEnR9QoxCHZDyf3kc0crI408LaKmQTpmu_2Qe9E42Af4zbDL0tjk6lY-T7Z4S2mx24ooN7DbGQ4pzX8csn70z_3_uXwis8mBJmsF21yG8lTApsJUQFi-KcyR2-TmIJpj0UjbDEY7gT0FkYsR2V4udK-xVYi23xPoIKm-Y8-HNYTSZZmW&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}}, "isBranching": false, "partiallyHydrated": false, "maxRecommendedAudioRank": 9, "maxRecommendedTextRank": 0, "duration": 7051000, "expiration": 1637786311362, "urlExpirationDuration": 43199977, "manifestExpirationDuration": 28799946, "viewableType": "MOVIE", "isSupplemental": false, "packageId": "1674268", "drmContextId": "1674268", "eligibleABTestMap": {"39008": "1"}, "media": [{"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}], "defaultTrackOrderList": [{"mediaId": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 0}, {"mediaId": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 1}], "timedtexttracks": [{"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:0;1;en;1;1;0;", "isForcedNarrative": true, "isNoneTrack": false, "language": "en", "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {"simplesdh": "1176827093"}, "ttDownloadables": {"simplesdh": {"size": 16161, "hashValue": "MjR0vpt+zo1jyhZ3VMmogCS0J0Q=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=taqTgiloAhxsMaYYSy85iuiPixRrdW7m15txXkmG8WbrVEhoZgs-qM89eloxrL-bh9NOelL9FgHjnzDjudBYN_w57jRUloxRYf2aJOH98hm81obzRYMzNjAOq3qgV2nMpMIPdLl37Y-D-6rjoRnfTtFTOCWgFWVRjSBZyQ2cd_4JqPAwKPStVi4", "2": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=GIVKlBi8XIzz6jKC7pWhJvR5FDIRz_v8RX8k39IUR7_k7jyVwgx-w4f_64wUl8vhwW7g4QSAkPNyHN_0q_rUlIcXWh1NN-BiQFtmjG0UV4kRk2Om2kQ4YBoBdstQufnaLbrHKMqXquX6fzeei7KQTi3448oliCTl2QRWdT4Elm9H5uSsu0Bi9ZM", "3": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=cVHRl2mVTJK88PmtjxKd48DSJPzlabS46SQFVuwfDyTUuUeI39J3lqF2wMb7JxC04drNgc24_mbsa0LFbn_FK67fI44JgNv3VfYsT1Y3ijO8TRVkF0uGORTIkH37JqhrKP3HchFUaYhLYnHzOBzlqlKqYC6gAA3izVKmVIe9mWzQAxRtieX6KWs"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "ASSISTIVE", "rawTrackType": "closedcaptions", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:1;1;en;0;0;0;", "isForcedNarrative": false, "isNoneTrack": false, "language": "en", "languageDescription": "English", "isLanguageLeftToRight": true, "rank": 0, "hydrated": true, "downloadableIds": {"simplesdh": "1091695175"}, "ttDownloadables": {"simplesdh": {"size": 89685, "hashValue": "+ZXBbL9zcLzKphEOcnQDDpe/j1o=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=DqjQAZ_Hj0dulLxn2iA8dgD777pE48w-LiUvYnxldg_7co-MVPgOhKDIwrpRH48jh-_C_1fqfbKV7d3Qp70PRPxI4fNgwJ9yWyipyRUzHL7qE1LCXYM3GLhqqiL2VGsnvFev8aYDQ-R17cgT57iUxlQeHYw3Lm2fKxnLSL4Q324CFfWCwMcyjiM", "2": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=U4WrxCymnkv3VlZcLK_Cza964_nTRoo_SK8xzHPECb1jAXnxEZ21PeSXNnNDS6wAUInzTJ0e9YPKYBKJf-NPBETbjJ1Mo2p4v3FICvsLKr4X8n0g5wlcu8MsOg2uLk_fAcdGsgXWUULgD_9eM1PewYADtlyY2WMHykmXFcTvJpIJ825tsgg6Ya0", "3": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=5O6X1SvM6inwpWO9Lr07vn3KN5Fqzifo_JrPAXvjCjoBVHT22CYZXQOmSDGRiC3HFgX1qQM7eG85gCwz8ngKyOJ1DXNJbLDK6ZAsy6NwZt43KESSpvrPEPjfJqNhe81MlExUSsLoh1_maxXLPpc7p1-INsl09DTZONGbOQF7K7Fot5lB70zMFOU"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "none", "new_track_id": "T:2:1;1;NONE;0;1;0;", "isForcedNarrative": false, "isNoneTrack": true, "language": null, "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {}, "ttDownloadables": {}, "cdnlist": []}], "video_tracks": [{"trackType": "PRIMARY", "track_id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "new_track_id": "V:2:1;2;;default;-1;none;-1;", "dimensionsCount": 2, "dimensionsLabel": "2D", "stereo": false, "profileType": "AbstractDynamicEnum{name='VIDEO'}", "type": 1, "ict": false, "streams": [{"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6350, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5311955021, "startByteOffset": 97454, "isDrm": true, "vmaf": 100, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1806783668", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=nUJJdgytZnUnra-trAGIN-jGC7givE-kMdARCZNFv515D-7Qq1zmZ8eHqODPzOs-0lR3A7Fz3NVDCqPPbcZyJym9UC_-otaAEZGFDUJLE3OdLpOgWmSa2qHwRwmfKdzwnA39J1XE2WYOsNB8CaRxQc3g_69tm75rQk2LkeR7vwYJyqbC9vTQtp2fFV4", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=fny3-VoEHKnryUcQJTQcMj3XF9btapgfkV4wD6tt0FAw82yDB7SV61Jl5F1CPeymLA7Do1FhgF_SEYPZ0Pdx7y96eRpzQnHthYszNyq-wmfdcXbCWfV6rXMewGhAKYE4aLWtYeOeVWgx-MfOke5t55wJO0YoqxxJBvv7zEZC8yIgIw1b24jut4UJEbs", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=7NPr9MtR-OgI31pQHqNL7VQ3A6eCAlknIsgFBLaxkgLv-wPem3qhwk4i1a1JzOm3fd5blx2nP8g7DnB8GdKaiqqpPZJksxn4vtfV6xPJ6e0PYpTFOrwJF04kvEt89dIFugZ2-eUevpu_Yypq2cNDIE8NVcnz5jJiQ20jNANP_Qkw00ddl2eFxyrt888", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6900, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5680647092, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1916117199", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=s9yM-CPchaaVJy_XVq2QargIvRrT_x_ZGM5eE0_hpKYTrcgj07SPKtaeqToTuLPU77Xik28twvqP8crPXc1o3C3WVe0DECu_uBnivxvY9jEnqK74Tw6P7kKCVxeYNeaMpIddVRV51GQkOJZTetp51oC8fI96LiwWDTd6QZUdvRygUIdOOYMYXrd30jY", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=grj6cE6hgEcGrWZcN3_6BoarPowqbdTFHWLTXcBZAMTDiXXWvDX8oSqNXo5XcPVTzW9TrbRlXj2ybYE_eRivirJbtuGzLlRqJH3HcHPX9E6kHdkA0htQOoIhHUBwC6H_gTTnl5GQOsodFwgv8jWPDZ09w0dobDB1_GJDV-gVQXX6_GtBNZkXyP6cyiA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=TZUnhbE0UlQl_7Tv6fEnXbQkY_CwPzuYa7E4IhJTAeUziKvMoPG7reaLviMUegj2F8e-g2SMXnXxDi6cqjo3jLwOa2pQ3d2p42nWWpSEn69Tl8cfASQ5SD8umPonIIz6go1jPzLO_BK5sg1SlZvrBlggRcWOxGw9t--YLTcIaIDF8NysQIMzvdL846o", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 7450, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 6021494277, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1956403691", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=tEtqvN6RA_mSfZoI6IgNNwzwzjSM79O3hVMAUhpyL9K_neXSnU4NZNZ8nYyEsHiPyRD40ZVT_Tr1QI8kuByEgAMrihiYj7uY-2zAzyW5guftFw0ssoInk3ZVbq85qNZOtBvS0uC3AxZ3NrfC4sY8iE8ly_ffNagbNKnTuzq6heVN6594Hayz_ZAQyfk", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=bqKSSg9s3TagMxne72nmR3xWQmfR0PjIh9jbcIeb-SoWN3KGoCYJRAG71LrHE0Fj-MXeu6oo8kVbOwzmvWYgGCnMxnvIex0DYF97s4JcB_0y4h3YApT-yHVPs6iw_JZD71t2JrtfuZhwVkpluWy8lohjZVGCc_IEdWs8v6yk5rH2y78m5WVojZ_k96w", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=YUR6trfUaq_OhYV3DCVQBLg2RpqO0uAYRpFANBUhebXERLldO1czhhzv4VttdCUYgw9R-uFHhxJsqwHEPuvt4wVMxFa0-BDdU9jEpH-TvrPnweAhmDi89XLN33-FmzYtHlsTRhwzfepPlOuyVBkaQOA38er5CCbwOWbv_QaPLEdWQhrY_PMgOMXk7ZI", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 8000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 7039207021, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "388580917", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=ZPm1_7Gym_xaY6eT98YyxFoSc_YdYwbPLETtnCctvFVydd2HDY_uM1_NuhIOOGVj8Pk2R2-aWTuVS1JkSp4rkkKfk4MkdQbQTMkb1S55rEVSSVHT_nc5sox_OcvDH9z99GrVyU2JKKAT4AHPCNHAh2xp6frh4XgP4xXmyqIaszSp6PrCLJXRj5mfkQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=m9IS1ynAQB-4CjizEWXDL6mICEUCuL0_LJ4oqbTonkLZFCo77W6Bnvkj8YfyZd75dbKeW_F-CEt5jbEaJNpf2CyN71wwXjbzpHVbDlJyUMEq37kcOVod201CKF-CQLy1PAWgJRI-n1_mDzrmwpCVxw9elFP_WJ2nirY9DSM-hF6ndsSubi_mpkeiDw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=T2hRuFo4tdAy5nQ7k95xqbCHyU4Um1YVVGf0Q3OaKu0LVQJY_MTMsbGgnMAVZya7NzwrNdtiosvZ87lY0bxgZuawO37LV3FomUVoi6LHPP5xivSizhVl57PYwxhNbCcPJ0ikIxCpdkhqUpg9_4PNuQUrUKRj1MoI74TbrCij6aTTg4LRTNsG5xOURg", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 10000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 8676621644, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1970848201", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=moIJYh-dL_KonvA8diMB6ARyZmIQolcAMIN4L1gPXxUZB58rjItHX2_kbhT6_sHBR3YijRi2heL5hB5YFX1pt_3sqW49a6VQSTlRXE49tTzHhruHG2fO2nxGAvv6z99JzSf60D1upKESflOWUDvAaSlwLl6Q-DEGAPL-YbvHzcvQpLwlcSVgeCIrvT5B", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=2u6jvfoA1HY0WCoYZAjPW5BqTziRkTZ41hxW3UDim6sRAeGzsyY8xiTYU7gxBNr0JClPmV8jl9WnpfLMkRnDZUlN1PFmxtTSHY48WmKhVtsMrjYzcjXbV5jcgIsndkIMH3nh_bEFEzI7HLKP_SPGUmq3lzEjli_wlyMWauB7Do1jCSXoFx33xGuPCrO_", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=8cYv5HOm9KU2EKrHlJ92E_QtgpEXsohv0vHv5l6zRXtsOy0w-7PdQAtLaugFtsLpHlt8fDcgHQfU9xlGiPITlKAG4Jcypts1HCb395s34eJcDagVq5D9WhQzDwRaHvUR0p__rdIJVJkIBHMGHcECl6TViPVfg8TwJJI_1PK76QORAwWnZRqFxreMJacT", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 12000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 10281705940, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1783080613", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=nwNzyTAM8i61E7JQii-pTvINB6pNM1eY_HcJ23Z0G1UpC99uX-OdpMEMYGQtJ1ZRsoSIyXjNLX3jerpM4QjCpOHEh7Oz0d9tNLTFMDg8nX8BTvSZrDiyIDS9E4ixrdpFC_vFFsu7e1b1tfOOQSL6BHFjrLSGUX74n8o4O-eAz_EFu_sRBvLBFkJ3Xhdz", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=phT1QoasBCAiwhitMjp1HGYoy7GktqYeCQcyYIOenxzlgKFjGgKBsCEwfwM84m9-GpoAWEgb0DDmDg2LuEYflfJh92UbeoWvK9jq_orLBjL_XBAV-rVK2Dj_P99LJZXICb6HivbsznxTLhiW-gpC3wrqPR8vTPN__BeGOzg2yhdDdCoEC4hmCiauMLr9", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=0WM9sRI5P9jldSPTumAXwchgiGh7j645ROoX2MKNkskx8WwGG0Irkp0NtYrETN9ftIW39rwFbtfP3-Un_imrMsQq0hbg17K3ZXZu9Fn_TvnodiYOvJqjabfwMnZKjnIM_P7nvT1E-KjKc63orRRAPell0PDQPt-WqCTvDqmdg5jLyxInOPJ-EW5rkmzM", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 16000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 13371437321, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1109298487", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=Cdbo09rPOvkTUn5WqNWRzJ8d_54YNcY2-u6iE-o7sP4hRAUv4JOlp4yQUeYfRK3wid--pZNLLRtQLY6g4UxbTBHf_HUTUsAL7zlT0l9drf_4VR8U8DgZw9Zjy38_MY4xr9ezW2LZFhtaguYIFcjmeJ040MPPrP1HoZKlWDHrWKBfX9I9udx27HdUTm8z", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=StpA4r0YFo39FGmnMW4p2lBpPlhQ-SGxl_J0zeEzKECKByOmQWwB9w4_GBx6HRRtq97x7IszO1ywoCguw7i6kyycDXhi7KyGbdbPrcgyY118RFGSxLRJKLU2PucXE-CHwhAXv18Dn8KLleT6vBgoWszTQwnM-qY8EjOXKB4PLli4u5h5Vmg2IhNuEMTR", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=-W3kYnNpJPMjw_vdFGnQxbW-Qdj3coMNyRIb8tkXmYdwP4CcnRRtd2JT54cFS2iTLmj3wumXyZzJbRXdkfIVP1gAybO7-2eTTvPPGwakGDgIK-wK3QqYlT2AaAYIe-3SyyBnotknXSH2xhG-QLVPW9wk19lvJhKq5sx4UQoyCcu-uBOZ560cWysNEvKr", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "profile": "hevc-hdr-main10-L50-dash-cenc-prk", "pixelAspectX": 1, "pixelAspectY": 1, "maxWidth": 3840, "maxHeight": 2160, "maxCroppedWidth": 3840, "maxCroppedHeight": 1604, "maxCroppedX": 0, "maxCroppedY": 278, "max_framerate_value": 24, "max_framerate_scale": 1, "minWidth": 2560, "minHeight": 1440, "minCroppedWidth": 2560, "minCroppedHeight": 1070, "minCroppedX": 0, "minCroppedY": 184, "drmHeader": {"bytes": "AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQAAAAAAWi+gcAAAAAAAAAAA==", "drmHeaderId": "0000000005a2fa070000000000000000", "keyId": "AAAAAAWi+gcAAAAAAAAAAA==", "checksum": "", "resolution": {"width": 3840, "height": 2160}}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "audio_tracks": [{"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 3, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430558", "new_stream_id": "2037430558", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=PA5XyGbtZRMgUF2t6o7Bud5LL_gKkhSQVFHboIrtAHplDkSqNiMSLRLnQoKbPj1ied0g2B6dXSSol9PB_JhpsunfH50UHXCYF9sBY1R16_TQTvyFcJvc9D8BhXe9ZOGIDI_kCUF7n7DSNfiiLM5pVPvoI7ycGZvUEwX4Mmw8SO6GsDcxyfehU7vt", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=yaEb9_yEtS9r662nrsFcA2k57TWfDHYwdoSrH2NmD3jj1K1_KXoVk_4JbPuKDB2QizksM7TjBwx4jc3PAi69DfjYaukMDbZoa2bJmNP_H45OHKGHBQK9c51vP1psBC8mRT44wv0ign68L5XegerVKMwxhmp4WlvaSDSfR5aXG0ZrdSm7ZYdBFKeP", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=H7hYs1XZqIbkoRFD5L5ptHmhyJjYbMj7YMbNxz15kFfEacAtiBoxKheI5dBvtRA9aWMQPV1AlFOm2LsCOgklBuQ3j_Tvna9RO-x1x5bOxMMqjXX1TZhFgIGf8rI-RzKuXQhc0UdihU8pWXbdHBtQBY1RaIL1uoAuQsDiFocMLDiQ5nLSqMAXEwoe", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037401654", "new_stream_id": "2037401654", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=siTHCasU9Y_ORd-l6S_qoPOmLf07EAWIZfe4kNOgXtIFkPKmu_Y1SToISqGwV6xKaTmX4yGL_nlrtcI16WmUrxafoEkjP7Vx9Usxin2RjMDHND4mpz3nthj04OJlRz6Rk42QyDC4PYH0KF8LWkGj81rhsBgcqlTtWv067NexXhrklTcvtiam-jbhYA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=SGYcjuFCtYhRH-EsRJJVZC9oFEpFZLocmVhbHtg-JSWXRbIi_F1tAf3GZIHxUKk8rugAE7EYBS7mOlGgaRegKa1CZcuzIXZx9pt3qGxR29h_BmXrN5y6ghrL3-aBr6thfqUzikh41133_K3xg8taw2bhlOZ1p4tWqG78QKRmS8PxOijmIWCiJPP3Bg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=s-aNBhpD6qdur3sTm0Y8epsYsjvDZgquiKbD1ulf2s9qVtNTm09SGRAPL4UcTheCzLnJK4VFZg4BigOzfWmafPBjvouVC0r9yeuH1OW1hHIlxHyycYP7XqlvNM7bXBEEYnLTm502J4vLtAtiaUaVXdQaq_bxu77MmeVyKZRvtQs3T9PajqJEJkLTkQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 1, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037426205", "new_stream_id": "2037426205", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=VYgAcc64iG6CwTpT8dZMGodKs6-GIvcdue0-Ki0LY3vAljWdue7KgOWRCqY08ubbz7zsDVypwd8ugx-_g4WLC7vckclkmhxyEDP9eJBqFIGKbUaWk4FqcRvPXClV57KUnsHnEjg3ycnAhQXcnFIk8Z9rE9KW42CHIIDxQyHY-WPOl3hGGZAjY7-0", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=2mO31Wb3ZPQ7T6Gz6_raW8IFWKwmDpOUy3t--PKZirepdkg68FLJ9zRaU-kiy9F8wAjtUZ0mmk25-c_kiZRQZbHMln-S07TZB8Z4HDreJPflv8VYAit7fo80Gmt_4qHk4qAF9-dErqL0GNi3XNSnSBb4W0fMed1Yuz9Damlfm5qlMXXFduO1koEK", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=STemMNTX7q2sHKf-7OapqlCYByna_By0Did5BdwXJmFjrb9_HKSUi9jnbXNHvBbwFLHF6I1uTEL5xtdOxhpyFNqcfqWBwCeE8ea3MhaJmDySy0LiFCb2cfOPKpfFJjoqrcTcNlu_LAHxrXfWDhajmcPfdBEJ7nuJH3YtjPB_Fa744dAPlpl0Zfk8", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400705", "new_stream_id": "2037400705", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=0QR4NTPD77Fr9LK3xGsY90DAgOXZVgIUwrNxNmu51fkag93w2flI2ZrCQn9omgGe6V5neyuYGY62JxivtGvL2IxfA27bXfSrhEWNM421L7-vFS39YF_FiDDKJoY1pbrhDQAmqUnRN-6vSUqFrBYRZA1yfsYtzuPYaBdn0SeyFMZ8gzVJY1oIYegKHQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=-tz8J6LLdp7L7Wj1JOQFMKRECQkyNecbIWBt34S9CByBQjkLXcmrJKK6OoJYgzZbhhDeYpHW8ahof8sF77u8-xxJCf-j0bgNLZDUa5YWBnsReb_yKQvWZJ3n5A41s8wHhJ_oCthzkpMKGuSIpcRrV76kFheyqjz0VYXkV_SRxXs9DBPPgxC-ZgmOrA", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=AmHUcLSGL1WmYp9c7nidizjaNVzkdInHLs8kbjD05xLT2y_RRDWOEEXQyOeR_R3iqC-TzY2SpLiUcg-mic33t9ZcU-2XvmBNiz1xd4OE_BzDP_S8ozwRLYzxgV8Ey7VkYsXRRQmYBp5j9E3lKiXx3KJlTnDR3DO037WYwYXkQIlRAQHAwr8eF67Ecg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 7, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430888", "new_stream_id": "2037430888", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=2GvMooaQ_diyuabhchSSyMDPwiaxeFgvxcT75hLJlM-NiSKnxN7bB3bGTF1ntvBPmmJOk_wae7SyKm2uZ_UduHTvI4BvHhe86Ad4RdVXgR1WwY7u-Zk0PpU7HqW8_obZmmxOa4-nFPcz_63NnrAPYyb835rEovFIqzsAx0xKPq9q5hfLRs1ODfzb", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=PVOIHlxCpR0fTsJcY9zzXeQML9hFMcltdJPdWij5BGsesyH920f7_pEFpocKnViHd56_5eWDkGTBbshw_GnMWbASOZta6nro3NcvSix2AYf4B2XZC6eebIE4QKoWwsDoaROqCAKx4B_pjW5LUodpQaF-TQAN8wKVNUHwoC3InByL3pnxLg4WU7Gj", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=w_sOUvfBCy2RgLrac5FgVa453HGYR0MbuB-_blPH9rPIsCb1Pkwr1LstlSzw3ghrckiHHYJWEzmGoeL_wj7FyBYC_hX1-PcZ89Dbm1YJ7ruPhAeAZQtvBmJNgAZfOhhU0E72EmUgSjfxGBSGJ1n-Z9OXl2Bfdf2IFupJdqtxvW8OBbSrglSY5KDY", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398832", "new_stream_id": "2037398832", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=4RIrWVLyTnoQ54SZblvKbTLkg1gsdM5EWWTNGdWQ4Nm4DgOZrJg3eBpxg0Zu2uu_pEL2fZ8t4GXCirDFReFjUaJiMWE7-UEwedLhAEinu9VpH49UE4LmC2fYyRhi00rZkl120Q6wseP31hvy33qEzaj95wlyEMvgDZUrFv0acCKGoqH87wCdOfGhXg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=zgg-sCt5U82IBLLZXVpFoaO3oT1GLtR9Ujv8aqZNaUmuxiS4bHPkIl6PdfvjUX6M994OIysCkOfgONk8Br2zRkD-nrEGj1Dmek4pwWiUQkHPLviEmnX3MOyIs6kyfOx-B4fKWlAfCazGgN-TkRqLL1P-FxoDEpd0bSfKNX0rzbbw7PyfDtdRlXBdeA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=uUjmw7KmVmcoKM11BQsLdqFg5jmuXDE91EzXG4DpdcKxSfuPaIWVDV7KBlhkH-xciFkoB2e3PYZjIT3CFg0cXOOXMr1y7gRJeIUs2Cg-9N6aSApau8-ChTd7gThTt0iZMKLjbIsV8wfVh-o97D47pa27lfwzvpfF1DWPyQJ_yP8Qi64vE34_TSqRmg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 6, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037428537", "new_stream_id": "2037428537", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=HZQKqE5B5mOJ-t8qFq0i9zsyP4nADPDl7aJfkQc2oFyV6ivCJI-ifGYiHMRyHxKGOif1SceYia-KbkxjacBX3AaeMI3kggMacoVYAJTxCCVUxSq6STPOlntoVI-JRKQLNq9cGM3G9QyZRm5_mcHLKOlRfjP-F8Eu49gNyAXnDMlDqJp2tnV0Ttta", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=Znnhr6zA59iGJikKE8KdcdQEHcYj708mrF0UEe_KH87HwXefEQpaBzUBZOUer6u_rIPufwq-hRWE4dtJ6JwxiAE-amc8DL3Rk_AyGxoCkE5V7UX7VXdaG9vBKyAgvKP5uxOp1NLyfV0K110SRxKUjBx2hmPVpsfaDXeBO7dMmcrUyO0Gwis7ekbx", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=ogbzqwKMQY9wDN6VuYkYpUeXxJSWUbdgcgsAeE0eK7q1crgEaTuhR4FnPHOKmTleKsCv5vyfB2drZ5aMDTKJUQo-6Bsp_O4ct9SWL0UIMFXicR88uEci1XoSPfDt2Z2p6eGKbD9FI4iuI2p4sbOk1aVSM-vAvgDZ8ZFUZDUXto-w5dE5mrv5AIPZ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398401", "new_stream_id": "2037398401", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=1y5TtDViHPCXFqVYvoa2dj1rf0B7AhEL9J4509SGnRYCn4alT8N09q7NNdqVxq7FRhwgq0lbTlDzXTU0nmIaK3bYj3BjSY8X2hjNy0MDc_c2OCvNUf01zVpO8blseaN-HaKMsEpTXbDz7dHPzJaOCXaW7odrleToNmhDzgmubi-cXPHMeyqq23nZFQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=E0eiYEexSiLwvK4sKOJbLNUB2e4DipcWjL2raEQCcG2ao_K6JHbrAXNZQOLYQYKBJVaP-U21p5H98N_RcgOIBvOiIX-f1uJhCWIEGDGLpkLJARUtE-Dwskkc67jg_TJ7qAkOL7IW9QnMEz0oqHzKAycNdi64j1qjPFDVhZfnNzdFyT-f1Vd7r25IAQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=Oo84UzUdol83Jjf5Edd6F9uPmn-vSLaiHEYmRrgt6qsF6mEgzue20Orf5HJMy49zgR1nxtuTqtUhlUDAWKbE8xwqwR86rfz42B85fCA-3R_s30-qjKGrngRSAHdTQNX8_S9XOpEXjN2iyIQd7-TBdLCCy70NxzV8Nkw0AN6SLYk0ss0tEFQoP2vXmQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 2, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "dd-5.1-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632986", "new_stream_id": "2037632986", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=fynjXIUTx9bcyIPySjK_Dg_pQws8QSfR94GErbeLRHpQb7uiKl0wUJZw3BdAbHCvH0ugklAP5ZmRF_3ZzziKHnoTfVcMVL3zodq90P2DTE3wCO3CRbkVhY3Hsu6py4P8i3TB84I_vZtQFdy3YuIijZ6WQKzBKYOa-2JsnJJasfNbE9mZ90TJ3BRBzg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=79wdpRHrCaTNCR2leG5Xs-KcINePEKE6wFChwynjfzh4Xt1KmVGH5ibOi5hfqMllWwPwmvV-kXV1UM99UDIflqiZoY76KZaFoYvspBMSvdHvnJrLaKQALz9R_5cLGplfvj2LV_no8tvgDP-2iDB7rE_5oqTuDwgQSwC8JJa1KLvIPmzks2f4EpbT0Q", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=9gkzwUl92_7z8Tup5xHaCQ4Qo4erF3kmBIj1wimdXan5A8-0U7w5J6XsY2u5lOrbG1TDSMSktufknU6VFteEJvJqgrPWrh0Gob_r8B4dZG-XAPAMsAUHzem3GBOgEcuJu9QpStaIzmHC2xhQlrvp0lXtJncBPRwhx5aVBhXRA__PAdMbFQMPgWKg3A", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 448, "size": 398321056, "isDrm": false, "downloadable_id": "2038451973", "new_stream_id": "2038451973", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=7wcES8SIRKn2dPm-gJfaixzWjdpvDrtv-n-eNRPrFBVXFEhdYSv7ac6Q9nE97_x-kWuuuFUHdtLCBBXSrVPmJawxwsImDjX529xtUcPZQbw4XOyOdHYt7LUVatUUdACxIgBSlauhLWXdIHVt9dwWHR25crDQLKwpSZsEaaL1drMohWorqvBi4NH72g", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=h0gSPY1EpShmuLNlLdUD1jL6_x83gJmdxQNGvshr5sGdw05xaeWh6UIE5HAheIotNY_cxtWwrJ0_PwFXxqBDw1GaL90E9MAphmpnVeyPLQZZrh7jgKo4im-XJe1Fn2Jv_zOnqrdNtQGvf_Sy-H5ytR2JocBaHZ_NYMAoTU4o7kd9mqXQIPlD2pDE5g", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=YcKwlT90GL7w1SN0xLSiml_xRVbAMnd7GEphFIeUxX1eyqK1GCw8vMM1s84W79MOPw07BpV9X9iS_0rg7fHtNFABiN2rZiT338l0GmJBMChZzFLEQ8vLJVUHAnXjFaaJEk5BaHo0TYyggRdxNi99-_1EPUzjIaEdRe3BBU_nck3_tVPqnp-5_RKfkg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 640, "size": 567539104, "isDrm": false, "downloadable_id": "2038451490", "new_stream_id": "2038451490", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=hVkg3v1Xt11Lb6PMxKa9Fr8heCjhb6sTPaOm4kFZMedCh7h_XssMFX1wro-EYZxhO1yBEbzfz-qK-JmY0yTu4ysQ8Z0ASTRHsMvaZT7dJP_QzrMCa94OFuklUA1C9Mb5Q78Tar4sjCMp_jD7fKnwprxawUusoeijIUkEqPR3Aci5-6sWq2dJTvv5sw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=PfYcaRAtivmAtGb7Gr2wSB93OMSaWwkcGdL19gw7Z_HYljjmXj395KrceBHC_SXQIUxtv7YAOMvhzbjBSZixVyGPRDvCVmWfzROBYKbdM5cmJU02L3Y6mSroc3DHce9AFN6VS4MEQxWYOQHFqF7-wwnmqJKPX9VmAyOJM7NmKAs7SJchdcrXZqFtvw", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=94J4WKV0izWOmOLi7xb2zJ-RJJbbQzhz6pHJqAHq61TwK-QE8rawvzfZHFd9Wwh7aORggyXni0lt3FyTRB7oyy3b9OsgTU1ld5cMxvbQJshwex4Jl43wV5qUL9o43kJyemqFCn8ciUjz3MRwmgJUPhtMqMrXI1oV-lhzrVeIzHRp2GP_nI-DAQOtvg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 768, "size": 680351136, "isDrm": false, "downloadable_id": "2038449646", "new_stream_id": "2038449646", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=QQYz_pI8dhVCzjmGxrpYW0vfMtYPkDNjTb-fpHdR1OxpBwmgPo34BfUPXDp-qGlwjnjBqOhboUHsUkLK0HtQoYBfYYvRc579_ITlZ04aOuDgrANuwggRSE1QBWHAceaN3Wsa_vyqMbiNkIYjoAKkjUM2sWsQc6EsVxatUvs7vlKo39y29NSqI3WtIA", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=eSY4SOh6HV6sAwjpsDCLyQEIBxvjKWDNyNVk0ywuVB9e2NR4crxNi0A7fS9b9cTODV9SnK6WqGIoU5K_d5W3xbGiRiNh9HwNEiB-FFTp2jEDCXgSBb3bzGPVoA9OAgPMDQmAVoNIUjaKq_4ClM_rm12Klw8S2TVTPJO-bDhe_cfH32NhpAYRgyA__g", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=Dyz0AJtHmgrA-pdMfhuQqjU-ifZi_2gGfdjCLGXeRb_O6w3_gmAZYlkvLK9pJ5hDYLqlDbT5ZvSa49b3_SkjqbexpQrtfK6pSfZT8bBivhZ5EUYKDtgMMMUc6pQhIeWb9f-AXmDcb7bhkgkR4p1o3NrF-73R-cPwnUBgANYW_fLi9b_YTYtjzQidqg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 0, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122172", "new_stream_id": "2038122172", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=6duaMODmszCFcBEX-GqRhg11K_s8xXTmgwFNovToz_NGudUvqxbqAZ9VygnDamoMq93-o4blxRfy2QTw6dkX7aY3gwkikiYMDdp_yga9zOAuwBxXiF810Aza_q5FXxfjBtL5ChRrJDWUzhy0NeBxWfrL_jwz-KayPb1O1wi6qHUkHaO-Fw5D4rPbyg", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=Oh_zCFOjnkzKFChLIUwMXarDTVIvx-ij5yYvJgi-RmQJt5ir4rzO8EUi5LJ7RGOlxNmHIroI_wZJL95bKDxGH1-L664lnVw583QoyDPjOqfZGPKoQJGpBw1jB0eGJKR1nqZpLsBKei7NJnAPMA58LIE44RJaV5Z0MMT-GzVFkaSdei1wq4aC4RrnTg", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=EazYM5a-4P_k2k41D24lbSaKK5uRn2wzlrUUxYldYhJJLFlv8SoiizZdekngCkBMgDTGuscZAZ6gpNdEjkY2KY0ZJ9DX0imMmpvxqIOMLKFzbvk-lOPnZPoyGJx4Urk7jHEwEJdpCPPUzx_bgAwyRWtNfNc01CVk3VvaWzNGmMismFdQemXhs3TUzA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632157", "new_stream_id": "2037632157", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=4y1DT6zxGd1Xh6XqlQbzmarHaL4073vctti6fQb7ZajvtjufvM47nsRC0tQMCRZlIjL8HFP7offVC0LVS4507yho7WCt-0TI4mypMraEKFiuObMmFyIMzsbC1E9k3QX5H2f36yyaqmUFEuvdywWzCy22ougzp-J1SKExbNTdvtBOS3k2HfEZjhcrvQ", "cdn_id": 1}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=2EY4cTod1wWes4TdRFjn6GR2a0J1D3-Jzc1Fa-m7PEqRmEyHaMcrP0OrdZAAd_bTI872rlTggUeDa306ExgSgKDaroPcQQy66_4fp2WANPnxHC7zw_kwkws73p-ocIKPUttpKqQgXdKL_5K45h4ir4YzfTot5LxHdmuUR1CWv5eDeFNvC2-fmPQcUw", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786311&t=bdra7dVIs-8f4mXvJ5NIV92rsf2BvM_phpHYfwjwcCaiT59aDVyHLD-BfLKP2UYtE5rP_aikJWRCJ6s12EvNgsL2Zy967_qWNt9nO2YIggIkk1N8ErRlFKHRcBssdwp5lRdpDKx0u_BwQ-TwAw8Rodt8gluNZ9NBrPkbozdbk60M6u4Ph7U28NMpjQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887207", "new_stream_id": "2037887207", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=iT7Ahp_UV-cpnKttqxBFCtIwb7VIQ05lDGLWEorXwJuivSiUQgmhL_P6csCgz9K7MzFJk1ISwbBBEdqz03dqV4fRXdfLEMTI_-YeGwuEpiKCa-RmjDS_CUHoXqFBQ6gG-VbFStyDhvUuPA-Y4jZR_R9koICq5xzo5FN13C2nXMkT64dcJmxYFegYyw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=FOieScxIj55ZHUaMdwlPMdXyC5iE1wRilNPvWU7uoPFVRozxKs5XbMWtwrkSXaRThmeZp0LvJgFqfh6LfmssaK4RW8UJ1_4-LiunrM9uqF3rhVdLeVkbC5_E5Ytzl3AtsCwA7yaI0ot-jXOyKAhMZhgR8QWqXRu-JMaZuB-iOz0qX7FYeLyjn5nBaw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=Juvj3mt0vVl1dKDeGM8d8ut3xoOvrudTe2npWIXD7QKcdDegfs2-zOATX8lnG1s8luUWB1IGpBbe_qXVXIf8TpQ_I2CMV-Kl25f4F8nUQFtF1Swjv4RfOJPFgBH20iGtdLn5rqPqUM_7V7w5NZjQl0YpumO7kF2A3-yFjc63Kgq32Y27hkEjnK1wAQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879190", "new_stream_id": "2037879190", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=ZAgdQ3aL56U1qYNBdnxBW6m2D9bLnANbM-62f74clhIynCpu-pRHXGNjDT2YNmS1AqVF86nC2wwuU3Cb_d3TKGn40ErtINyQSthXOI21vtvf4iTHSQnjumo9wSHNZJDhxhsQTwaIzvs4fuNIXl9b5VmjH-EWGpiT_Dvmve-lv8dq2zQegFLhPcHITw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=Na6j9oUOzrx80K0FVRKl_jecnyE8hpoCpzzbDzKdtSY4f7EHkG1GYS_wxbt7B_QbWnoNaoPLmS7y4JMafZyLbPzohfQIBWXkfAogHxJkEx9xTWius8YdRFa12YA3mpWyBgJeV7u5PyCpJPQXvY46PzJd2rkBCSeTTyzZoPyxKZ14zbzd6heV-0OjPA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=DH2dkyeAIVwHMVdFMr6-QLvektjuCdXKlgS7TIilL9E77PZsjr2xCPnuYMLi4s4PRRX9inLeEXnLOgROmlmhWIu5tYmKQVUUrixcWm-r2Ez2xNbkI-3aL1AptsffBz2qt4Bt21PLiUA_tWJUWI0GUnc6quRj71cvV48KdI03bpQrDClh018nRo6JaA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621891", "new_stream_id": "2037621891", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=5poBp314cjXXhAgDSDdfQ7iD3JV7I-99-YckbKQvutpg4iegTZlLUggIuiLXTZ8ocWG3rWw8a-y2CDVJTXSttu8S05PxWfefUQouAxLJRkgmFf8YxO_yNDWWJ5DpDyHF2fWs9X7kipjxBKXxU-huEseNq_7FhbGBv5pSi8k3ry5L0uYQX8NNQHjmEQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=WM4nkLX7NV10NvRm1utwZJZ9YQApaY-UcxX6x-vU4E4zyLGva2QcsVZMoakt7JyIeII0pigNeewQGR0QdMbMZJNRyKjkUYInsBcq9Qw9sZakC_3--M17KrnPLObtR40nwoiLg-rc3gMJe-9TmACu5TIjDfsMjYfH64SOo91DS87QbQ5Dx63qXYxRjQ", "cdn_id": 2}, {"url": "http://182.79.164.55/?o=1&v=31&e=1637786311&t=4YZPX8OyDvKaZpTUG8wIZhiy7n31gid4tM-Qp2kGRymbqs1d4GtN1FLH4BXVTPqwjE6K3J0Ho9MCagYf7b0Sh8MX3rDB2lo-OgizukrL1jDKHiSmw9xImBy7WRuiKcvV-4n0Idm8e-_1_ooU4UTNFl6dDijKwtxbUAexT8wpqo847d2GFbopsPoG6g", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 5, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038120294", "new_stream_id": "2038120294", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=h0jjzaHsKGyVikzyn78X9Ip1ABFWWeVYoWugLCdVT97iU21jbMT97f4Cx1WW8XqZtrsnCujR5EMmxNzYbUEDuQk9TITSKN-UKums-fR9x2XDhWFK0VnJmCy-0LAQE70oDOlOSCt90ErRHIhRjO2v53h0qo7Oki_CiImvx4DUO7lspKSoeT5VCcyJrQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=Mgopl6DqcGxhVAHkHZ_md8Mm-IkuUrXcqMUp476UlHLMqL8e3S2oe81TMLsLXbl0j6LzYF07yLkkzNNQXVvAU3RHhdyIb4fzD9ZG6xfZLzgPkqJ7m5nTG5mTP_zbM6roUx6r0E7lcxTL8BxKcwThXFZSz7L0gR_npNuW4Q-G_TbUThS4kFlHrLZr6Q", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=s09qcP_2XJNjzwUwjNQ_k_8cRbl08a3QOSr-TXpQIy3roTDbOBqEZoRhJI_u0dqO7YlPphraber8FoFydn6MLqlcaKBvBu1Jz53MyUxx8SxfYY2zR2tTMhHIPkKxAiliTUpMxcXIJoR9ryi0DdtWXKIhoJbrVS0wjchzkdC85FzIACHowez_C4ECvA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630472", "new_stream_id": "2037630472", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=6jUpaUFQz5_Vqq5RefiR_aL1JW1M9Yu7aZrD7lOahMskdh6sl8mjKscNo8CidwRJkAVx28JG596sfIno0uerCNNw3iKNIxEEanPV2k96sbFUBZSaMfdiXE9pr_fK-1krBVD-xciDKYDVP8dYtWEVuWuupmjhxRSJk24U9-7X9aLiecqkMqExOF3N3g", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=umYxmz7NtoaDtpTYG0UoYdj0766YbCJ_7ydJHCQ9LUiUvwZS-zBmNYex9huPVH4-CbF2dzmk9-hj00qjDYU6B9sZyCQ3jvjkpP-PhOoHXbSVnpW9IxFpheApr7QdorUBSjIc766s0pbH1Hlw522Us_2Bs1glQRWFPQvHaExg3IZZpConhlv8eW0XhQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=H9SIbFdD8frV2TPPsZcifSBuC6LE1_NQv8JMdsgeMxDwZ4WHcATXUFo5VVOQehe_UnO45lPOGWiq_DQ1z4cIJluKL8JY2uIaGgzp9Dm0_1yY6PFNx-WTwz_ZsWFYO9j8NVguZvXrQ0NO2SyAXmlh1reD62qPUL0BmnIu6KWbrK9Ifqn9FlPJbU9b6w", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887822", "new_stream_id": "2037887822", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=eA0Q_zp3qHbK6vTrPMqhxPxZhnOllfLiKsQrN-OEUyd9C-eI9tMGIpzHKLadqYiWHkoZwxH7J1Axme48ZF9TOY5_mcxkK5sjLpLozjYuRqRLnNoL_8GpkUMPlDxI-2kPlnwbESfR9PZ5N9sfEPc-43ZBfP0rY080ICMiC_F_fMwggIsjEAZDsr-rtw", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=AInuENf6ilfXG9G1VbMsf63T6V5GydlUJPi2HI0sOSYiyko7rC85eLStkfXwVKHbYnB5CQ5EFp108_MmdJpoqiU5q3XfY4IpBFuwJuCtI1rmWMpBzq2MUVxhcqcDBLzdKFXwRKfzvnNtktrw7gkT4X0b1IF0B1-qlp582tElPs8vRXvYrIIk3LH8cQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=TySmIHZFw66d1nDZRPHYGAdCEbbJfSW2cfvb_5UyD8o1ZcB9tdxzsSrCJ9Vo0sHtmwop96CxRE8t9tjDyE76I1jXL-WUt5sLYNBaAiswxvjy81pkBiRESZVPYpwf-kOrHgiQx35vg4rCxlL7f3UfjNNUdqiHzhHGwmDYJkmVfXgPvbXLnQKbhGQvFg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882712", "new_stream_id": "2037882712", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=o1V325bAk0iDnmD3ScALvGhTgPknpFRuRaUPtA2-PKp6Ug-nEFXihvcyHoeXMc8arvXPX9kgoLrDrD0gxFBIxK57f9vZEUtYgybYoAkTsufZC2ny5okJXlS1iyXedq2P2iBwS3q6iUw9qOVFMNobQ2DM9fp6ciSjjFzieK4WU3ICBYg8QKqNkOno_g", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=-ZRAiQLHcgcLshVEkQOs_e7o3E5S77fQsMf-JHKvcHwyiysqMAUX_6ljfj0bTLkgfMuUX_aD3ItuQB3Z4_m9WnpZdaqdMAD7LKEciorkvW_ar5g1PgiPLy0rIASfjTGX_SLV-VJ2MWEtt-zETv3uzt3Sl-KD5q4_A_G12kPE5pSslm2GhyVRpFe5VQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=yEDMjPXJcO1U923aUImwIePRiDgypm5VbCaANuSGXEQ5urVqvVRZHrVp4adgWiVY3EawAiooCmjpxnzVOOpGc0yF7-tlCE4JviU0lgaajFhB6S4d2WYTRbe4Hd0-K2rOsu0yL7kjZOznVqs7oJ0GSDv_Z5D8oHtIcbfhdJunFetwzr5QZ7oqx_R8Qw", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621591", "new_stream_id": "2037621591", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=FYLO6cZFYjBpVnS2GC8XxRyTqwbXbyCO7fhgGox83HAv5753mVi9KdaNDuwaTsqSwvV8OyxuA804n1LauRc8sZX1a9zb6DgBX3MivgELNALkaBaXyZUVbqZBoCBD5rsuEM4VJWNa50CFA_e8Nh7xekmoFmd9YkIYxZxJD0M8SkPXapRZ7Sn6bF1MAQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=hF7n_ipSr0l4PfcyEMG9AjbEFMm1cgCsDMgTCnvxiupbXXXarlYubNYp_FD89fxmzeVRGNgeOUXe9ali78dn7L8TDpTl6v2jwvKpWhQXHF7BunZgIoaoangNE79GnRVK1W-BnvqRVwAdxzkA1u7Dbde35eDbjV4S_4ucb9caB2Qp3cfd9lTLJMyKSA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=7M--2fqmG4e0OiYchb4rXR0JfPl-z7RzQaaDdxbcyIAH5_8EWlXu27hsfhiV0ealmszPLcGmUJX7NTqdQAeDdp2MG6nvS-bQWhdtEPWGR3lWRddHaHNVb4p6VIUl2TuQD2kqbELr2_YxoEQOIAqbB4dW7H8L2o9rxY7W086ztMQiOlfOg6qLVP_Q8g", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 4, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122469", "new_stream_id": "2038122469", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=nSWits55qBNTW_P7ENPvCHcBWuDXY61r8EmFIB6FIHOXxng7-GBqcikTXL-e0IrzwQWXR8VUlrzH5ABdOid-D34RJK4wj823UygoBmAtfl0fLDOFfJaP_fggJBUDlQIxHl5DfPxncUIo3j56j5bQyw3kWkO9L-rX7n7BMueJrmXvSb7_vJi3VYRi5g", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=n-Ia9a5PrBtu3XX0mfexuawOfG7oHMlFaMsu0mmQcb0xe4YHyYRsLED4x9hum4I7x62hfXrEdIXXsWgTWqnojfSJCYnpmzfrwA9TNmloK9FYeby91WwHEtY63_6PSyYFgMl5EN_m0ZKqDXy7TdZ5pRiuJyE4vl9YTrzwIyOJQLQFVCeKkmYp9FZsIw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=WXPKM04ZiuxHzybVE1xoZfdm6Qp4qIdT2OkW5LVosfzWum6W6PZq_y0CF1NR5seJNtTc-cT-r9WKGjA9lrdilJEk9CMw8UoxCoHbGQjI4BMPcatS-8E-HSjyv4x4C-h72LaoIZFbt7Rw3djAAGEbgDVui-eMfeUiX1qM34I7_mM9FxU9421TWqq3-A", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037633762", "new_stream_id": "2037633762", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=8ga3kjTCtav3153QEoc8Noxa_4ITJvebP2dGbmO_P3_fJE7JTR1xm6RHDbnyvVrsxb1XDF1I0z1lanNlp-hpHBDabPlmJTjQDxKOG1gCu3moYBLZncXRcgNqaBQzVKW9B4eMPCpxy_XI9jEI3P4o7bXGtGCNS8dBXarBYoC3b9mu3pSQ9ZqaYRAe6w", "cdn_id": 1}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=iwDNPYcislWZVZIkYM1sg7cjBHShhsxIgE5mVPpTAS48s2_nEt8cKkV3ND10zAQaaUurEV__DqEByJWOwmHwAvaYTQVizWIyL98ShBQ2S3xhjAK_te3AP4OmmpsD4EBQaRKVZWkYF2oB7Rr_ou8V4ds2WPDJhh6UrADwPuwM8tRigBstLI21MmHQQw", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786311&t=n_NjljKueiazZC26NoOdnJkc7tA3SS8GmIqdM5YkwLJ2iSlUhF6kAWnW0ZvefMJkoYSkK90IHJ0uEBOI3HvuJVoHHUeekAlH-mKKBB6AsNBxuZ44q8iPtteh6ihufPGO-HSG8nzuXpI-sOxqnodUjlx8loBu-u529lpWR_nLzGb0WE7qJTr4BsfH0Q", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886203", "new_stream_id": "2037886203", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=4POJZ2eyZ1yk5w40xl5xGmgYOau7ZndMmY0hM5lkZBIaIJaxEa-ICfokr_cu6hLfCyC52MzNa4Li1OilrtGeH8Ql0M1FK7rioFFlNqtYcWKHKfL3quZfhD1NRjYKvcdBTKmf3oa-2XQm2d-9NBxXYM6i0SUDMqQIB02gH92sWCe_4R5JP1Kv9x82Kw", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=XIhYn4ZEUKp9nwXUWMe21ckfanMMEu5eI_4OY9cUT_OlqD9n74K5wQJAyI5vjlIKk5M4zgGYZxKHrJZvB7HclcnlSfaJn_j7-cGeQvge-FpheemJpGyBi6hxwgGd-lLjG2v85zkXdlhu0mLNCsuoY1LdScp5eDqgpqY9969giAMgNJojgjwXWK5hfA", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786311&t=cVPcnjYZa_emWyf3iX3oi1uW2RZ0YDJiW-_JoGBs3tKiq3LxAF6xs2iD2Aiuzgji-s_0kgkMj99-LjbsJTessSTlBc9C0Y6kDSyb2BkgFK7MFhFCA0tiJgzDQ-tN_rF5pYithXzIF_VlNt9ZeSYpYq6wA1cwKlj1DKMkiZN5Z4PluhVe2ORWkv2uwQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879896", "new_stream_id": "2037879896", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=w3iEp2IoGHRkRZ12EaabJs2O2p_d2U261NAc0Z50ox3kvF7v444JpphnGL7YUXKlPHpXk0VtBGaosTMeHS7O96eWjUkmAUxd8dC3T6_zTmaDBddN42043pU0gTap97jEG3_s7o6Z2yL1GJEdHDGk7h5VAurIkMc2gKEOBr8x8USsRWIxCgXlsMOIjA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=EBv9srDjAEu8McFzpZdjm4C-xdsxCofvUc75oRD1U7ZMRgtILKPH7wVJsWeBn74ahEtcKT9W6vfAObLYPq2YND87cPIHd2RIBb3uN5A-YHNXPTu0xT947iXdsh4vQ6y7-MTl4UKasAgkQ5I1RjeYvNlBfltB3Mz3Z3q4NemXw2rlX4e1YxyWbLcKjw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=zLiT0WymQ0nFyzHRZ6A6uSciPTWXgcpNGm7XNham5vSquuBdRxbtjQF9Rzg_0WJSuGjc1pgfV_hUkISEKhDyQFFfQXcickbxs8E7rAt3Pw29eRSCv0gtAgSqlj57FCZ3XKfSW2Pyi-ZTWnjXTBoqMmkly-uQPgW8WRbGKE4ycbnn3Lnt3oybDRQDNw", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037622635", "new_stream_id": "2037622635", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=andI3ACyqDwanofznfye4exwI4woAMyLcHzFiCtKHevQgwVP2e9RmEpBzuZvE10KEup_x_DATcDkVUmhhL1Vkt4hmp73-BVxz0Ue0PtBxoMpX_Fd2pkrfsy-kOmaNYQmmNO0KD3tQtVQqnQn0Uq-bThqdWfPlvT_7keakJDK70Yksupu0Y2GaSgKvQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=GGqGfVygIww7o1Go2bCguCjdYxb6-IL1ODtfMQ3mJbnLOAvGKfGtCNGGlIqp3KuYrS4DbJXhYQ8ft58qEZSf4cJu-E090Cv2ABqtWZToulBDYMJutdlceEQK1XI6ico9RLbEX-2ncXGN9yK9jZMl4RuA4jgI_yQf9NPCrMeXLCFfswbFUWNoVmiNVQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=Mg7U4PO-zrEaYQkj_45g6EPF_DOe2AVsAGpOLskGE_y-kupc3T72k9uBX5dtztYR9U_42n-fPgwZ0YW5xQdoT8Gjk2ZFkTGiIGrdDDwqTQtfMwf456ZE-5fN6EAMGJEqizbg2B2E-sxBdOyixH3i25EONCEpe9b3P4-4Qt7bPc13jEfpBafVRF7OtA", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;2;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 9, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037429668", "new_stream_id": "2037429668", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=VAKQ2oqhnEiF9TfNtFX5KDErxgrblXDXcWoZCb5TtAIp2AlA14gl0acj2D-hcGIUcCvVyaGAHSadMKtXPNfKHFIALNnSkXulxIn2Yka1_IPZeBqslCchIJdwlCPcbZqejKEIehjJBjD14lG5XH0ODeV6CbIxBw2_lEYCpOQ3WdKCbeWX1J9Ch_03", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=xMvLgmBOMaVHH8jOC5e3-HMZSMn--tWN7Ws5V8Dnh4v5xiZ3kLT8i7kZvbLbD2R82SdBec1Ct5fcCe3aiJ1HCI6lksi2vP7Dd3A-GDl_3dKr453ofX8VzPrR4T_6uUzyg5hO9L_MtIxaCsCQkswntTtoR0HxA__XsDWksIVe1vWPNUBZCUUmPwhY", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=e0KrqC7OfwM1lHf6OYP8kdFK_K67U3yvsKXupffcOBw_aUggVvQ4CFFSLDFdA0GJfv7Eq-jpuGV4P-_ax8vaAT5LIi8pVPiNfDWadrlP708dYlxMBQfEBcqnUY6X192OAaiPHC-E8BhurWSclBU7fw0CXR_NUKxN7FU2ZTwPbILFrVQZu0_vfNCU", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400409", "new_stream_id": "2037400409", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=sdt2c8J77keEheVuRwz2xLzLxEfJQFns3zEcrGAo3yLo_0tSq5hgR3h5e-DDCUFGsEj4-SvuacbBvwj3ltNmGJOrQM-QNwnO3oydC2M6TzW2Xt0Ius4ZvH5UJDTgjhgK1Yd-e8vsIozBtKALeyo2OVRxcrAY4UVD_yOgJPiCnG8_ZvtPjjhFmwhpIg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=wSUzZv01qTislUQSWZJnAqDDMbkzM1atuXbgxoJi6GJilOM1SV06xeu1bKshPgLs7neq3MnnOLQwQuT6ui2IXkdjBExgW1FFZoaifrZwCDNMythQuCZRqLFIPcYxqLciXeGUgznsmgILRhO2V76p3UcWacYqMeYZZYGw93kK8JCJCJ60IrXZv1dgRg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=mG-w54rSTS61wvcEaRaV9BsK9fJ4IdMx_8VgXajTzIr5BPFwcgtwtOiaym-1zA82XPpOeLBQu0luGYt_IRLfrHqxKZqB2M_wWUyjwXyHaSwT1jZIozPKYu7CW_LmnrkKeFzhsu1dwxkYFRwnDDoZU5w0LIPAMvhNtlg_f-wlEzgIZhd3vIXCZnRHKw", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;6;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 8, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2039673808", "new_stream_id": "2039673808", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=f-McyK-GQp1qX6YPkHBYoAGhcr1kXm5aD3liw3L7nObAHrjP_h8UMWe1BXM0qmkTYFR-hpNcuYXX_X7AwkpmS5XtMb5butU3zhEtnb0c7Ldq8q1BUZlAxGn5Dt4pFB7rgnGuA2Y_XnQ5f3--WAANXhaSM6svW54ks09N9nwpN2FDphx1famLCnnoiQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=acEBNPrFnFwn1WFjQ_0rEKNn0qB144iQ8y6V7wQd9-e-8MUptI1rKnOLsO4tVdZqNfosfsUuhyv-urCYNOXjOSWvAtxHxAxbMf4LTGcMl5YbrlAhszf1e53-k4Cva8eYP5NGsu9-pJOHVmroyQSx0jMBRMtB3sm6pW9t5Cy29j4SznZVME0dXKNeGQ", "cdn_id": 2}, {"url": "http://182.79.164.55/?o=1&v=31&e=1637786311&t=qmTEP4CLHEGUKZP4Z_rE5WxZuDtxjLsi4StlLXvFAGEjsHDb9u9aNW-m7NAzw0Fw81LI853464xoxE8YL6uEdFphI8xrV8a1V0K3aI-XpaOxNKxU72emLIz4C44OhT3W4pUisrB1Ka1Psv4fCEIe1LEmUFFfgNa3_hFjGXL9RMamxarO9gGHjhyxgg", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630286", "new_stream_id": "2037630286", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=l7zYYyL41J7L40BBiG8MbYV-vYGy2NdKS3j1zHH7QDvyFNyiNJBHS0AXjGkKHEgMwyTNae5vMG-geHGTLRqXJBITJ2ePVrRlN4K-I5LuO3HaLgXZsIVohT1tN3N0i9PqEhl3ue0sMAUxhGdMXejmIf8JsjaTktsa7XqctvDaUSNlHRh09Sd76e81JQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=TLd7prdJl4nneyy0aIBgUiyrNhD-a_kBy4oQWL1_WL1oPm9IBxul9WY9u4WyMxkEvdWUoahp2eQoZmS4isFzNXpmZDvSNuOUV3PoLtYua3cFHctCKNdFNNd6P5Za0Rsr24gsbcGCXXqk-sauW0bm9y3909rN94NgxgW4EJGN3G22VOcq2uxz1Wuzpw", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786311&t=rhnZ7KeaUL4SlQI9EyBplRe6_mwlgcjoOe1E4uqWGxU7J1LmXFw6eXFuhsTz5j_0fWWpab5RhaWqq68nq9EOJOdec9HsgQogFz5LPWnq5v0YupN8iI0jCYRktQEU92augWpC2CSAMqIOmd6vXFb93sYvvXJy4vO1w-5t2mwSkllYLwhPEjgbU8epjQ", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886411", "new_stream_id": "2037886411", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=6tB6kDqcuX3Zjuq_YsYJ5B7bqqJOYQw7nLL7JkgRfLhssPgUewpaSbhbOa_G4wFuiEzNBbps_YBQZb-ZEZ4HvONJbwUm9yauO2La3SLyXktSXXQjyUGz0YGxsKaGoaYoaC8FDAP-urPs3jWmcTMFUCp_NNE7ogemskIM-ihso76sfJg80y680zid9Q", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=pC7U815AEfM9MwkgJBxIYfikxSO5lr-hvs-IYz6u-8Bge_EpmBoiwU-8U5s2D4WkwkyIBxGCmepeMwR8KsajZa5FGBWhCCvJrlfAsLJJCmViN5C8Lr9qjtdi57PIW3AlLsEUr4svI0XbnaMx0CrXCtK3G6OhSGsW3gGdLhuFnYPs4Zscj6-Dbzd15w", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=pUQmu-OSfVyzI9q5MReULDyNvF9u2QNqd7npeKMrj1lXyXaci5-7_GRa1qgbizaT4MTT4MpJw6gBCpTnCz2KFp8iLgrBj9Lx2B4NaDwCkWZeswLsfoVMqML2gQkysvia7Mr2jvqydHf8oPbg2rXFwjUj5xPL3Gj2VSJUCZfeh1tNuQaVAeAmx-S8bw", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882117", "new_stream_id": "2037882117", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=-8-QH0-Oz-WBTwvocGgeL_ZejC-kzSBhPJd8oAX3AwASyohs7TsEMTs1aXUUR-guFbzRZ7Ass9k5s_UMXcU27lV3F9jQGJq7VAN_TwmYUwKUoy03GNoprElQj9CyHagWEIW-JX5Za2482wmtqqB75X61AjT5tuC6ROw0eS3dtFApm2piBI67N1oDsw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=LapSRsj4Pycs-E_5PYScVF2BV2vP8-sn2HHiP4Ej4y-7gr1O51SJwg2YrdhBz_ST8HlfcxHZlCkbGmANXDQtQ2bJ-v-A2g-jpYs9dSbqxBCgZhq_8d27pQ5BrlrTGtWF6BQXjKQuOHDJaeV7RFTpaGGfyDJJpxFAXfqXtfzAdiA2skx5GbNR69ge3Q", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786311&t=xgYZS5bHY_NtuBWtG-ClPzAQcpfMm9JtPoeFXCimFHcLHW7AchZ7RDd2DpupJ-8IqtplHTUc67gRumKSRq6erLqaQjsnX8F5RSlzrhD3TC5iqLgjp1QXZPLX238putRvKZpAknrwmXg0ISeOu-KUY6vdyH1sSduzbLaS58gLDSEFwXJZuYqk_U0gmQ", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037623180", "new_stream_id": "2037623180", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786311&t=RcFVk4z85RhcrQY_aQRWwqBULpgCKtrm3-XYgQCRLvkripygxeF9ZtB0vlZwmoeV9TzAuBzsUqGi9vokX5cZ_Z5MqxSgpbBwbJt-2UHMMZYRsc0RaILjvcxALvT8dWjtQ2eFcvJgaImr_S3Ju4HByg-Hpjl7pjxkM4eegr2snFBcug8BdaETf3KMfw", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786311&t=BwTNSDvAjx_izBZRZT0dgjFEOqMChYH_QricBhrpwXvoGZEHLEV4bOppjb_z5OAXC2fn7Lf2sJAdeeHvrz75C1Ms2_OHb7wlljDBQa6U6WhaOpbLXZ_s4kFUTtOdy_y-432bkAsVFtzibrsSkbEcuCvgg0mJrRoCqmImQTPgrtzPaZEvjLuifyDaEg", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786311&t=R7iMQpznFgARDKU5cT34Fqux-PZ3_aWyGVmB5kFPTxdylH_MrtEXUz71ZMJ2HK7hcrQNKrzmQj5qCy_10XRwqgZsZUgNJkJBkE_Fy5Z26wJE5WgAqN1Gb4wQmYSuRnhDiyDxlMyYZ0fPc-lzqDKA9HMAsgVUIU2p762pcqY8vGgrwY58l-xRwBt_Ig", "cdn_id": 3}]}]}], "trickplays": [], "servers": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}], "locations": [{"key": "1-24186-high", "rank": 1, "weight": 140, "level": 1}, {"key": "2-24186-high", "rank": 2, "weight": 120, "level": 1}, {"key": "3-24186-high", "rank": 3, "weight": 100, "level": 1}], "cdnResponseData": {"pbcid": "6.tvceMI-IgkT-yOOs4yPgTh-5bQxrwTKc32-qNCMu7mE"}, "steeringAdditionalInfo": {"steeringId": "6.tvceMI-IgkT-yOOs4yPgTh-5bQxrwTKc32-qNCMu7mE", "additionalGroupNames": [], "streamingClientConfig": {}}, "audioTextShortcuts": [{"id": "c6f13ca5-4d3b-4ca9-b157-df814fcc1086", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:0;1;en;1;1;0;"}, {"id": "623708f2-a496-459c-b8f6-d38b724574cd", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:1;1;en;0;0;0;"}]}} \ No newline at end of file diff --git a/manifest_hpl.json b/manifest_hpl.json new file mode 100644 index 0000000..0cd2391 --- /dev/null +++ b/manifest_hpl.json @@ -0,0 +1 @@ +{"version": 2, "id": 16377431109789, "serverTime": 1637743112261, "from": "nq_cadmium_pbo_manifests@2.107.0/pbo-client@2.107.0", "result": {"movieId": [80230399], "drmType": "widevine", "type": "standard", "drmVersion": 25, "dpsid": null, "clientIpAddress": "45.115.91.43", "bookmark": -1, "playbackContextId": "E3-BQFRAAELEBYMLCvIrm8HYe2sPatACWGBxptCQu4gcfAhwD7lmYVQujl-y7aC2m40ZYdaJl_MZChJTZF7uBHS5Rvde364JEFBmBTmVOXFiw7ZjXxaiI1pEIBGkZJYbr-6HOj1BAIoEU8aNDCdK4DRuSdQlBAUMWcRhDSidBwjlWqCBzq5TObXOzE0xq-mU0y_e1iXARGX8m6Lq3rSQ2XLephsJaaxJskBx5TM2L2mVI56QHWwVucw3Jv29Wz_jN-RHUym6kg5R3JBrsPfGynwU9St2d7MQC7H-Cw5L5zSjwNGb-MzjWM5KemlZ1xhrOIRUfkPxeRnMqwPEpl333ZHbluX-AVUBRBXjTTNJh5itquU7LplaQ7pCn8QhKe2CDJT-OyBG6WWaGNIc0jTRY6nL6DBsHIl2EiPwIZr6Ctwgy8dRZc_3fCtSRTxpMVxg80h3O3Yr9TA37V5Q2bIwTdw2RlPHSAYe6QzESSkHSo13ooNMu2MQ_OA7InLxJ9Z-7SIRnFrKBXSLUOyCGv9ZnwmjD8KBuLW8Y4QpQSamjWHnb0o-EiGcWOMlxYBqGAt6x4gxWBLvU9MoS7f9s1J8voqW6CCB8behsfnSZItkcMi1PgiG4tY3StH09VpD6wdoMo=", "links": {"events": {"rel": "events", "href": "/events?playbackContextId=E3-BQFRAAELEBYMLCvIrm8HYe2sPatACWGBxptCQu4gcfAhwD7lmYVQujl-y7aC2m40ZYdaJl_MZChJTZF7uBHS5Rvde364JEFBmBTmVOXFiw7ZjXxaiI1pEIBGkZJYbr-6HOj1BAIoEU8aNDCdK4DRuSdQlBAUMWcRhDSidBwjlWqCBzq5TObXOzE0xq-mU0y_e1iXARGX8m6Lq3rSQ2XLephsJaaxJskBx5TM2L2mVI56QHWwVucw3Jv29Wz_jN-RHUym6kg5R3JBrsPfGynwU9St2d7MQC7H-Cw5L5zSjwNGb-MzjWM5KemlZ1xhrOIRUfkPxeRnMqwPEpl333ZHbluX-AVUBRBXjTTNJh5itquU7LplaQ7pCn8QhKe2CDJT-OyBG6WWaGNIc0jTRY6nL6DBsHIl2EiPwIZr6Ctwgy8dRZc_3fCtSRTxpMVxg80h3O3Yr9TA37V5Q2bIwTdw2RlPHSAYe6QzESSkHSo13ooNMu2MQ_OA7InLxJ9Z-7SIRnFrKBXSLUOyCGv9ZnwmjD8KBuLW8Y4QpQSamjWHnb0o-EiGcWOMlxYBqGAt6x4gxWBLvU9MoS7f9s1J8voqW6CCB8behsfnSZItkcMi1PgiG4tY3StH09VpD6wdoMo=&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C"}, "license": {"rel": "license", "href": "/license?licenseType=standard&playbackContextId=E3-BQFRAAELEBYMLCvIrm8HYe2sPatACWGBxptCQu4gcfAhwD7lmYVQujl-y7aC2m40ZYdaJl_MZChJTZF7uBHS5Rvde364JEFBmBTmVOXFiw7ZjXxaiI1pEIBGkZJYbr-6HOj1BAIoEU8aNDCdK4DRuSdQlBAUMWcRhDSidBwjlWqCBzq5TObXOzE0xq-mU0y_e1iXARGX8m6Lq3rSQ2XLephsJaaxJskBx5TM2L2mVI56QHWwVucw3Jv29Wz_jN-RHUym6kg5R3JBrsPfGynwU9St2d7MQC7H-Cw5L5zSjwNGb-MzjWM5KemlZ1xhrOIRUfkPxeRnMqwPEpl333ZHbluX-AVUBRBXjTTNJh5itquU7LplaQ7pCn8QhKe2CDJT-OyBG6WWaGNIc0jTRY6nL6DBsHIl2EiPwIZr6Ctwgy8dRZc_3fCtSRTxpMVxg80h3O3Yr9TA37V5Q2bIwTdw2RlPHSAYe6QzESSkHSo13ooNMu2MQ_OA7InLxJ9Z-7SIRnFrKBXSLUOyCGv9ZnwmjD8KBuLW8Y4QpQSamjWHnb0o-EiGcWOMlxYBqGAt6x4gxWBLvU9MoS7f9s1J8voqW6CCB8behsfnSZItkcMi1PgiG4tY3StH09VpD6wdoMo=&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}, "ldl": {"rel": "ldl", "href": "/license?licenseType=limited&playbackContextId=E3-BQFRAAELEBYMLCvIrm8HYe2sPatACWGBxptCQu4gcfAhwD7lmYVQujl-y7aC2m40ZYdaJl_MZChJTZF7uBHS5Rvde364JEFBmBTmVOXFiw7ZjXxaiI1pEIBGkZJYbr-6HOj1BAIoEU8aNDCdK4DRuSdQlBAUMWcRhDSidBwjlWqCBzq5TObXOzE0xq-mU0y_e1iXARGX8m6Lq3rSQ2XLephsJaaxJskBx5TM2L2mVI56QHWwVucw3Jv29Wz_jN-RHUym6kg5R3JBrsPfGynwU9St2d7MQC7H-Cw5L5zSjwNGb-MzjWM5KemlZ1xhrOIRUfkPxeRnMqwPEpl333ZHbluX-AVUBRBXjTTNJh5itquU7LplaQ7pCn8QhKe2CDJT-OyBG6WWaGNIc0jTRY6nL6DBsHIl2EiPwIZr6Ctwgy8dRZc_3fCtSRTxpMVxg80h3O3Yr9TA37V5Q2bIwTdw2RlPHSAYe6QzESSkHSo13ooNMu2MQ_OA7InLxJ9Z-7SIRnFrKBXSLUOyCGv9ZnwmjD8KBuLW8Y4QpQSamjWHnb0o-EiGcWOMlxYBqGAt6x4gxWBLvU9MoS7f9s1J8voqW6CCB8behsfnSZItkcMi1PgiG4tY3StH09VpD6wdoMo=&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}}, "isBranching": false, "partiallyHydrated": false, "maxRecommendedAudioRank": 9, "maxRecommendedTextRank": 0, "duration": 7051000, "expiration": 1637786312232, "urlExpirationDuration": 43199972, "manifestExpirationDuration": 28799942, "viewableType": "MOVIE", "isSupplemental": false, "packageId": "1674268", "drmContextId": "1674268", "eligibleABTestMap": {"39008": "1"}, "media": [{"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}], "defaultTrackOrderList": [{"mediaId": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 0}, {"mediaId": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 1}], "timedtexttracks": [{"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:0;1;en;1;1;0;", "isForcedNarrative": true, "isNoneTrack": false, "language": "en", "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {"simplesdh": "1176827093"}, "ttDownloadables": {"simplesdh": {"size": 16161, "hashValue": "MjR0vpt+zo1jyhZ3VMmogCS0J0Q=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=NYOLstb-qZXnub9aWj5zFlbFRHrES_473raKmhV0VaXiw-4u8jB537z3Ro9L0uo5vGhTBALKE8CghXikjH084KKtD7e38ifRiTWaz2bgGYKYXglBrxvspUq_64Q-GfCH1YIsc7qoJdpjIbJ_RjisnkaNbBHVot6hupscb7RmYmlBK4cmtaOXPds", "2": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=STkwZgMOwIhOH59I7Rp_RMK7eDjjEjCWeYggq6POBtnQZNrdruh7iE2fHIKuxo3SRGPW2BEFy1EDiG58518fICreSlOWo-JKU-D7eE_yjzk6p5yYWg82fPSBEAHMN0BWpNT4bMiTdC_OKVwM8-1r6F7KwoPYa8vyk5W0iKRf_9JbDt6PavSJ8eE", "3": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=8Wjr_q695_uAaP3aR1-EtSllWfunpi-C6ECGoe-fPiC38vBH6zXEU0kA3UmpJJN0GIvBlHI4GK-l256lfoI5YNgn8TTP25Ikjhkph5KJQn13cINmndLCSEwMiFAHGJuIwPEfHY2eJ1PNXrFdeoG9CNfhKh2274SF42R-mdOnUw_zPScP9rlGdmk"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "ASSISTIVE", "rawTrackType": "closedcaptions", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:1;1;en;0;0;0;", "isForcedNarrative": false, "isNoneTrack": false, "language": "en", "languageDescription": "English", "isLanguageLeftToRight": true, "rank": 0, "hydrated": true, "downloadableIds": {"simplesdh": "1091695175"}, "ttDownloadables": {"simplesdh": {"size": 89685, "hashValue": "+ZXBbL9zcLzKphEOcnQDDpe/j1o=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=r_zFo4wY_rW8JCs4lrzfLGAIkBrPKBOgzPqsCqucS9Rb-0rxqHKTQtlxa4DMhahbuWbnz_6drgwXl9ChEq0i512T2OP5UBHLIS8770YlOBi6zzETXG-Bwpqm_DWYW2AbeXkzzRvc8tvTpDXtkbmfkdoLWdzoVM7FkMFZZ40038muwVxcr--yb3o", "2": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=3vAEgmix3DDMyKqlAUDBLFg2HEEGkIBwWvQIn2Ymp4K8vtAi-8m57-GyhEdt1MQ9rFc65SKAiLPNEEXq05NK1rzSlh7ulfkbiHHu0ptGRv7zJmCsiIZfhY1j8qnBuMLnD7zHZvGbx4NJBZ00KHdwsE-I4Lziu7rZZAFHfgOmG1iM2o_5bITiDdw", "3": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=mKwP9OzMHR0sY7liypAbkrSUVm11d3Q7vVrX3w1Q7Xw5HLdrLG6LUoOeI7fPWcqvDd2PtqA4boSIyUIOMkNZRNgYQ15UdNz2Fa42KxPZeOG-6LbMHz-7loaKw3RhYlhZ4qnulDVByM35hyYaOMBAn3h4pmd-c2o27Iq0tqLP0qfJjjOI2iBIPi4"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "none", "new_track_id": "T:2:1;1;NONE;0;1;0;", "isForcedNarrative": false, "isNoneTrack": true, "language": null, "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {}, "ttDownloadables": {}, "cdnlist": []}], "video_tracks": [{"trackType": "PRIMARY", "track_id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "new_track_id": "V:2:1;2;;default;-1;none;-1;", "dimensionsCount": 2, "dimensionsLabel": "2D", "stereo": false, "profileType": "AbstractDynamicEnum{name='VIDEO'}", "type": 1, "ict": false, "streams": [{"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6350, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5311955021, "startByteOffset": 97454, "isDrm": true, "vmaf": 100, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1806783668", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=t0yxuewDDVjBKX2u4ouhoLyImW1SBHLQ91n24fRk2EsHw6aw0Z8b3etZ6vY_DIoOAAR84n-vyGynyY4qiwtqs0ZkCUWC4DqKU7A6XLlL8FeHZvBNaPAd0sTvTzRIivhDdoeLZ3tCJcIYvn1_zZplLyrUvHZCzD3nIgO_0e43cHc8LmW60dBWaHgSfg4", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=6x1Ju9KkJnhypl0BfWNT4wK0WTgGB1r00xqli-enoQmssZ0ddC2Cg_3Zephs4IEEkFomDyjwXhq9fwEtJxb-LygFaQgbAIzQqlhtgQ-ci8wFBGiII57pF-sCzeCDTnKyykZOAXCxnI0jMADinh7SA8KtCYb8x2yU8RhF_oBIzELGeBfsDwT35-ByZnA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=hI4b5u8J3uGsvqN_2sd_X92q_1aAZMtbIujcpTteBcNyiy0n9QTSI-IACKe70a4FvX36_HqbC3X_jDcOXSzkU3ueid0s0_SCSt-OtekILbu2GnhQvsDkLfnhj5mRD1mqvCItXX4WEZT5h196khPKEGchxZgRhOTKk-c_nd3L0VcuAChmZxQykQfX9tU", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6900, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5680647092, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1916117199", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=jMOGdafoEfAXayKKN2kT0I1TZWqZuK_Htiu9Qvje53Ny33AxhWXGq-D21yIvV1VbalsFGQKGnt9ncceQb59Sa4XChvr8sONhIuc2In7qHCYp4dYarE9fc6GuXMcO_-Pl4qPP5tw0zfmnYmdjHiOKLq7vOlgjyoR8BWIzyhlWmfaMRzPHb3ultDJxGaQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=JolGCpkzAgbCWw_hLb5mZU3fnkMWSaTxMFUzfVSSOyYmr3tUBQgudrX9MgoFKTSibbEw0IlpN7KUOM-WqoNwzeTqiEilvnF7XxwkBlkiyXcHe0canAqjYwhwqrNVgPi1puDvt_HdW1Ol29jiOkV6jV9QE_sNLAvSdpbFk8xAtQB2EQPuFshg67e6i0Q", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=jPH3BUgRpJaUCbRtJvKUqSimg3hN-LUrTwcRsSBRvus6hPg0dczG1TKZQuKpQhECo8nb7_eMov66X_7TLtuZXhq2RpWAU9jFXnQXGhs6jHVen2XDdfKKH6jpUhlmrebhTjZq-kCfiOHqkyrGazHUsD7jb6P5tmw3Pzsiw9er8cJJVIQQfxPHhTVdSYw", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 7450, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 6021494277, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1956403691", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=JeJNd_9_5q2Ythr2KjQSt14QOwC9lJw0eE4UaxAu_QhZENB5bAtH10YLoXfDVL4P-hRdhhVMLZ9he3Oq0fLbEQcHbSoJasbeD-sWf2S1cfHZKczBuwp2_QZlF4Kj-4qhmPfmJJpYDteis3ckjlbgPy4Vxvcl2NN8U9Dz-ktdhgdrHgSDwccCkVLgcYs", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=lmWm24kHe4lmQgjAEdrVp_lvvw6HLdpByjCKD6qno9coMmkAZcIUmLV5W6sblqxso7Ly37b9qk9yiXmy-r1nQRD5_g-e98j1Yg7_2ApiiqOzCG2Q6c5X9WBHBIGP_SuEZq1asJhFYCtODCH2N4fybkWUo7IRRKc1v_w-LzcByyVMtDU3AfiiudBg710", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=9bjKWTPcAROh2vbOjCziNxscJU0yScRoXllj3jzkVI3LWedFuwha9U0hGqKCTrqDlsjlxGAo6vsJvLJ840FavDEn-jUV1aA6jw_OOHEJMGgVRBLB3y75JYss_80S9Nn6RpY8PScuyc5pkzHQWgDHZ5ZUYqc9kCuseTIffsW5YwSRYvjmcpDZYKMj7bg", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 8000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 7039207021, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "388580917", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=C5eb9cd32ErxSxiyu04afxK7Qdl9uTdo43B0FtSsA89lsbRhMpXX2hUupYlL5kE7icCnVCRUjcm0uP4uR2j1ynwecz42YXXWKPzD8rMwxSA--4XKfPA9rGVecg4U3o-4w_gtrEzi3D5cnCDCBEDNj5Q1xGeB5cW846gbCzsz5MWxluhMPgyRu8fXbA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=xvddASM0zm3FJUJXjt3mqBX4RgdCXXj1kFPOXw5HuovsyhvcGuynVW2JZiu3lC_iZ4973squSlxUZhJO2AaVyx2Q0aSGUKk3J4xPTHY2CwNJMNe6KV2snjcTbqWjGhYrQae7I8gLkiG2M-mHCMWkcH6XFErhrOerqht4-h3ugnyqEVvpGllwaUQ9IA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=JPd-4nhoWCBXECp7uCJf7cXvaDkT90iAUrRrCIPJNRe85cmYeaNBBPE5Wn0yw6ImrQ8m5kYXrDSUHbkN2cy7gwQfx_wMJIVyqaCqVKnM_LdPtM9kDR95FRDx4KERlHkNE80cFR8Ip7AlWMZTkNpU-ldSh46uURsCzPPE4DfXfImsZF0ewTAmrBSYKg", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 10000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 8676621644, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1970848201", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=lPzjpHMvY9-M8eELDyf6LtHGF4j7lf4zuFUj78T2ytsRF_MaicFrRI6iyBm_m_r-uOOsYUrwPWhnnFbtdP8_topOFoFyaqd2CZ7Jij1cuSv_OrxcvlKnCYr-ff7eQUQjD5DsEUaa5_kayDPq0vx3WIu7MvLQpUjNsKbB2QVjIGRf92zEROWolezvI6Q5", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=69-PpXAV9UCXQLdLMwFH3tiCbrY4RU8TYywlxRzjGuMlTaco-1AmSApkHHmJTlr75q7PUcAkhzm0YFg408Oj0hHeO7JSwCT56bt0BhSd65ALGL1VCQBv6H5cyVADs12JYmt5BQUwWr4eGJfBW6ap4pEhsNvwlvc4qXGsfwDk323R-Rnf6ddqcsUlN3h2", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=rUP-t_hCV7NBgcmHNSFE4sz6_1o-K4U7a3PXpAf4Xhwiy6OQb7jcgXiDmbErPqdrE-pQTL2xya9ROUh8qQV1zWfEViC8HNClKIQUJdVPET03-_YBrK--9KORu3MmqEDY6OZLcjnbIzkIwGfAomSo4hCuzeUiMXYFy_yoPpoSYt1Gn8jsVMjNEvp3hKiM", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 12000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 10281705940, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1783080613", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=D2N974eRlTHQOXEE9q-GK9jwvfd1b2wTXKqXT1pBF1x-eQwAU2viXsFryaaIl0Uj2T3HCAJpwe4JP9GP3skQVEVOfMFYBU8ZtaX-aTmgWldigTH9oNhcyY_T1v2pKE04wqbe1jGglEm9Eoui34bQhwMKQjgNH2DUj5NoiawmSEhs0zu1VMehF_zvInmV", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=RpXA7yOGfrZOv61QrxDlD0FKq_GmsCvMQu9aQ0G0KYQsPFhDYBXNg7b5_PYMWFJbNuCP5_56loMBOar-DEjxE0xBrVrIioZQL4wqKjZhbyboVLmGFp8eJpDWqHvKZFACbYNVL8f0rHbUGNwUJicGYI6J21_FB9-HSs_ctgBxHbQd5u3ckV4lJyiEdNrk", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=s3SZXRGvu_a78yUPGbM31ZbwI0RBsuB3M1XCuIDIhnFN1e1fepR2j4L3f824V4bYD0IWLSb3V6-7o7PomCOOP7kNOWsnmF5bejvjNkTTEvABFigG8pnE7Q2j6p8CrNgjn2NGfSf218w7EPxXe0O9NRzUeJrjjjNm7e9UejqBXnqtcTuIqoR1D-Df6p8F", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 16000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 13371437321, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1109298487", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=SgBZljWl4e8OV5XTC_RlQyC_Ms5IJzEQWe9R3CRkGdUiIMuRiO90DDZb1yTqaMPgTRoEnmVNABTNi_olpAWiov9_7tQdvveQ163vqwLVoq9nu-CU6qRV-FtsifZCAy6Suh4yK6YvaJq1BlRKxGeDIooBVKN0ADspjqBW9STaNKre1jQ6hLbdlxAzgbxU", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=iHVGRbO3b6EsiSkBWCoMpMYO9O7OoEccIosmK9zy7Z5bPBxLHWVKpvQovkT0aWEZtxGNCvpJn8tTijKfiUYdnkmEEa7QQf5MD_gtBNFIqEVzlkURkQ5MxB7D5Kt4S2FDpkrS0ZTkoxL-wI1amZU_DfpxZ2H5XJfXqe3CfYcUI2O3HMblHig8OtbHOxVH", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=sMWhfV1ME2ZONccMxraEr_evqdMxhoXY2JksCHh4h86KpRRGQXQWHnVfmbK6RqLB2HAumOrNORK-Vv79v1eRE3lmzppsRHkyyFV_-jE72sC-jv4UZ3pqQ3nf7CVxhSwiWcIk-R9AVs8DgO2vv4qAcExeTEfO9YJ426SjiRv_9S3jgOK91aShqSm6TJpb", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "profile": "hevc-hdr-main10-L50-dash-cenc-prk", "pixelAspectX": 1, "pixelAspectY": 1, "maxWidth": 3840, "maxHeight": 2160, "maxCroppedWidth": 3840, "maxCroppedHeight": 1604, "maxCroppedX": 0, "maxCroppedY": 278, "max_framerate_value": 24, "max_framerate_scale": 1, "minWidth": 2560, "minHeight": 1440, "minCroppedWidth": 2560, "minCroppedHeight": 1070, "minCroppedX": 0, "minCroppedY": 184, "drmHeader": {"bytes": "AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQAAAAAAWi+gcAAAAAAAAAAA==", "drmHeaderId": "0000000005a2fa070000000000000000", "keyId": "AAAAAAWi+gcAAAAAAAAAAA==", "checksum": "", "resolution": {"width": 3840, "height": 2160}}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "audio_tracks": [{"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 3, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430558", "new_stream_id": "2037430558", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=A-WkqW7Ef3t67pjdsyc47b2FIelR9kIRA0RuWlfV_uAbSDtaCIlSCotVmAdOhEPvc6nhVjY5HvqOgdTaMqMybPN0hpdIOziRZInfgtqXuF8vFJCh5C7zI1uBMESewngJJJx7rd1nGyx6qvTssz4xogg-3ryvjw7KBeLYGrAdGI_l_GOfGQQ0O2m8", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=noasWu6BBCDPf_N9vWNOoGF3cX-YG5JcxkBAyr2DujsdiALTMRnZZtHGye9dX7bP4lm4eyIVEIJ2a-MpOBobblputHXVhdVXBpCQ-ZOaAYS-Qai0cJV3lfG9JXWk-DLIp2k5QQHK2Fe_gyVCCZCkgJuMqIg0wL_D4AHGTiizpi2UWiR1FAi3jlc8", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=SfptrjleKRXSEyIvqLYN6kYqgXtEVy0oYSF3SNNOodDuExwgqC2VTV-ez8FR-WeF22dBid9bEUO0zA4NgwpPQSK0TWvbUfNen1wF1GxxYMudGl3BhS3EsbRPszgWQjJWJYhyOZq9V_Q0x6EcjlMlIWiPvy2aaUFzAgpXDJRm3t-ytDjcgLOzeTPi", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037401654", "new_stream_id": "2037401654", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=hw27X5D0zQ208jQ5604lEaeESIXA0Q87l8R1r7AE7jSejvp3fY1XRHm5Wqn2D6YVECI7ew5iuKOkSLEuqGQ_TVHqptTprLiPPRf7eVu8zyOAa-do4W3Akpod5U74RjvVBCMf5ZoprNXnsXOmG0FI5hAki8sy9rSTkJmR2gA_DMR59H0GrmLS09GFSg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=zh5z0vNCkU5I011IyAPiY2eh2J2hRmxfZcFMz2lXgN-1kyENyEj0VoXzVs8Y2TJhf8_0KOk6sh8cdY-0NJ0tABvQfUDFpbdIzHmvR9xvq_yQLgxlArmph5ofsfVewVvJ1j9ZAbTKYRqFGwiW_PeuXN0pGLMYRIEUByJtqWY6Ak4M6P8kiu2U0jbExw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=VOSSldSFAwbXB9DEFSlg4OQl3Bt-Kbd_xvpnVRwOdnwi9MrRsQhwIuZ8Q7fKgFmZ3wjcjfX8j8LQzcw0cQhqe08v3WxTZw4TbtsnmAuSRagqPa1S8nnZcDyMFnRqs2CZNTn5wU5UjUs4BBW0WeItd4Xn2K9oz1IYGA_2Kgd12g1pFHWrnQV0t7wlYg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 1, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037426205", "new_stream_id": "2037426205", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=U9gqC_JtKtO5I0FNvDKAArXTUziDi5tOARMfUV9Ru5KqEUeYaUqpd5B1EJ4b63TmrAhEEEeXMHHhxAllkVsujw8zDg6gMcaTApBd5i0oas8Ui2-ZoD1hfPt8xXowTSNmQipVVF_tI7BsnffLo1gIYb2k3EFkIjVHJdkNvVppYoEktWRnfGGkAv27", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=zkLMAidrDSpzcG0hzaqYSPJ3hYnC2AFp-wlUZ_A_Bw9qfk1Z7JWkEIHpl9QlCv3-Ckplr07em3lAHHsSScz7YJN2ZNWOWvwQTIuUzO2jsmhmbgaGbLxlgwMEESogm20em-uu4xW5dm4Ndol9xOhbYe4gVi3uYZzdjzfalYYv9dYn7WMbEwE13Nwd", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=xBtkfA3oT-JJaY-D1QT8AarM8KWB0Pyf0XCdgeC7yENSzqArrtV7El-odVn4WGmfhmfMMEgxjlTiIaJqESQKRG7aRiOXNCIwzpdPZiMaXyPjJ140VEGc_-I0c1-Q5dWSBTgoSvSRaTPB5s62lcYKqIIwhCQJpGi5MmoxBveLLDWo7u5D09dnSfCE", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400705", "new_stream_id": "2037400705", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=mUXoyuBS2Lh5zOO_zPDcRdwOF7VN1hr7Hw8bxKCnZxbM2R_ygZlNZyET7ZKpwD1A1VPijzaukej6iMyKt_9HqcxQIyGN2cqfHXdp-V3zzM8fFUq2PDbnM8vrOY7RgtAFxdQ3fBmAoUFI147mkFANSUiZZMyGzxgaCwAOQbVMxoY7DK7IorTq8VkhKw", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=h_EXtnqtS6tzACZL_F4LzaynYL65zCZtawZQiqRlAQQPXjsFiWDc8L9d6xEO8D_b4QJAqW-JQjR1nu2IV8tVokP4_Qa4UpLw6LyDxC0AJrzaad8O_uYn4VgP2VS9wN8X1TwpKMEtuNUHFsuokZ1VRvpevThW2a9SkUhS-qedCpQYe0Mi8yiwdIEvMA", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=buXHwqklmcnSvt8b0W3MqwEeIxcM_zT-uJsweLLGKHxVN9HHlAXcLBIBc7yul-0Nb8eZca523NM_LKCkeyYAiqWc6wO5o9Q_0NkEWZxzxdBLfnbyaVvrx-dckfyXZFqSLVCdmvecIPhANEwyScssXoKze0oNdfP8JA8RB4s-Qlepn3Ytq6KpObzWgQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 7, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430888", "new_stream_id": "2037430888", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Sd83iI906YPk05utgpwBFH-mfJffEaakcDXmSyC_AGLXwOU-TSCWKyAOkigeQYSx1NVVuIVj6yMuhrr-n74VdFsEDVLMRWbao7kk6FN7yrrSoUb-XOWGRQZpAb6Y0XYNq5jQlKfcF15yCJOkF5Z_yNb5j33W2G3y68eHVW3fcwHW1Ku3WtlE5yKa", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=vjwC9njRtSaBOcq3U4639gm-hYsp_LAXu53RinaagY1gxdIeq7QGVQFuCiIHc3oszpSFtSsn6YvowOb-QbpwmvNdO_ObE-hZ27HCxaG_7HvUJt9jUL6rvnlWbAxxAtjDqGivtyvOy7d0rn9ORYOkn3hqZ9neyod9dxganQ2yuph6EPyX0HcUQoVr", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=Tj4mO4bTxUYHcqwRQK_hwIzhZylMvKuxBngUC0Pyd8N0cUptFdbnWJ77ly4TLZGPTaEws1kSgvmSqg1NMp9oyh-Vvgv3yVUI7QIp6p4dCooIh0iiS8XofAc49ktOZFaQCBChzow1a1HmflMddk66YcVur2g60hTmVjSZAUAeA-hx2lh_MRB0RiYd", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398832", "new_stream_id": "2037398832", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=bhra18I9jsan4hP4CEpmWLnFPgsC92Tzabn_SO9bdGLed1B25ujIweFsy0Kzit2pPZX0o4vrCSMx82fyp0YLtbdQ2Jnsymxxz0-Xdqbyxi17cBHTEU9NxVro_t4UMOeImU0bNH4ZGPkXLvdtOxVe5y0dOxK0UCUpyjbyc6r5cPx9osYG9Ii76JUEVA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=XoUuKrdFZ_iPcXckBouY59RmhCEtMQQLzb05XwmA1Tam3RHZPXqz3973-UEbUHjpQI4uUYQbNau6RSAJKRaOcAaWx5c5Uf5HUSSXL3ZQvav6ySVXtdYZa4iIZM-uISohNfCrrRJpSykhHrxusfrQsnxfwFIxsFBydqndh3IA1GVnHoexqty7aVjxmA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=XzZN1o0zFKpHlMR9YUjtPw10lgfglz_4QVDrPcmp_pcaHC7SmJ-hcrQhMUZX4YKS3q1-wEitIRSjVY9jD_TP3ymQfIOy2kjS-rK1rJebADZwIpuHmUmquwrej8U-ihRWgyABJNy4XliKf_K-f7H-_OZ1pE5IxCPUqdZmzkT-PGLPilOqHpbSPN9XXQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 6, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037428537", "new_stream_id": "2037428537", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Fhpy32vtBqnCdrBmASLVVQn_ZZdKZlNyMyR2bA_Ifann6YiqhQ2mKYD1rCYvx-pUqQlLZp4uVh4mPWtpmw70oZXFG8lzQ9ZBPqSInJ_9f61GibQgTDjyzDEJguko2MZXODppI873OGwU8YCMW6LzJK5zcXk7xD3zN4SyjVWoTVK5Fdsvbl-hXwr4", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=NOlqWpg_YZA-8I2baTIJIuahUy_eTiHQSaGweAGOXTHazwdMwNa9ec2gQf4eL1nIOqOl-hrVKv6IsprUgB49XvFyC6r3NYUJYqmUfNp9k1mjRV8ERLRNzYoahKgJYRUQYAu31i-4S_EdBGiCApoT6lBvqYcg2J9_gVor5iJ7IU1nmwCEW2Ewwbse", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=UKmyLZbK-HodQm_DXEweim_JzdJDA_4hEA3sEOhlL9GVvrU4qJuTfWrtID7Esvt3UqWp2OB_zWdZmpq01WnReKiXkRgwV3fF0XUleOdzmgfAI3p6AK_BRSQ7_NErA75oKMSu_trIXyZ6gRaYQYE0FVHvtDaL2MArSxaVcfskD79TgQbGXR8mhZMB", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398401", "new_stream_id": "2037398401", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=VTqmEDSbXwO8lOvbHyKN2-VECR3plwWdR-XnyTo07AcWFAnI-wOTNcO91L7KihhBrUkdk36XmEgEnYpC7merEshE1SKyiZRkFhwbE0HifBu4A-nOjeIvq07JRn1voLgdvdUH2iwmLzBWbAf2OB-e-RCnrGI0VqRstNeACtiFhK69r-SxfkvOiO720g", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=8zwDYvLo4xgoLBX90jp6E6aUD02YKT-Je8vlGwGuQhhS7vXs11UYKjCbDtqu3e__5hyVbRGtHvZRn1-3Zt-E9xB6n0Q87ouZKnNmdMRlIc565yNhKmlYbBWu2KaWOki8sDflj9Psta3loSmyoZmd3kBMKAp5s8sCblasmE1CXDVbYuBREFTpv7qjJw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=t7xS5eizUeQDZx9F9dHF9payGmmWYYrs4vRa9iR0Niv8zeTzkepyzAkbswo5HrC7wPj5DFujbDO6RIT4DtwuwyFTsolZptGEZ7Wo0QO84oYDiXRbV_v9n_3q6Y-jNqvBR0y_w7Yh1B30pn8snQf5FOR8bCffz96yZOXWWQpymuNDRFK8YY57KEwBAg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 2, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "dd-5.1-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632986", "new_stream_id": "2037632986", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=Wmc5afY4_e2reek1jDe2FVk0ntTDEkw2QD-y0uHHDYNL0X_Y-3XCFQHpkkU-IclURd-5mpdvn-UrQ5lmnx2MzDcVO_wS9alkfFI5RVx6uBWUFcmDS4hGNWPM52K_wiOHJNofuQlZFWBElkPUsNnucKW253xDG53p-c1FnNr1jxgeWQJoKXVbj0J3hg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=pEMs0h1fSsRe4HOuqHCsohWNbE8x5vzxA94HO9GJ9gDLc0o7rMiS2jsXKtMN_z-ure8h-x1e0Jk-k4LItvyWtFgTPRZ0tSxhHXUtpES2b0mW2r4uueLR-DhGSeUkrpftU9HsT7xeb78My_R7w__eAc2rFK8Bb4GnepUmP52YU8g9PnWZJsjscEx9mw", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=HfBcIth5CN61E7DtjxrHjXa5l4BTiTYyEV_X7BqFbyXaonTJTgYFQfyG9m_blorUTm-UWRFcQ2PIn9qpNfRKOZswym4acdFfXZWxwOaKzr2EGCinemVxU_3Y0kt7E86Fd75CD0VnlSevnyXJrrXtz3B6SwRmGnx4kgo0r3HcizpsZx0fps_X3ZWDiQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 448, "size": 398321056, "isDrm": false, "downloadable_id": "2038451973", "new_stream_id": "2038451973", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=9sPOPhDXyZt-ZPtLzTEkmNOscuO9iKjw08NEkRwlHDnRg1zJsKEQ0wDQjWiWjdmfIxeNab-jPgAKUM-j91qLi1y58dcHK98Nl1V_nKpGi_DKPvYjiSF3uU4jDld1oP6sL3XuAOttiYK8FmDqFOFW66LDmStFfM_R4MON04O05RIQN2V-LC7YSLhztw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Wn27e2RK4Vj1_xRWawmtSvk0JP_0Omxv8ioR_SP2w8CspWxsmU5LwbId_sPPHpg8onELUCuWNggGc4sV2TsNLL4Vcfsbd5zmVKsD79C27_InhNo3ApXECFNxpKFONALf1I3Hf6dJEyGo_3ihU1D8T690kc-qv1D_RQ06WqDNJWguNaok13kx69OvPg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=MM7Gx0-2LJhY9Q6dLwHggWelKoGw9ZzRzcpL1-ki6zdmCHKBceWS41guKYssIRu21epcJ9QII-L3sYTwFP5ppfp504sKkJQeS04CHp73DatAtKBmoxvAcFwAonD93_L81mTE-JaXnhhzQnQCLSAlegYM3IR32-ftBbZBimbZ2VLVoVtk1N5fvfQmxg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 640, "size": 567539104, "isDrm": false, "downloadable_id": "2038451490", "new_stream_id": "2038451490", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=SqgnPWHUzphbx4JhwWcsoF6kZDw2TEJR6Cl17Mh5amaiscOtEkou91VM70hAh0P0m4y3hjIbAqf3DcCpV4VjTjC4xb54aA95zDup_Zk4Qt0fiv_TRSaBwXZNv3RR0d7UbRbFQluD1q54GYfoPYR5gk9swFpME5am2giPGlQyyLTZDoZhX_kIkufAKQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=6-QEaPPIuBQi8bSqAD6QW391bjoEu-f0hL96luG4Ur6fwmX4dwT8b3aPTaTBHjqrUDentZP8fddQgh3UyU0Vc9azERDpNlx8Nv7di7swL38856k354ZpXaDD5JqXoon7-BPLL1RzYHal--duXY_qyjRqRQ0YUeLOjZ6BvrjyHyedlpgsysuHCk8itQ", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=87rE97X3Hc9bFWfogR2ITyC1wUdb98M_8RDJJX63EMlBC9Qie6mTf2_Tv3ZSNuLPpVJ8nkTdBw9FYbU6PiJBXa5xWnz9cZ9y0Qj_JTbIXS-AzmmjiPibxtWuFKTQ5B6SVqOLBaXwVa1-7kpEPbfh9KxRQBKiI2iykfaiflwyNbHD2OJyfoaQJuAeZQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 768, "size": 680351136, "isDrm": false, "downloadable_id": "2038449646", "new_stream_id": "2038449646", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=dCVbDaseLZmVrKPcludq-clKjBVpAcR_jun-msX1ozBajpK9Gl3cUvNDi-MTSzWlTOjWnD-jwbFyhwcgOmBuXT4zyTmQx3VimtDEXrMx6_YZ1MqlLbealIEGuluYbpUeU0yLBzkDw0t3Gx7SJwgwhJfchUsYSmEo-edeDdMxXgTrcovbTndXyFDGPg", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=9GYUOm8v_FXpaN7jXEk_WV-vUHHvjYUKeu9uAy9kC5Du746xdk4jb5rUUoVjPvfpNnUaMtbJ8df_kjA94ks66s4FZ4MJlDVjJcUkICEbWS-0q5I-vOdwqOLIVykvmM7s-4s5cQ3WJ7GH9y0bUnM-db27WGAGt5p5eylBHALuTMkwGRpAPfa_Rm-a9g", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=zbdCS2QAiGmYi_t5WTseWzCLDMRUi6yzj-6XsJF8HYTj5orU6v8vOBVk8cd4KZ-ZuWnAIo42GlbpDW6xrMvuw-HosRLJUFqJmLKVAILuGCo5_DAxHLbBHVMzuFuQxOWfUjd6iCQR70Sa1XWBw2utwqgES_bnb9JpvcymQ7oajVI3OyMEy4mxzNmm1g", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 0, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122172", "new_stream_id": "2038122172", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=fqXk35b9epLCT-xbFSDUV2557X28XnZJ0DiuHykYslmebyHPe2DNs_0MzYLvsnKj0J3B1DtLUQ_ptskEb43lXkDYmJELuaP4ffCIJfk6P2v5x8VJZKS5y37j7c3SlFhNr4QPgUKW_lUgUclY3yhQu-33d15x-nImo0qf9qZtpkZZ5G8DQwAdC02_XA", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=ZuruZk93a815KtiNTqMFEYE51tQFQStZw7EY3tGl9yUWLrs_0i_lQdL8FeS6zCKGjO90MtwTrgNVdIeRfkDbxlankM1gUewPj6EeMAIhhESEIFWJmfSOxBzXCk4ulPsIBgrz-hVxsaoDurgXF3xVxqP_8bIYbYMVnXFo3hysXb2gAIkKXWbTZyAUyg", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=hYa1SZkYpDqHqS9RfXu_oWHQan7anNbv3ic_xU053TbTlS2EldxBHvRFszX5u-K-tFz-ZAybgoO-9T7DI3FrMl_Ltmy_adDeLieiSuBM_VDfoI24SCmEsADEjdRaRgdcXB0oLOMRt55ENy9RO6oJbnxUISZbG1aElGta52ic2DqZ4htI74hk3Dr2KA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632157", "new_stream_id": "2037632157", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=K9XSXGezfg1EB0ugSDiX4G75S4x2UjxEpwH1rOFIB-6MlUuc0PIWb6beyOExMKJ6J5dP3GUBedI1Tfw8KCshnLM0hrZWS-ZHF3x4Am94QW--jw6GvviHEUYz_OZsniJgz6V8baZ0pMLPHy4aGyRgaPYe3yizoviXax37b1DPXfrFaN6iZeXf1QtknA", "cdn_id": 1}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=pGZTCk8wHkLE5JL5ZdJm9HcP0p2dpDcoCYrwSapZvaY3oNflrJayNOU4kL_LCyijLttDJnu94lvw12aNCkaeuENhG1EU9aQGX3xmdy87Jq2PPiXrdXVKkEfg3FTSkPZ0CsLXGnxGh6P7J-qJqHUfzShGHBYWWumt0IJbaKPfjmYldWJANQ2LmvAOcA", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786312&t=1Jwx7BBsT4oZ3wEnXiPUUB1uLUn6jy7GoOVLE366XSSIADs4HpCLXHl8ZbKrALxVVAXadbj_pDZynAieN4YsUnKTgXNcf1jyNQrBnFEO5F1gx76JY--2YyhAgNEUs5Cy8kxdMB9eUqtnX8bdijiu8yp6TED8MG57p8AHosLxLsPnA1V9BNeG7dnAFg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887207", "new_stream_id": "2037887207", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=QEg4dr6qeavHHjbkzs-kz8LYt2__2dvLXFORkdy7U0sasatQFfXqWTkYanaYtaEqJewlg7R3rf1dHQyAlxYsUtd3AxtMauuObTDb-7cnW8vEtuaQz4mZFWu-d8A3nbsTJtJ39M0Bry85268BVs4LC9fu2TXAvX1at5vmNb3V31L7s5QoplqSl4HvSA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=hRp7hyj5KqKyRpoqMZY0pyO1TdT8rOiUAMFQ976jP7O5O7Z44lu1l9bEI9AkNdrQ_RGyE0SUfq8fwmQSDXpjFiGI1KP_JuwbzSTRatYjWN2gCHwdqcAiK-JEaWsgaZgax7tAAIgM8uJ7LD9FvjGzUa4nTJnMzH9E1pHMIw-KSzJwcWHhYzJfyFHzmw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=wfZX77C6mhhJcXYNdiz3xdlTK67pCHexikkyfpTGQB3zH1Mn3TII5_8hFbeu5uCH6T6TBpPzAS9NXhKByu1cyFbk5gB8Hp_nb1B1rfZiT9Cblq_GtLVt7m60gEFMq8WV0q7Dq-2jUcaSaYT_OQR6LWnufR0vkwZS7nmE1K1xkz5xP8uDisdZczmjPw", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879190", "new_stream_id": "2037879190", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=BAtC3hooApVdegwOfTRvRUZMTdOCK9Wwpc-xJR5vYMro7arofBXX2G0cqHrvNl07vqQ8L-GHju9uO6E8WfGPJgy-laX9sBw9e9Yrcx6AmbjJmLfmNstiX3VINbuSkCKEe5CiJDHp_0mUDUUedWyNH4g3XWcqz-ZAm1dNW8A9FgXjH3IFfJRlQ0peFA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=LhlSd3YbqSo_VetAiIMiskPaLUB6VOF_rvxpK0EdlIeoltyNe9sT1-ZPKUUtIJfjd-l3hoLQu5Y8uFWyYaAvxqjpbVTGBeL518rifl4KKbtPd2S4Qp2p-AtIrmnq-fQPStEFTm6EDfJnAYLZYODaNWhih_26jKUI1OAnChQ_YBbBzt9ZRqztw7fOeg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=KYmw4jo7CObEWwG_IwcsNoDXCWY7MD3AIZiPv6zo-PdhJSWJk1s9kcxdtgBJksbi-p6MWPlKSmS1guljT4X4L9I9hefTL4Pn7gHyCx-kHN5-CO4Rhit3zMcpvhmowfY1qpWkc3ZZ-CBhMyeTCFU5pU6bdpKkbueNAtkEFKNaiObx1LRDgoNd-lIVyA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621891", "new_stream_id": "2037621891", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=yDbjVqSP5sRciXiGxizy9lbzsNJDSX_VptecmXeEwbgXo2RZp9W_1Iq7GnQJj14F9arud7T09jKwNPngdfe5jsIoD53b6P3OUNHc0s9rJw5fuFKoabRUDwuWHtAaSxjVGhmaEzRH4dk-XZQ_UeWXteuHgZFog-JnpIvygZZyfspiLffjV7gTKY0YfQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=UqX1WpmSoFPNxMtHXABoaEScAOFHT1U434OB68d8KikuF_nCU3HYgwdVKSI74lrhE1kTbL72fHe2K3Ixygp8UgmdxNQQAFVMqGSw2qzsgfpV0wjENgjBEqVYeJ0ccpMtMbGj8onRM-JGs388oLFd6Kqvw_YMKPE6LtecGp6kLs-MaBt7656_GyW9uw", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=VlcxnYFqMSrvfHwg9Ervj14JqCjA5Zx61wD-7Y9IoWY2vRs4nptppgfSLDS2zefAnhCSmhw0MDl7gsLjFR6tVuQ_NVtfF70OMUI3QxHdpIijqWkc-V1lKoJ_EJF8CaSGsEV_FHrFrIqGpE1di_bsLQolLuV_qt9vy5jF2TpIXZ-x51sIvWI2cS6QyQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 5, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038120294", "new_stream_id": "2038120294", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=3OUKjjRgla_WsQ9FAH0AsIXz3G0oqCdigQvgY78SmTTHgLzuw3hJQ0eGPOLHohcYiUHEIO0sL_2Rv2Lh4BxTCMgup8V3Pps4IecH-qQZkcHrXNWaXk6PWI9K2yeMwpf4fmyZwAjrhivDNb_gGX3Jb8q4E6L5_78f5hTIS6Sa-t1PSGFDuuqu-iq1jQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=TrtEJCRxEsHOEG4JTZCC5q1N7gNh5LcALaCWilWULKfScP_y-qF0kM0iGzPp-J1VYNWp9T2-XGEuKTB0yjH5xvBfagoz9aVCd8eJze_6-NsaDX0DVgGL63sb2zzIR6k8zAl5zFXJI4z28rQId-mrqcs5bRE4Q5Q-GwdlI_PJtHyVgLG8oqRR9AO-ZA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=CIcNItS8Y37WPCkdloj6TOKkMEGkM6pziwJ_BGnbdj7FqCDSPH4E-y-Y3MlqrlyJFynS5pvI6QO-6i_tl95OYkfw4uatZihKGcRMVZC3DNWP_KHvf5sCs8Hr3Rg5QVWRjnRGmVSCgDkeAsjQU_2Z8sLeocoKg7dbBmgNPd_hebiW42uJ0u73q5U5tg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630472", "new_stream_id": "2037630472", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=NuSgXhFQoT-R6D7By4U3FIzncNVfLrJxjE3Nh4jnObdg7H8hMDGqqClqwley1tbN6sgw7QKc22-ljF8de_kacFjXDZjnIPgXR41pHRcJ50Us4cQaI-dwv4At5CK2KxMoVLLkTSUb4pjq0Bd1UY3AMyC0mT14VHJ6NTUa7tlTlkdR8oD8mTJn2Uv9kQ", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=avb_cVY_iAR07ozprEjWkOcIsNNHy67aljpROosSrxCZbs5ly7QfbpB6KVVPOupt3fa8Jtra4u4hlE_16GSwQfjtrq6L7basm81kIMVC-MDdpmK-m9CuXVHgUW8y7lNXLNdW9D2lRA_uKtcXC4LKs2NahHHNs9aIYvw0j_qyqoHNT-3fJefRGMqipg", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=ouVb8T1odCP2pSaq7sWYQtYPcEd6qPV1bMXw_kzf_wiMy7EYShGtscZFdHPe_CCim9oCDBdkKZHmQJZAlnnSPNm4BUHu9GJ3ZYfzCoE58X5iBT6H_uqkqscX73bFSW6BebuxOWCKaahj8L0gBDu_kkV6buLqtnnrvZS_9o_YKF1SZJ56LEGJ2kdIBA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887822", "new_stream_id": "2037887822", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=_flbs2bfgYitt_sZt2B16OEV9c9l48U0HyCMLCKmB-sRbM88kjM1SaVr-LUomYkpxO3F_Qwniiy7BK5d0K5tUZXQFz_4baSliOJXq2UEUuLMM9lC3j4cSVevreSskk6SYTGR6ykaOLIBYhsMPTv5v-OTZesT6dNdVFu-uQhSaNBJnj_-qrqkZ2QUiQ", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=0CwX7o2HJivmc3hCaKJ3WtQmv7mNyYYbo4ogBCXwXiWBWogxt1s_8PFjzCdV0MEqaVhTSg7AkwLkPJWoXI4YIz2XBYQNxGEjZzHE5t7A09FIqllSrGa4DQKrpIF7tiqIw2GlXseJ9Jb4ATsfcFm6j7TRCS_kEYmxAYF3jkj0aSt7i_vvwNcjCUwbiw", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=2MVNz9ZjxHtBn_ZntjVBeckbJV7xvyMHAGis3OFvkUVPHXobHqeoJ7J6IiOMaLSlp9FNxm7sCTpTZVwpHGqqGyRSg0al4sDww3J6eIdCFTztiP9CZl6GUKOccIJ7Y0BBF2s2B-zpNQa9ZXmscv-Jx-O1xzKG7sFPnufd3tJ6VkeB48upCx2BnEY-JA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882712", "new_stream_id": "2037882712", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=zGw3M_MAG5xs9eCX1CrcCATRoFXdKXsBGhaI7WmxEqXA8XYtxMfWpiUYO3ctOXRU7aD1iOurYrDNcAIDAuLnOWhLbsh7P6SPDOviRyvOG0xNb9G_5Q_x7OdVDmz_cHO0xIPKU1kuyyni2Onvq_u6tcZMN7h9THAF-zZePtpINolzl38xUW6n_mcUqg", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=CmeTpNuvc0267-psxyqgX0m_wHWLanoynn6aC-EMrtHmzMypYOghBZFUTTE2g-xXrSJ-qMbbhrxKBKmIKZvozTE63i-HX-rLOwtFWER_EMzJIXWIc1-WXnRV1DQD1nOT68E4wEbuXknK2YFkUUc9sNH18_g3TixM6T2aekiPOsSd5b4u0L6WjmiP4w", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=YpruhL7qLJAvSACOOD1iknQBGbXfs-8SlBDlhd2WWXSNi-mLxjlfHGcvaz3CLUZwMVBnMNihxteje6Yg2B1_fFhhcv5ET3GC2Cg_3izi7IMpuFlKa9tUbY9L56rVubPEsFrSO_5v5RBvG3denRYNC2F9zn_tpLTElwvbB7IbkOeI2Zbdh40NzGa-xg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621591", "new_stream_id": "2037621591", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=S_u-iDQS7J4-YWUN0PCItwuSQVXX2_kwTMUl4390DhzXZne4j8VGoOGQB1UXAPsF6a3u62FdhIjtd1NJrPBBsSW6Rd8qo-tZHfPbEWIebDaaq2tCMMZsr7rsYVgCqa-mPmZOwiYyvW2wrHvEuoOwpAJsBXdcsixcAVxjBxYsP_GHsQUikojCbaWAcg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=kX-1KdU0Kt37y4pJh_O7laFuPSAbgYyVdntxSVgsVL5JDkjM3QwcwOHtCeCVt3rd27cfsZxgtrCKZ9sTI_kr_Og6QWLGn29S32eyZ2zpGpBPnqCBZ6QIBEd_RfClrHgXy45vpIf4a0en9YZwsVLvrPWW06sRQquhS1vScy47yQnbiCTQi3tSPxTfOg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=KxDLORPjxkYGS9_e1l4BG3yHfpcQFlgfJeHn3G-F6RFLvdbZ48LCqZ8m9IXyP_cwpc9xOOw5n1txWKf8DtFNJyhJ0H4fsRJ3irUgf04eRnsQOTrEi_JeJFyYhfnGsH_tA8ztuJK-mk7hh8o91fk7RzO3lIiSBWcRjCjcHTyzngOGruudq7oH0SpPwg", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 4, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122469", "new_stream_id": "2038122469", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=7gyYwsuTt91rL7uq7qsJhqyO5qcFTIrNwgF04Tlu1G2nJhT8Tn954sbN_Hq7o4Ud_b2kus88ROGeeWepgWLm4l45Qq9VbjOYt7rfQL4bLjjq62W7gw2N99-KQM0Z_7rabuGFT91e4f9pZTurjJL1AVVRTU-o79XWw5zxj6WaZyRuD2_rXffpJsvd0A", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=mTeLtQ04dFYaxvNPI2R_kNAyQIu1Qn9KGqo4a86PhENm3gnHZqIIriFlt16Hnb-ns9fS9n_p4lcFyGcauDrf9lhgJDVd1-IlGdOMq1X83xOAltBgnS67x-SKPw3NZU4Igth8w8oqHpFBZe9XWTC9MU_9ao89m06bXw3ihTmp0z7-stZdHDVShFmOJA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=dY_dI9a5L1ecDd7B4ij6OUYBhc20AJUkRxI4fWK9Tu08qM8QuE3UeOj9aE2fsUgUSWk1CdiqKhRfXsrmxBJohh9N5i3AJ02p2S6sz1ZBt4jwlRkAihfRsfEjDYcv4ljb3tQHVDrTylzvv1-bXRl_KTIzeBFVb9QG2NbgJbIyQaoulty1geqK0Fxirw", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037633762", "new_stream_id": "2037633762", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=7TRIGs358jlSZjhfOHdedKd-vNOreuVKfK67YswkrmUDltKOV2e3WrE8otHH1XPJdBiHbWtOimnelcTCGmPvjCdgqW5YprLH8TKVdsfyRdJTO93zsMhjfMFzaTrGrBzbYet8rkRzJKY9_wzUt6W50SkC__hmNb1XV_zJSy4sgLplZ0s9KENjYW2_hA", "cdn_id": 1}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=i6YY9iQHB0glrttUS2tro1L91UOJOxLgPRBvnTiZUuZ8XqO3MedJptzie9h9U4APjm0dy2xDgMINJDyNqIxm-jPYbzRrvZw2WbO0bcsjuPxPv-zasUAux5g59TJYhOfHvZ_3ZwsoqXdMT2fn6Xq0ofJUNFHdNw2ACQZSshaOiC575_hTwR1SkRRPQg", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786312&t=RnFVQdkovZNNYACNAUjZ6yWmQDtSBWzDx-k6pBvuTCC3VKfF06ZupkZiGXW7kCiqAkXWC87nGI1fyzatHOJKfbkGkFNg6rg5DAW6c4X494NKh86GSg_LuAHMZBW5a-ICHUp91mK1uEkREKs-OOWyR3atCTNBzTdpRgNIPlPcyTtA3Ghv1hFYTaE9dg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886203", "new_stream_id": "2037886203", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=L0RvrSvom-UMoVo0pQJ-vnV5JY03ZMAb4KZbptSTO4pxeprOMGEjK7bkbwvhnKxxigbaVBBZnsPrGtwwW_FnphekOYk0ulESM817vURaizdqebARogj7lTldkmsHKM_N-lC-5xen_ViY_jr4Br9O1XsurobXnVzlOpspbU-PBbUC5CT1wV6uMeYyfA", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=GHh8040Sk833iC5V3eNEOQhAsGbPKW47nNtuAm-gt8vF_pcolt9tB7Gl7Z65ulpr7MLIlNZUdFvglfW2oLg236ABPUHZsvXyD76jJY5FkdqPXEQ2fGGL43hO8sQ3tv7CESz08AkkSYsLDX3hkS065btYVxmQZF9q3QmIpsoFc5DCwMpO-SsC__K7SQ", "cdn_id": 2}, {"url": "http://45.57.51.144/?o=1&v=17&e=1637786312&t=E3GiTbrGFq4rUKte_vyeWeF4S1cTQdo8HiQCBo6rO_hl_vf4RZqPoaUoXbHziNpgCiLv_tKNTtP3KbD7G_cmErhm6RtXPjULJOea5E-CdlbettUTy5wnkCEODjuDeQXRiKigNPi5D1PHqNSWgnHzaxMraVTYdyCnjv8TnczBBY9r5jchQLw_bDoXpg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879896", "new_stream_id": "2037879896", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=ticWgr8dwSCNMljnCqQis81MJFj-Dg0Zx5bNX8HsdjiPMD2DLLKcW4J-wVAISd_7FUxTTvOlCT9tuHeYWkx76fwAmeQpzLRumWcO6MrCsYZAzXCGo3_79f7DbVMIr94PCli_MXc-5I5gDjoy8iaTE81BpVGuyU8X-d8I6gysm2ezRI-lMSu9fuja2A", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=e2_iSWEAhsHZHYddJMDJHFpDMQRmGs9VUahh2lX-CAeuLhavVUzRDGAYQw8i8LmBdZ3nGOTIoBev7Gdr4FjU-Vw5IxXeiEeoBr_eHj2idcaUyrPqiWLCk1JiiGLa6iaTRdeFCcUQG3lde7YEAq--sjOgtHMC_Lj1HJvcfIql_LO_0lDfC93e1kl4gg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=g83i5Hh7Xji-tx7g6YRa3b9FnVBtO6CWkrojk4Etq8xpdDPdaFGFrjTWKSc2dp6QHUhJAD0elgIzU5Edz6dlDXR7me9MvZ_--ElBTAA_M5T5xDsONSiULz1Nl8hpzTCBEgNpca4ZJ-9wN_Vu5T8-mj52gqpPoyCCPkt61yspKwXYGTrp1rBIb_n5JQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037622635", "new_stream_id": "2037622635", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=iIYtBsA96tZgIj6HpcGo-Q4U0-6d7zCfBAQZd_bxOm4f8d8ZXqDHFs6tckPS2nN--l9D0-WX0M3HunxeKkvwc6-AL912UatWD9n-FAFFRDaVAV0Wpds46wKZBfpZHHmHfPAyEtYmDn6StYjSDCSq4b2cVIAzkqkPFungHMzUIyWmF5op55caJXMQbA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=bNw8dtBOdtV7EuejpWoaJQsb1PWQsF05acFSKN_5Y-liCjnhEyOPSw8f2VJcchxcxJOwaWf9EqD3v-Q-5PJ-FE1eqIljkuqD8QmlTsB-q-QmqOuS5aXOeK07m9Gt8rMnM8zvx0n7a8wtLRxNgj-2p1VUkMBlZVr9ji_y6I3juiuTZhDdgMr46WLysw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=oSFvqW3Z3d34C751D6IYZSMte6myOaeo3UiAS6grGpKcH5tLRXGwsNN_eqfMFTmyDlDPLa2dc8_s3L0ofLKyZqPfIUFPREiKxWFFdCvpnc0h5r1AgZtZu8whlKNp15mSY5QnajisMPjxC_FMZcXJ2FTzupOxugA5KEqupDXumWSvgML4kr2b2z4Isw", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;2;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 9, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037429668", "new_stream_id": "2037429668", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=1yS6fXrwzy7Mzh-4dQRQe8D4FZuwHENmAcf1RFcNjD66eHNl8Jl-vx5d03tDRAIb9Mju51pxQ4AANiaSGXcw0aHSPw4nI3D86JzJ8RmBiT049_efAMtIz9wfXUTwlgou9S5HJTlzr-0SqApbRYNdiOtQh4nc1dICZJ8aIsmhpOIGDmXgNbGGhucv", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=7yfsCV0_MRpxeGJNcHs03FsLArUlFzdtVr_6ARad94O7SLKkY3-TP-fcedVmyHGhihPoHDfx5-C6sFxXFsVyg4C6mdc2kDcSRROAGJON_VluMEad7HfvYTDh31x2TvV3Qvs8Vg5-UIuYU_Y4MuMviMsBJa9LpBA1T_lLVd-Rr6Uf5ja5fBXKM67f", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=RPX6_--kENEFr-3QUAoX9ytq0ahhbSCd5cSqpyRP2wkrncF0XUhAL15cgbiPbW_XPD6yhZav8_rFVO21X2MiV2LyRUPa_wQKDEglvb2NOIpCHjpoatlKrb-m2n6iEyQR79zJQPPFbLfqCWlGpD2WtZUVjRSzlZsXiXE9neS7v-7vb-rCl6SR_0vE", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400409", "new_stream_id": "2037400409", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=hU3w0GXysbc-9H_PjDVeg1K9yPA71sJgTatgakTKfpP0PWaobCAKlX7E_kfDb6nXbZCcWVECk3PmyEdLyfCUZSVzADQF0bq35P87D-vIITfa3FtnbqZY5y8WOOCwBTH_Px1s0O6BSRalXxxm7-JD0uq_NWcIc0-fGNFbnmuqdwCLr9aNpLSV2n9ggw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=XNSs22N23_8ldpD_BNGNMy5F_eDx8IzrMIuY7zzr-ie5khyYtjDc0GjjsRgYorxpb6k1FAWedfZ6KDxYVvhMSIFL-3QbuBBW1K8_zIFk3D4hMKgDBxfsXoUPg5HCQ5nulg6AUf-Gveoio_2ZBmjaJPpcqecZS47LKjLVrDsHw0eiiP2SPuBIIOlDzA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=eohz-HMYeDNhLP7UZYBjcrnAR0_ISKXP1ET031vm0IQ9aqaOJ41nsi8-aGQc6jZ2qUt8qgBz68Gs0HeU0_PeQ2VnXGFf89DNgoy_L2D_jnpSSRoymubAHUUJTETCaD0H6vbVhVIdo74COd5heh8eqpDe0lDzA0XZqWZFLzka82A7ODU_ZOW9iZjLJw", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;6;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 8, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2039673808", "new_stream_id": "2039673808", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=Eigol9FXrHUZjX8mKPO9JH79RTfOOAFNI3gAykjHnvYetV3EhvBO00yAfhUpKpaqMi_GquYROQhfkwi7jdvbtbyKeH-Zc-m4sLPIdMlW8l8zZwgPC87GemdZ8ypRbMF9SnxtwMrMe2fdP1EqGt_HqyxbI5zAfeeOLD7xa23I6UkbW6XK3IqXiOkqIw", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=jp3MN6AuY4EcJFGNmrvAj5u2Y9nKoXM2GH09LUIPLVcYAYvvTUpJvjbaPUGg96HK0RcSDvw7wccGLAoWS8Xmoz6CGyu5Ptzcz0CU1ZG11ywnHnJLlTQOP68R9wVm0Zi-pAgkYNWirTTKS6cT30Uht73hPJSpJBAJgXuZEg1Nv78rFFu1DrSOF35XSQ", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=gkXFLyeOJ0M1-BzopbukM_9iVemrsy0nEYYd-4jFrGU10C5heM_YRH2dtqYHJP0qejaXKxja6RVWyZLg_PmH2He0SRaBeg3eGW0k5XXqJEDTFf0GrwX7qjqk-n0ZqFOhS1t5Bn2WVrrfqEDHZ3IvlavCrG4GbG2NPCnbgu565PwSqF4mLCiepK4p2w", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630286", "new_stream_id": "2037630286", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=R9mnHnKl1bGZ8M929cYXbQRpsAofvbbOiha66FK832OsUTDanxlYe7n4SkNboD_rZSM9d9PIFMhKsoly7krai5QCg_-tDOmS1tnkQy5UZsF8W2c4oqVcozRuElFkEI2gt8fOajd2WDQ06GxQ0nvVXcbwmpPgK5gv2bDSOhqt-gwxsl6J1gjsinb74A", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=670ledrAfY_5SPymKOeiPOWFEZ6jxwlWiSiKEMKx3YrMJCsNzhEivPsx2uggobiljDwv-XXyB1etIlfH18T5wmqD5B0s49F4HTMIlQ-igq--f7HO2V3qKifjQ_EC-mjfo0k3xgL8YsJlfiqqp2rzyArOIuoR2PCa-mKMFJ_iaWWb7AgVktcTyxzWzQ", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=6W2GBEZWE_mPnwUEihanrWWEBX112Bryv4NpdHsvplEnY-852AW-k34hQxb4kR13q-OfTaSlRts7jJePCC7qw39jp_ti13SYnNkGz48JHqQzY2oWGJzBJoZXOi1xRWVNV9hRi9lBV1_a6VjhKdka4CQR-eUfxkEOBX1Pw9x8I0AeJA7lJsd-8sLcUg", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886411", "new_stream_id": "2037886411", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=2-PG8fdButyb18R3Og1kC9BJne8TwZ07ENJG8pLw4BrJtfv-tvPTbH4ZCooVwZuSmU3qcBZaTRkPtCvbWF5_xa8tCljWPnuNWMSLi2ZdEHutGjD-iTno1TPXhL44WfIxV2BB91A-WY7aA0QhDPImSB9kr4yp_TBXx3onGhMQLUFeuWX0E8P-x67vYw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=BqIA6jKCQBjj9e093Ba9K0bJYlmggQx_qKyC-hAqCCYzslcC-iwGzw-hHt4QBZsafauvOOVXFPnS296RrKtT0bPFTI7WtUf0Y3nKglGiVUayIRwCjZGNYJBGyW1H1X7EAtR3sIwQLXJAF4GukfhR6LNAN7wew55Xgo46DHLBc-c54Fxbmyqjuoqb-g", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=sbNwwLL5i7Qrrlfj2vZ7MmT83TD9Q7DQ8UIv0o5rKX_KzkQqKJeg5rs5xJVvc1RA1Jz6A0Qjs_N3ZLsIyjRU4hX5t92nX-h-SVnJRREuGbgmOWZ9B6weKjfk_xyEeOuJxEXZfdXyc2lI7YXunY29H7sApEH7ojvit6tfn_eh-6gOZTPdxXwssNKmUg", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882117", "new_stream_id": "2037882117", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=vz2qENeeBArxII_Huupo7OQQzJur4e-KNZ4zHJm3hvBmpcP6Xe9Ss_6qnn40fPsIZq4ytGb3fBewJ0ysewwdYYzmyFZPbPF6gV4cN54Ks4JHUW5ImIWwDUmfrwIfPhi5Cs6tn7kBZDiV6oxLsf95sN6OQwHKXM029Uy33Tb-XnIfHJNSqJJU8n-HHQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=86VeELHQu-yvAAq_aV5MGpaR6PHFs9fEhOyJgcbGMwVPt1k5ljD_X-a_zXZz-nrX42VldQCHfMLGkee5iB3CgkZoRyRUrfm4KBSjEcLQTK0NzKKpCxr8CPXvm8LYBCyVd23w7xf5PZE3_Sdc0QYgoQoMIb9XitxSjm2RSAKdKf2IRfyHXN65u5i-CA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=aSgwbzpHHGsAchmzCkXJ1EQg6P-6nOxWd7-ddkflvtannxDsyFSl5b8c45LlxWquCW3X4_ZRKlpm3IZdZBm74GO57Frwn3i6Of1COPyrc-BlsZ7162LccyTJ6TjJmPvUix6e5NGe068-o9ldiMhxrc1OR9bHjHeX-PtMgjzvA4_60EQ-9Vb0-RTPCA", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037623180", "new_stream_id": "2037623180", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=9p-vndRuz97gIbZxgsNusAv7uHCbeNPABV8tLhj2J6ZdEj67k5c1qlP18e0auq7EKI0LZ4OljaLQGN6JJVcg9AQRcU3YPWqNshBNHC8-euHffBDyEF3tECVzTFB1Smr5wx1vIYenPoz4_cR7ISWGdde4D8H1CtZP-yF5fQQJa5gDoJ4vAU3mNt4bDw", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=rHN1n2Nky2aJt_UnuwaCV_8IfyU0opgZAg9c_CYtd7Ed1w0YDmX0uKVHOU8GyNYI4MmQrqcIqyDid9L9yEQlb_GzmiLAZ0cZ6qR1ej8meZ5GAlc6fTQYvFIHjYtHImF-25SI0MCTSXxgzIkCLdXf2hu3NqPTJl99tqEMBoETwFvRAiPavBR6IoIw4A", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=iHVbPa-3ysy80IWf3jV5zcGl-SYbKi9iwdG4fVMoDgNIiYskIshBGQ0Zdv19JnJ-NiJV0mrNJaGAmTI9Kpdge40f07_grUkcx4If54yfn_OzDGs2l7qZusU2QH-6hedirbzM0zaaUHoZCpiRoPmWmHLTWTs9Tm0zwiX959iZQ_IxgUmYPH1kSNJcjg", "cdn_id": 3}]}]}], "trickplays": [], "servers": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}], "locations": [{"key": "1-24186-high", "rank": 1, "weight": 140, "level": 1}, {"key": "2-24186-high", "rank": 2, "weight": 120, "level": 1}, {"key": "3-24186-high", "rank": 3, "weight": 100, "level": 1}], "cdnResponseData": {"pbcid": "6.rmTU7GqiLGR4d2hgXdK-hdSB6n4gX5I_DNLlIxZXuRc"}, "steeringAdditionalInfo": {"steeringId": "6.rmTU7GqiLGR4d2hgXdK-hdSB6n4gX5I_DNLlIxZXuRc", "additionalGroupNames": [], "streamingClientConfig": {}}, "audioTextShortcuts": [{"id": "4f6dc4c0-ccbd-44cc-a164-0e4424b0c8e2", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:0;1;en;1;1;0;"}, {"id": "3af16039-e589-4dfc-9405-fa319093e1cd", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:1;1;en;0;0;0;"}]}} \ No newline at end of file diff --git a/manifest_sd.json b/manifest_sd.json new file mode 100644 index 0000000..70e0820 --- /dev/null +++ b/manifest_sd.json @@ -0,0 +1 @@ +{"version": 2, "id": 16377431109789, "serverTime": 1637743112846, "from": "nq_cadmium_pbo_manifests@2.107.0/pbo-client@2.107.0", "result": {"movieId": [80230399], "drmType": "widevine", "type": "standard", "drmVersion": 25, "dpsid": null, "clientIpAddress": "45.115.91.43", "bookmark": -1, "playbackContextId": "E3-BQFRAAELEN1gmduolrg6VwzoLI5z4r6Bx3pOZNVzo6uCzAAQb4ZXL_PseYtJ8vBb2Do3y59oLAUlqh6yxxexkLj6RNpo9PStqazYjcvySwTPsJJXWuzAcp6zr0yoskW9JtaDmBizaHjx2CvxhY0rOAOPfo62KUzzK_6cJKn-MRFVsun04fqrpP3THR0kgS1rHPnAG7YlEUHJWbtfE5KpmmIm9v8sJ75GMtX2pIcmLFRdcm9JLmSwTAkOvNoMPnVuOe9EElaPIgwoZyYOjWnOQgdSveCIMpFRKw4H3gBEMi8XI7mDNrz1sQid3ZQZ6dFra7Fj7xi3b8i2m7gyT1DVt9sMYkWgWXPghZHjXl6eyiSxqPCE_j2IeNJSKLs08lAdDGsYFAd3XuZ3izx90eUxmFgCC4a3K-iaUhCyRQsoMC7MNs8ofp2h1Q3i8cSJoNmoZ4CoonjVIbqN3UWB6MxnRP2Q2I4O_zdqMK__sBq2WB-ujpRuiMwBfk-nKHU-OKiVSgm1c8Rz1XnL2CpZSiUjIIxjGexnllX3Ln8AqdCY2QVk8ntv9mohylhC_-k8S1Vpnc_c7OjXmSzoZNv5eVJ8m7CEgPmlxgkeNmWpQHr2_bH2GTstDB_bnza__ZpIUiGy", "links": {"events": {"rel": "events", "href": "/events?playbackContextId=E3-BQFRAAELEN1gmduolrg6VwzoLI5z4r6Bx3pOZNVzo6uCzAAQb4ZXL_PseYtJ8vBb2Do3y59oLAUlqh6yxxexkLj6RNpo9PStqazYjcvySwTPsJJXWuzAcp6zr0yoskW9JtaDmBizaHjx2CvxhY0rOAOPfo62KUzzK_6cJKn-MRFVsun04fqrpP3THR0kgS1rHPnAG7YlEUHJWbtfE5KpmmIm9v8sJ75GMtX2pIcmLFRdcm9JLmSwTAkOvNoMPnVuOe9EElaPIgwoZyYOjWnOQgdSveCIMpFRKw4H3gBEMi8XI7mDNrz1sQid3ZQZ6dFra7Fj7xi3b8i2m7gyT1DVt9sMYkWgWXPghZHjXl6eyiSxqPCE_j2IeNJSKLs08lAdDGsYFAd3XuZ3izx90eUxmFgCC4a3K-iaUhCyRQsoMC7MNs8ofp2h1Q3i8cSJoNmoZ4CoonjVIbqN3UWB6MxnRP2Q2I4O_zdqMK__sBq2WB-ujpRuiMwBfk-nKHU-OKiVSgm1c8Rz1XnL2CpZSiUjIIxjGexnllX3Ln8AqdCY2QVk8ntv9mohylhC_-k8S1Vpnc_c7OjXmSzoZNv5eVJ8m7CEgPmlxgkeNmWpQHr2_bH2GTstDB_bnza__ZpIUiGy&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C"}, "license": {"rel": "license", "href": "/license?licenseType=standard&playbackContextId=E3-BQFRAAELEN1gmduolrg6VwzoLI5z4r6Bx3pOZNVzo6uCzAAQb4ZXL_PseYtJ8vBb2Do3y59oLAUlqh6yxxexkLj6RNpo9PStqazYjcvySwTPsJJXWuzAcp6zr0yoskW9JtaDmBizaHjx2CvxhY0rOAOPfo62KUzzK_6cJKn-MRFVsun04fqrpP3THR0kgS1rHPnAG7YlEUHJWbtfE5KpmmIm9v8sJ75GMtX2pIcmLFRdcm9JLmSwTAkOvNoMPnVuOe9EElaPIgwoZyYOjWnOQgdSveCIMpFRKw4H3gBEMi8XI7mDNrz1sQid3ZQZ6dFra7Fj7xi3b8i2m7gyT1DVt9sMYkWgWXPghZHjXl6eyiSxqPCE_j2IeNJSKLs08lAdDGsYFAd3XuZ3izx90eUxmFgCC4a3K-iaUhCyRQsoMC7MNs8ofp2h1Q3i8cSJoNmoZ4CoonjVIbqN3UWB6MxnRP2Q2I4O_zdqMK__sBq2WB-ujpRuiMwBfk-nKHU-OKiVSgm1c8Rz1XnL2CpZSiUjIIxjGexnllX3Ln8AqdCY2QVk8ntv9mohylhC_-k8S1Vpnc_c7OjXmSzoZNv5eVJ8m7CEgPmlxgkeNmWpQHr2_bH2GTstDB_bnza__ZpIUiGy&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}, "ldl": {"rel": "ldl", "href": "/license?licenseType=limited&playbackContextId=E3-BQFRAAELEN1gmduolrg6VwzoLI5z4r6Bx3pOZNVzo6uCzAAQb4ZXL_PseYtJ8vBb2Do3y59oLAUlqh6yxxexkLj6RNpo9PStqazYjcvySwTPsJJXWuzAcp6zr0yoskW9JtaDmBizaHjx2CvxhY0rOAOPfo62KUzzK_6cJKn-MRFVsun04fqrpP3THR0kgS1rHPnAG7YlEUHJWbtfE5KpmmIm9v8sJ75GMtX2pIcmLFRdcm9JLmSwTAkOvNoMPnVuOe9EElaPIgwoZyYOjWnOQgdSveCIMpFRKw4H3gBEMi8XI7mDNrz1sQid3ZQZ6dFra7Fj7xi3b8i2m7gyT1DVt9sMYkWgWXPghZHjXl6eyiSxqPCE_j2IeNJSKLs08lAdDGsYFAd3XuZ3izx90eUxmFgCC4a3K-iaUhCyRQsoMC7MNs8ofp2h1Q3i8cSJoNmoZ4CoonjVIbqN3UWB6MxnRP2Q2I4O_zdqMK__sBq2WB-ujpRuiMwBfk-nKHU-OKiVSgm1c8Rz1XnL2CpZSiUjIIxjGexnllX3Ln8AqdCY2QVk8ntv9mohylhC_-k8S1Vpnc_c7OjXmSzoZNv5eVJ8m7CEgPmlxgkeNmWpQHr2_bH2GTstDB_bnza__ZpIUiGy&esn=NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C&drmContextId=1674268"}}, "isBranching": false, "partiallyHydrated": false, "maxRecommendedAudioRank": 9, "maxRecommendedTextRank": 0, "duration": 7051000, "expiration": 1637786312809, "urlExpirationDuration": 43199964, "manifestExpirationDuration": 28799848, "viewableType": "MOVIE", "isSupplemental": false, "packageId": "1674268", "drmContextId": "1674268", "eligibleABTestMap": {"39008": "1"}, "media": [{"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;6;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;en;1;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:1;2;en;1;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;6;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;te;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;te;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;ta;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;ta;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;NONE;0;1;0;", "tracks": {"AUDIO": "A:2:1;2;hi;0;0;", "TEXT": "T:2:1;1;NONE;0;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:1;1;en;0;0;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;6;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;6;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}, {"id": "A:2:2;2;en;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:0;1;en;1;1;0;", "tracks": {"AUDIO": "A:2:2;2;en;0;0;", "TEXT": "T:2:0;1;en;1;1;0;", "VIDEO": "V:2:1;2;;default;-1;none;-1;"}}], "defaultTrackOrderList": [{"mediaId": "A:2:1;6;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 0}, {"mediaId": "A:2:1;2;hi;0;0;|V:2:1;2;;default;-1;none;-1;|T:2:1;1;en;0;0;0;", "audioTrackId": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "videoTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "subtitleTrackId": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "preferenceOrder": 1}], "timedtexttracks": [{"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:0;1;en;1;1;0;", "isForcedNarrative": true, "isNoneTrack": false, "language": "en", "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {"simplesdh": "1176827093"}, "ttDownloadables": {"simplesdh": {"size": 16161, "hashValue": "MjR0vpt+zo1jyhZ3VMmogCS0J0Q=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=NqAQGh73mdIPvGFJKH8bp6azeFYS0O2Kopb8UaT8iiw_6P3PsclO4pbd10qOCLMoLCNCA57Cfp1AbyTV00KGhdVn_s70jszKRGfGORTjL-PiHpqqq5FmG3zvJGhg9Ulwt6AexnapD4ICuo7uRQE841tW7OfBlflJ9Cg9FbTxuCGWsh2oKU4ZDr4", "2": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=_Yrquh7aWkDD7626pyDLf44bfujWh8zYS4q1bA3kiQRZnsxnXhE37Vn2u6__HJ9LeFSvTUiDFlj-bR2pccy-2B0KDO1EYPJUHWAIkLbn3phTe7f-HmCczu4ZTiMCHGjsM_-kqekh182nhgMOgsiQoY2CGVKIMU14rNXlwt6PZDucTkkXWc7N5m0", "3": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=Q94b0QF8oprWyyaDzsyvF6OA7f7fo97XB-nvp6bZ8zbta9Y6VLyqdTXwdwAS084t_sUx_ULR4oevkDhk1x0nsWYfPezgvw_V94Wh_OPtyUnbpi2-asfdSRlJAhhChGywoBHfyR4lf00hPEKDvFcGuaMYpyAFx3qCgwVCE_PzG9noxZVnz3Q49HM"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "ASSISTIVE", "rawTrackType": "closedcaptions", "id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c436c6f73656443617074696f6e737c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "new_track_id": "T:2:1;1;en;0;0;0;", "isForcedNarrative": false, "isNoneTrack": false, "language": "en", "languageDescription": "English", "isLanguageLeftToRight": true, "rank": 0, "hydrated": true, "downloadableIds": {"simplesdh": "1091695175"}, "ttDownloadables": {"simplesdh": {"size": 89685, "hashValue": "+ZXBbL9zcLzKphEOcnQDDpe/j1o=", "hashAlgo": "sha1", "isImage": false, "textKey": null, "downloadUrls": {"1": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=XJINeqnmW4cDxZ5TDlKF4T3DUi-pRzgbNJ-IyWvH-prh4ggMFev-gqvGcQFH7Dl7aPuD9MNORmRO3UhLdCu0A0x7mo3Rsf9acvi5fsTZNbrqR6ngMIyxuSXorpQP-24ml3gb5sgJFjRp5WOjfJRtH-WmHDk9YLX69lnqmhBgBDIWroEDZ7WgUJg", "2": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Be65DSlK2w0fX15Do6v4aWCkjkJbo4gUuWxWMz69aTz2zs3mE5UNBi_0RJL5L9czI3eua1UV05vcq9d9bmMkAjXW7uh-K4JHPZyVXLJ5YzRmau6NTJG6e29cYzy3rGQE1UFCtFEsRFdWsQwBpzBKNtB1yiqF-s9ROPoto6SNS-o37ukWZPqWOqs", "3": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=CQua8-QteVx6HNG3cIvN9_Lmlu4G30Zdjin2taSfWgq-OFVqwkVvsDhRzWDTDtHTxqTOqDEbnj7uavZxSwxWn2z_4XIdR4I0VNTzR7q-gXMxIT4NlR9klt2j-XerYjr-_km-NMgoygsOYcV3msp5csSJeQLzWxEq6V98fQXdL2SO6Df8XMXrEIo"}}}, "cdnlist": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}]}, {"type": "timedtext", "trackType": "PRIMARY", "rawTrackType": "subtitles", "id": "none", "new_track_id": "T:2:1;1;NONE;0;1;0;", "isForcedNarrative": false, "isNoneTrack": true, "language": null, "languageDescription": "Off", "isLanguageLeftToRight": true, "rank": -1, "hydrated": true, "downloadableIds": {}, "ttDownloadables": {}, "cdnlist": []}], "video_tracks": [{"trackType": "PRIMARY", "track_id": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c6e6f6e657c756e6b6e6f776e7c32447c566964656f7c756e6b6e6f776e7c7c7c64656661756c74", "new_track_id": "V:2:1;2;;default;-1;none;-1;", "dimensionsCount": 2, "dimensionsLabel": "2D", "stereo": false, "profileType": "AbstractDynamicEnum{name='VIDEO'}", "type": 1, "ict": false, "streams": [{"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6350, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5311955021, "startByteOffset": 97454, "isDrm": true, "vmaf": 100, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1806783668", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=TeOv4otJWkA-Ox_e9X8MuySSWk-6Mb2vIpHBUgDA5PLNZYLzdrWXupUcmxJAkHJjum-APGc44oX8n4_97ElaWxTGqmxyXL_Duv0cDESHKLSmhchYHpDDtQF1Kw8TC93j0FFoMiwa4sb-oqhI9hwyRi5r7t4pV47ABmFjrXb2pioz-iARFaB-1ipXXqw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=BEb1QSaZq54W5FpYJUyJXohAtSMZT-N9KgeKSUo4G-RBOt9F_KXtqcOED8fug3r78RXG1owtcXfWceGbGtrjhx4XcFFy0nN3CwApKkP7MeEzm8dSuDMivRq1akdYVp0B9oEVhX_hBz73V_9BTCxTNCLl1Dhw76wwr_82u10mV8WfXr5iiQOjTgdWmyY", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=DoC6NSTCpl-4xmYT4dTSp2WEfID1rjAH5l9tkjqYxiBMD63kJEc-ft5YsPnCLd7ZSkMKJYlyJaFRDGbd0pSgpR1qoDCn7mbO4IUMhEcxHko2a_q5ESiM4g-OE7GZO54yoqSbKU64P145yV3s4BGTooZShJle-ylXSvn__-tCGSFmWXd22oqsSXVYrEg", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 6900, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 5680647092, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1916117199", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=9OXgxBpe65BEtDza4Nnev9hCHs6-3Y2WArXWAFUMxfopOXdu2PHsik5IwO6qxOUE6F1jfgLiemSkICjKdh_xn8aje4x5bjeItAIbbrDsX_csYffT6FBusaJ1-pufY-YPlSTJgZV4FmV3mpy8yjl_NJVmI5QMYcPpq8OYr2y6wFTq4FyqzANAG4Cqv-k", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=oJgfxfLdHc6NGOrtZZckKpX5t8dY6nNZMCRqBTzd3awhf7DmiGoQHuVyu7Ns1t-5_aoucTQwR8yTs_22NuiIkYWNYSc4KYf0PYyJ_RPepAavwPDFiOojGsaTuhWzEGK9Fz3Z3rcXcocxQjn_zyI3xXhC7dpEIgaWnC9f41QJMj_bW-px5HnrkGlkiXs", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=9LYvl76470NwBH8etGBIMJH79iMG3LF73wHsh_U5KsXIHT7WtxWT0w91hUH50B1HiuCehDz84NoPETFvxEHYgrQa-yINlAwD85ydvSWfwaMzMOW9WXezn9xcaiL7jKgQNHNT-REmzkE_-7reZF8uXs91jTDHadjpGsRcxZowyRmXkRucPq-gZFkPL50", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 7450, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 2560, "res_h": 1440, "framerate_value": 24, "framerate_scale": 1, "size": 6021494277, "startByteOffset": 97454, "isDrm": true, "vmaf": 101, "segmentVmaf": [], "crop_x": 0, "crop_y": 184, "crop_w": 2560, "crop_h": 1070, "downloadable_id": "1956403691", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=hMtTlZ4EhtcXQ7BDGtzhx4YS4vRf_8U2LYwpKeOclDD4vaXrL0BGmnGZTzVRkfzw4vb_eWtI3K2tiVCFVzI3VeOtY7KPia5qF7QNLFv7ZkEkBG4JzbxaJr_0OOnJl7Bi-YLwHM7DyOaxJT2jAS9qN3bAy6qAKDk_xjZuqFWsc0PbcmyDtrYNzkiOnF0", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=WflppRbS-d38RCVgBOoD_lpL9udUc-U-H41qUgJpchZP0Y6oEXuy2NVUIttcofUkR05am1cQWESf-Vgu1xGzGtCD3I6IkmYXx0aD70CZtGY_SEr2EUeFYqMFXubavF5OE0yUfbcqDr8PLFhu47qD4Vw4-qVv24-VgISm42DSHLWON4BlD7mj0RKuXo4", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=ynTIghN0iJZg_82y9EUjjTEhSmbKK8EpAldqyKvhJ8tyrj6r_Cb1s8nsvB3PoUOeLjesAAyvC0nbrn1dZjVUrqQzs8Ap9uwDsbOaVE2L-TFbJm3bmUJnY2oV0Syvo3oruYusQ4JF67Bu1WJgOqtCb4rafrA1O5h8Nw7vF5YS9aE1eVi4BV6PcjRRnzI", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53512, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 8000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 7039207021, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "388580917", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=EXbUsVDooDxHM5_AzHrA7o-QzCK36jyxR8GQRzI8E5-2B43EFp7EVQEDgCKWDk69r08LTwoJQ9j-nxciX-UWqJPp0F_zYJWB26OLFqSftcrWjyz2cdPoTjLcLpobtYFCzZzII8aLP32cATCAB-PVjz_YERV4-eRdB2muGegDz8ltueExMYuAEVdeLw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=EhJT5fLJM8z_5ipAkd4SI15OBkbpjU0MOTvGwLLxt3_7Jmpy-_yav_eZxkFjooLOHitMGvsW1Y3LT0bcDNJTfDSuVN1HpntpwvI0f7ZlJZnDnc5deqOHHxb7RmuQLyaRl25_ZqQqZY-q5z-Uf8vqVR8eCitb-Y_Yk7MBe3CrGtIJD0QMYK7nAZHm3Q", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=4azUx5EDycj9pBon_nggsk0D7Tuc8KHLOfEmqkgyuGl2lXj_IhsLcU5MTON33r_JoqaqYTS4WNC1V93A57-HHfDGja4d1kR3N57SX_FdytUd5wqveOyfNpYFEgfKz21WFjzRAT6XBCB5oPeLIcF4CK172f4xrYcf_jKqv1kyyDQ8JgOaDylit_sZVg", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 10000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 8676621644, "startByteOffset": 96986, "isDrm": true, "vmaf": 104, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1970848201", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=_Ji5BquFyfcmfoH2AEeLkd5PFsz71ar_pXJeP9OJI3RoSSTrCnBdZozWnYC1AGOH0BTqs24vtdZSbzb2Vnr1BrZElTY1bpubesVl35sn10yKQlZukvdmZURj9C5gSGA-jrRbug5SDxRC63NDvOx3dGBl6zmNnwkxQmHx39dvPlXrlkC7AktGdOjdWAUO", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=b_sHLeNmmA_brL9D9hv9JL1g2wRb_N81XIbyE5Pd60KcUnjNPyzUw3vKKA1XLUihZkXwNEeYedNZKiHdKqoyODyxcDYvJVJAJN9QpO8MTvTR-4eWiP7fGNCZuio5bSPYBBS7Gcjp5HweXNovT2l1w3er0d5v91jEbEB15pt9qxMns8F8PnJ5Gp5ji-0u", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=_rJdMLQQRHQ8TAAXp-xHqi8_IdwZRSXPTTHMDX9KB1vQYPBK6lJW6AuF7zbaERrEAd7xajn5YGR1hx9mOvKvBdYG6_hYokWuR-JLhdMTRQf5TVd69igL89H42b0C0LIQvG2Lg42JMFBfx9E_8_qgzeGIhVm-Vj9vv6a7Jl7CCfv7uXE4ud0GC4OhWSnH", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 12000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 10281705940, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1783080613", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=yR_Pc-Dv9X4U83O1TJ8MCdRxTxTzfBu3Y7TW0gZQ22MrwPVep0_g0nw3He5OfwctmjCazv3HvIJWinbDZuJlRGH5ppMetfZgv9XtsbwE3DGpNXTgd1ppFLNGOnwpFa1wbOzRTTxbsTUw67gOQiZ0OmPnEXt2rXJvgrYX4zNRbnYcuP9_5nk0RuoJ0owK", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=jFj4DZ5bXs0vIVpLYTrjnVv8gwR6LxohyyhklW0i5Bb3a_FVBYN379D9dkEH-H5_2ln8J4enQGpBZf3MgVqD6k0m8uvcEW5YSZALG8XZJDbE4w9FE9tN8zCshLNxGaUogghcSKLeeCPhpCm3Zre7DYAu8SeVvsVOSjw50JVxQQQB6ppmNrnwkou-4IE3", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=VRxTXickxLcxVvDx7dsw09wM0CmaxXcQWOBkOgcdWKkNk0yPowifwTf94hKUA8mnmFxjNCm1DOLMMnUPwrTxNXTxfIfOm-pRz-bC-fhDYaEt3FBs93t1l_9HiBhpyS2Ony_uTzcAxfQ4HDPOpuiN17W7ge0P-8Ejsbyxb2MfKnld_agPCQehar8hwxfw", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}, {"trackType": "PRIMARY", "content_profile": "hevc-hdr-main10-L50-dash-cenc-prk", "bitrate": 16000, "peakBitrate": 0, "dimensionsCount": 2, "dimensionsLabel": "2D", "drmHeaderId": "0000000005a2fa070000000000000000", "pix_w": 1, "pix_h": 1, "res_w": 3840, "res_h": 2160, "framerate_value": 24, "framerate_scale": 1, "size": 13371437321, "startByteOffset": 96986, "isDrm": true, "vmaf": 105, "segmentVmaf": [], "crop_x": 0, "crop_y": 278, "crop_w": 3840, "crop_h": 1604, "downloadable_id": "1109298487", "tags": [], "new_stream_id": "todo", "type": 1, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=fJ026gljSDNRtmAZQx1R1vU61v4JWuHMn14DOO9MkWUzUGvNTXIzH8KX5YvY0olT8gJe9vLadRB70_aDRQB9Bc--eriMRd9CWXfZmYS98L1nUj0CO2kTZOqPkyt9JqKodOpB7vFWoLL2SmW8sU3GKT_9NIZWpQl2_HD2wLUGRBr4cuMyzumtcFtssb64", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=6UcOhDNrZFI5ZebVDoFGvaNrd9Oo3k9FkKCNWLwQQ9oNhvOHMXTLQIPnVKr3bTAc2rn1PFtR5xM0Ax4qSm1DJnsjqqbSh3GZPBV5dyimz2vadq8rbJOfVNU4pvXsqj_CxTiA6c8eYWDQaBDBMOxlhPGOe0li5MGgf7qEYpxISBPoxNeyC2i3_i9p59vo", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=QpHczOyD-ivB4dZZKsG-dNAT0czVs0EByf9p78g2ngCO5uVbbyRmtazcxLhZ-ldYIJ902YY4rHCFlQz-iP-bfxd-ltWX2zrnY6HvLlwKgfz2XY6sRYxPO98nZ6AH7S4LhIMaYYRMTFzkk4pRcVFykDVKcH8Lf_9UyjEqGa1NkY0qkKMmU6hdeNy3eMce", "cdn_id": 3}], "moov": {"size": 1869, "offset": 261}, "sidx": {"size": 41812, "offset": 2130}, "ssix": {"size": 53044, "offset": 43942}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "profile": "hevc-hdr-main10-L50-dash-cenc-prk", "pixelAspectX": 1, "pixelAspectY": 1, "maxWidth": 3840, "maxHeight": 2160, "maxCroppedWidth": 3840, "maxCroppedHeight": 1604, "maxCroppedX": 0, "maxCroppedY": 278, "max_framerate_value": 24, "max_framerate_scale": 1, "minWidth": 2560, "minHeight": 1440, "minCroppedWidth": 2560, "minCroppedHeight": 1070, "minCroppedX": 0, "minCroppedY": 184, "drmHeader": {"bytes": "AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQAAAAAAWi+gcAAAAAAAAAAA==", "drmHeaderId": "0000000005a2fa070000000000000000", "keyId": "AAAAAAWi+gcAAAAAAAAAAA==", "checksum": "", "resolution": {"width": 3840, "height": 2160}}}], "hasClearProfile": false, "hasDrmProfile": true, "hasClearStreams": false, "hasDrmStreams": true, "audio_tracks": [{"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 3, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430558", "new_stream_id": "2037430558", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=aq4JF2NUxMAUqTL4UZVSklF1khyOifukHDgrC-sPdAPCEiAz8u2BtK_UOjRyQWrHZiHP1Le_dvQEIEsWJMA7KcRxSe_6U0B6cswnUrBop2IqM3WEgPXzKiGwHgjt4hr1EN5o08qWy1-t_2BMimm6odIu6sdu44bxORD43mp8Gkwkk4-IvVkAOAEC", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=po5lKUWXB4xM5LQ788AGxO_3A2BugmvaNivEgwztT7NPgmbBK7AoGrdbMjLvJbq5yC5pDlBPM8_L5XdZiay3hALlB_uXoKgZDBMw-v5fcN11EYa1jQs_LRspmoaATu_zzjuIscogZpupnizSh6Kk7uG5JhF3Sk5DdKv0xJLqZpPoi_FtNH93WZr-", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=wHo4PoikEWl6B6KM1rtAmkqdnU068QeuzOIJUSI53rlTqyp7NLs8FZWa9vEVDaefM9DU3M5Vpc-r9isSBBXNxZ3Ax9l3whsqXmO_IAfX9iZkxPCb9v98G8IGuwpGgn0QQRH1p_l2iY9DdGfzEuYzSBViiaA_Y7l0XKEu-WSPbI2O-MI3b0BF3bHH", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037401654", "new_stream_id": "2037401654", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=iPxj1dRCoTrTYIJXIA3BWY2_M0TMxnWSUHedcXLUhy2Y6p05Ge6K9Y6bb5utglIsWk7aDi6dHi-q6FjtM9Dmz-LFhTEeHJUVHDstp6f71-NQHeX9RI65foDib7KW83r83-jfJgUpADmL7U5Ii2h7Xhtl0whZ4U8J9Q6mj-cj9qWpD-g4rIqg-GnF4g", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=A5sjHay0StS8Y16eKi8IXaVbNRbV17XxsO1iBmXtOLOFW2DntgX_ka7cpmf8393n3KmiEgrlFy1p8DlauR5CkhZstDipWHKn305pcu78yP6KUU1VhvpzHTiqUfSsAOO3X1JfLV5Ygk1Z-baS06taQsWTk_UJOvbd5NiGE9QTAOxisOenuDqXEFCyNw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=lYE8mf0MM67RusFVY7O_CoxACneXuEQVXjzKK2gKZ4js7ENfiSafREnXphUgDBYpHRcpirCZiiX-Mv5VVNLjZZpGoKR4AA7I65sKlReao1fgoSx2ndKmeqByiQ_M0_vNjBPNIwU2wpAchhJdm1wJneP712I9VCrSCIuAMbnKo7BzUzozpMxPV3yCXQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 1, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037426205", "new_stream_id": "2037426205", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=Olmb4suy0MWgsbGwCMZ1gu33emGK4jpafutZTwQnvHy0vMJK9xiJIHRcwQxACNvq6vISmeZeIWMFj6gUWxBCrGBeflpEE9ht3Soy3qBEwcrvPTRwfgKQ7h4reVh9Xr5uYsz16HCTOgmeeGWYbA_Q7NdFEYpQUuRM1DaXy2-4A_WyZjc2yzICWrog", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=k-pJbBB3gciRAqP3Byprsd-rL-sZogP5-nIqrZN1G4ZInJzdgPH3g-TpGNh2H0LDscUaLm8-ez5_fyf7dFTgPcRDsKaXlicXA7iF2o7AjQDCSmQNnHqE7PhW3AZBJLV5oSj1IA5GiH2pjdpzvz7alFTkN5TF43m5sX2qzdzoyS7yaAlx2f12H4v3", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=rdSdUjYjP3glZ-z1AhwMuSZe45jWZ87QRmiTbRJ8HKvEfzQSH4i2NRpQ_3XK7G5vekda1Bud-83Y8TZH8UMpll4LSyV_rsQffm3RgwBM5ZTIQkc92WXSffd-BcfHCsefV_qiVuoS5GMeBg3nALa2beaL-oRG59E9hmtvlswmpsp3BwDFvojUfLCV", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400705", "new_stream_id": "2037400705", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=EK6IDRw6mSU5bJomCbl-mQywqHxc_yDuWB6KQJp1s8xbCb4QBsX_khEYcUYasvflQruq7kZLfPpSypKDHsSyeQsktXysOKRmXGfUne_dbelqQTq-xlycY4Ksq-3yXH-tgX8Tcs19LL5kJzuj9HdcdJ9C-njjipidZeA7sIx0LXWm-dPEhS3RzujQYA", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=hJ39JjgPNiuBE5Oiz3TwGCaWaeAoHEGM_YR1jQ85GL2JxrBN3wYj5eN7A1x5ZQyPVfPxay4rp2sEdLhYVqb3qvlyttAn3MAqiuJ9JZSsvpTLBGejyZkAds5s8mv008jf0yAMwkWDPoAmErjEc8rMJhz4ok6bfOjTmEVbo5wJX9NaKyo7Hp7H7vvoXw", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=V2vWv2cOvGsYwf7FIBM4kH9Jm2QfMwOU2troicZPKfsjCKzLF0G0IiYBDxPTLZ-vvum9HpRQnMyCq_g5__Wurhu2yJ5iJTGlRFoA7tBeEI9NlEGrJlxAqcr9KR9LoIRo1sDHyU7YKmjjoUnjx8jKoMzpFCiwJ0OzqJ6t_D4tgAe95AEwvMrPLMoVLw", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 7, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037430888", "new_stream_id": "2037430888", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Jw6cuqq9R-rKkyArUtqXQOp8NdS-hm2uu8jpkQ7DWEn7fTEtCOI16yMjVBsSIQVN8IKe0ixh0urAWu-Z2ymw71_k1PiScu6BNHPoSIR8XF6ImVMuNppTLgj6o36yt4SBtMOi2bDkEbSJPiP7fyG-P2yJVGwbyDWtCsGcC8nmjG3Psp8M0EKFj5yw", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=ls_bUIXTlV__4jkrKt6oYPzKf6He-WbI11gSGL5y3MQGFRyyJIodo1KarC-gVfD-KzVAklSLOcq6vKfV0QbcaDJb6mjEje6lXQuEfV-GLVCtvBSpBuuwd3UN8vSTYCvYqlLRdB0soYFYKSEH2mSOydMcNxzxREmDi8vuIlDwk0fcSjjSp1gKFwqn", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=lq3pIWv2WOfvONtnD4F-UpD0oMgrz7hUjUm0iZnE-1FypX4r7ZInPGsifBQG_blnb62mXl7HvA-xoIPZcfhflQLERiGC584h61ypdIx5buuFx8rcWYA_zOyVfDY9LWB_6rXxmvbCr34fGUwWdlt4h6qhHJjSTLiqh5k8HRD3EDOhoz_c96BqNygq", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398832", "new_stream_id": "2037398832", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=zHzNK0iA3nv33Fq7owzcknMl860rwW38JePOfzeD3WVlFGfFppeIxPb_9Iq-HpS8w2alNt-JFpt2BAMtKXlQZ_C7IHvmYrXyVHeSQcKJhWWu0RiGxLhpqe_JSvXv441g0Hoy_EzT54oDw8kGJvO7hXc517iELB_OCHVaHXF7iU1hi10t5-xTWHoptA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=9S6-8Q2GueeCstUuqewuZzW-Z7W1tvrjdvmoNgKgUjINLCdqkyCmHQvtU9AnfZCJfvzpLv9fHgNzVN8FlPTKYMwv8cb53WzpMZQJz0ZxFJ5KV108cz8t8WhVemKZYo1-aCk4n5-MnC-hBqV1XZiAr5dtxxINZWl3lAokcH0VgTTOfR2CWvktOYgnWQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=ovFgGtGcm3JhzCTauJ8NwBmxLnXyzWGi5MLzpfHMU3RWRoXjku7In3A3tVSnPoq-tUfX9F2wcvrpCIdoeWNFPbqGN_snhuULDtUANCKgPE3-TsIYXNgD-nFOBfAalzLNdP0n-Xzf_U3i0kFilOLPDcM7ViqKvOx8ZIB2_ptt_Nqd_om72selF7SC7w", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c322e307c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;2;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 6, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037428537", "new_stream_id": "2037428537", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=fbKkIJozMhJbCmkTgF7OvftXK359t964J5SsZi9z0idGREcNUghhl8Z3tE9f8SyEafoTIXaytS6YcgoM0HQJEhs-ykzlvI9j2xkoPiF6XpruW4x9qKUcGICegRm3dOxcuyqOGyTAHpR9MmhtkJd-enqjtwZNmVwI418ASv24xBzjEb0kVTZqXEdp", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=WaHOBMsUde8y8YQOPeXNGe_O8M6GMQD31aJtOMHY3EH5JibrQU0E05KPBS4Fd7zsSb0d-j_xJ8s3G5vknQx9AYCDXPsxIIO7ntRkQ_F0cc7yR2MnIjARTBUQ77qi98vBOBsfRGpoLHAnX_TmOZCkaGIbiQQEFBHKEVQsQ1kXGVvI1qWVz9_o-3WQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=GUbckeljhSplDx_4RAZ8Iyl-GwN4rB8MG1sL9hqTzXIrvCscTDFgK3YlEfgt-wxF9cMPKNZJMy4-gz636ej_9MkjTBl6mgi4z5184nFCvMYqQCroc1di5o24ianGuAkAhAj-UhfSYa_OGqH7CiQESEqzluqrTDOMn_fOBRhQc4C3UUrXPTajkXTG", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037398401", "new_stream_id": "2037398401", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=fgdvhcR9k97xzXd4Oj6wEPM7N8ad9zY4OJOvgvbNZvLiZuCesQmW46NQgdkzWjJ73QxXfZTizyE2Tikh9Z5FijpsfTHZkWHP44HtssWxuQk8oiIogG1VJbxc2aixDhhk10ufNmlRxZuoysZhMwRHJ3FHIjknHO01ObRd4llJ2Puopedwx-DHwK8SZw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=csXzR2R7rZX-63VzmBUeE-PEbsoe6htuMXg3IXdK80_JXhhmHQUOQz9RJXzttr5uWWBwtvjKtB68yI54A6oGAGTPUjbVF9sJz6sWB6R5XAfCE9kQpfUD4hsKLDe3TOR54WdAd5AY-lVR1rvWttDNFaFRGp13PKU5piEzjXZ510je38eo7_FXLpgs_A", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=hhmFK5ffukcL-IscCqstvQDGmfgPeJUyWWXxb0lsklzx38KcGNVSlgjcJcnufbGN7OWUTA55kfrqhSjWZuYuRJ3iPxKSy6gUjpwM4AivSh_aFUUr-ZnGP0ieBlWwAC-ODvXuny_NL4w1_ZaByB7PROewN-EeszL69r1AlRq-3PFRvnQ4tgJwXdGa1A", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "languageDescription": "English [Original]", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c5072696d6172797c747275657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;en;1;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": true, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 2, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "dd-5.1-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632986", "new_stream_id": "2037632986", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=lwccMPQHp5rZk0_S01vTEhVW7BxIpqoLsm7BSzB38AQto2ah6TYGI5yPEKuyZmXOv34Wj3lnHSee-IrsHsQL6eiaFW0C4B2DgKQfWrABF8T7g2l94cObKPgo8dNUwH-Xp8JRagCJGI0nN5_juyG-hgddtp7RLbjpSYpLpIzXOIppiiu8yYN64yAEEQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=hCfzMTS4Ax_ehPrcHMKOdF56E-RFGyNDTmRG6QquGA3RSzn7q59Lb_xbC1MVZfNUw7_Zve3ajCAPVH4T7I0Be1jP8eTWt3V3Jp9GoO3XVWnOhBHloDLVgK4BvhtO4eAvD5Mwc7theVoc6IT870LoEN9I3bXRseKwynj0iSiC1X19QvzYei99zMTXUw", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=80QgZjVP7oJvJNfuJdRpLftAaxpqKxJygcbvJ8TMFGU18m4gAd3juoJvyxIw2Mv_JfCnDqeiygXHwQxy-6BMGSHvDVOY0CwH1DN58OmsAiMwWtKoowJI2hrRVrss5yHYW_5tLkxI0qMBmINLdDQhqFS3oFk5f5PSsPxjPGLSfgWaRP1D3KNlE0tswg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 448, "size": 398321056, "isDrm": false, "downloadable_id": "2038451973", "new_stream_id": "2038451973", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=CfOL_tCuSjxydQwfmBou_ygPmJvWMGC47GR9ql4mMtX49Epe9lKKxVa4Nw8emV7SG3bA5XpoOUw8LMY_QVdgjIjmnYBgnqigVK0SHEhVUD7zA91WOBzI2ZuJ9EGunBSaL2e4UtfgOJi3LzDbTv0FHlks7wLPTpoyg3tiVGJVN_X9-ctpJ-yawtIVyQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=CseDfPwtoYQuDukNvSxtjv6t2ChW0csxiggDYjbcxEpZ2gHG2IBo8DSqoHA0dsZkRk3wCHWH3s3-2GvtHLuHYMzQvtSxb-iJe-7zyIsTtCHrldK9aXtr3UXAncTtS1YrdZT-uEUmQJVLJ7e3CANmY_EgnrXLXy_3N4MpmBhhqq7jFu95Lvegv3ICpg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=nZmkUSUa3XsEkybLTlTuSGhjJzEeIspFABmLz8N2ucpdklFvce_1rEc_lkBvpkyTiJl9HHwTUQyQ8piOrm5J46J1mpMg8j1KaaqvcMZ705hqBaR8pWX4aWUBQpM7e1jursk-EaoQFu0wHzidzrj15axWCvLzhVdeMGMZEEk2T7ywOiIloiCAtBGjGA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 640, "size": 567539104, "isDrm": false, "downloadable_id": "2038451490", "new_stream_id": "2038451490", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=Z4nL4JtS-oc4vzfuVjdZH40_CL7iULrET797MPhHHi9xNmQApjvxqEQy8B9dPvs37eGt6XxBbmxpC0A7HAJqxA9fHuX7_mc9HC-P4R7fl3SVSMoV4IR7lZ7qBvIjdNLfAbAZarCI4i2ylsbzqmGeFy8F_tku55JfLpyVwyhEwNzpmiMOKUiyRWBX4Q", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=fFlAwfF0VbLC7IeRv97uGqKXa5sRV-PFjYiMugJmnZBC1GiY7L99T_mf4mPZFUyQGWtQI3CMnp_Gn61UCX9tUAVWo8kagdHLA33xqAJFnidAa6-bJRePHAu91kVSQWp0YxSZj4UVORGyhIwdr5MjNc7HttmztVkUdqC9NfOgE-kjHcXvsnzla4BwfQ", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=eMy9pJUKlwxoY-VeGVkzCds99f8RfO4oWk00l-mBYimmaKpXNSX3ZTRvzJsW4Yix8LxBXZQUO_wU80vblFn4UjRbUvh9ZsxZ1UCS781_HrIqv810Xni6OVcct0sCC7AHj0FX6lmEG23XmGJkvO9Gu-fglzROlZVZzBEwmYnJ27fq1XOHvFRrnT-1Ew", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-atmos-dash", "bitrate": 768, "size": 680351136, "isDrm": false, "downloadable_id": "2038449646", "new_stream_id": "2038449646", "type": 0, "channels": "5.1", "surroundFormatLabel": "Atmos", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 623, "offset": 241}, "sidx": {"size": 42352, "offset": 864}, "ssix": {"size": 42328, "offset": 43216}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=xUHRJTt5S0Tc0ZbWH7jOai6MN49wlxbGTVlzqxnR6y5_xlJ_EXOHErPcgsttT_sOBeHyzv07kPra62g3Vi-an4w3n6_9E-rLR0kJRlc8ziv1xchJRzHhi33oibVQwVmhaFeqRM9WGyHLUmq40ULyTMEQ9Hcp8xxFOHxIG5-6skWy6dh13N7JoxECZg", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=FgVrpaE3RrXUWtvusjh0D0ufW5EVUtF-pSiN7ewMEpqvBPz2YHYn19bRDfJ-dG-lsfLaJpn1fsZ8RQbG0FkE8liRqEQx4IHrrFP-iyPOGXeC8eCZdQhvX8WtQxDhN7EecsH3SzZ9n7Y7efz-_jq19cwxU53ljmezEOL7RK095mQntovoRb3XLq79jg", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=IHAR1G4zmRxHWxxEboCS8b4FMUGSdgGB8X0eCvq9623gNXivOxU2O1fV8Aj22xTbxtuVo9xwCDn1zCYYQjOJd6P-78Y6amRxFzjqSAexLmCYhregdfXbIox9cGrGoWOZknYPuIUTlh0jy6lDNr82dSroqVcorE7kg_ZlNAxDmUGKRMkIb_EPVWDhCA", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "languageDescription": "Hindi", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "68697c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;hi;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 0, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122172", "new_stream_id": "2038122172", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=Fyk-Ys_026YN4xXEFV-vDnVNdO-q73HRhCnac73tdZGwoziDcBgBjUmOgNx4ZNbQXl-j9zGJbHJB7aV6nUSGro995S6UnYSpaNP0uwwxQgOo-7OeFn3ptGE3lxDzh6ebjAeTlGEvMqhA2XRZWsvEHvVZJpkss_3k6cUcuTbknFNbr1ykwJMU8KdfbA", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=sjHLo_r1-m9GC06Agh4JRPG00BmveHQz74pBoMXlRCf1DFPqSJXfXbF1hluYN_s4suHRbVQme-N0CvzvM5rcOHO9fW6TtKNmeo7poai9UCtdOIkoMs3EzDURDZz3eGAO2-uRF63jkEDbvBgRgQtIaUdI8Ufh527Jd-wmsA_cJnHT1WRKbcRtjrJUOw", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=pRcJD5dgfUiIgBVF2h5Yaz3rTtQIsDzgKfPybsikz99M_uN1OiFavpxRRszINGQoalLYlYgrQ_w11D7YmX0qNGdDCNo21yeMQ8qjzCuPbttPOj-7PLz3RF0n0cJg907SwcTkoiA4hnqFoMSESdolytxwLYYFLg5nJ-kqcJSsLZdCaXXjv0Il3jxz1A", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037632157", "new_stream_id": "2037632157", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=RKDASLLAOWvgIdQHrWVc4qF2Z3q2a0MsByom9-VLsHMsU_uIBF4jyGxbqk0ZYA7hUm-zxN5bBqEpjd84weUp8W_YTxz7wE0gsdSsh3X23L-ucV9ABEvUQV7O7jDCy0CgrNfV74b64ipO1sLMfwF5U2P7dIFyGumLNaZtF35YJHUY46DvA7ABonZiLA", "cdn_id": 1}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=2D4eIW2dmzW2VyNW7JmjyLpiD5fKlLQMRkVfUCGjIG9cLeQTKWsOfuVOES4PDye1Jh__Oa_ovjEf801omuUkBEPqgztN5gdcRHV88aMS9Q2u_HpxRpnfSrVYUaHjpgZYKIz1XfhmTZY_OyXqHWgjA0SWd4W16_VV38P0ZzzaOtqPCwmIj1fLm5-mpw", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786312&t=I_Q71nP-PVCyE2ke0z_EortWoOhrwlPZb2WrXyHIkVSS9aphMFM22DQiufYbd2XSwWXiV2YMzNxLQrynTwACZfs1mMgX1kVRwx3Zyir6MGusz73jfLnf0uVSOmn7OrrmS00SMtPVvrtyKejvrKu4fPaRjGxxqz8q4VkzO9FEDSeXeJqJLv1KWJ65yw", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887207", "new_stream_id": "2037887207", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=nJx1pSGAhMLPCTT9Slgjl9gAuOpvWBbHqXeWG4spvelpgPKlxd8bxEVOr-FqYAc559zv2H2eOFtykIva0f_NPTX6v5dspZkGIuV9557whwVzrsSLhj62b-pxreLSfUleEDFKY8fahtALBlvC10r6biQrud9Rw42kYRGjgXqYk1ezr6QtTR3Mc18XMg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=cKTFTIP4Ytgkbcqip_SqyEqfXZ5tqNd24vVcWFj2wYvwmEyiGQ_UJzGbmumgURLN-JWlX-uL3KfrVdhWDImbz9R2N0mjniVjm6mn_T3QD5V9meJnAFtVZ-FqY_5h_Aq1KvBPD-LYC-6gFZMtb-XuIcrBS4vMRYGWGRfKcmfVz2u-9h30ADzEkcSkHQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=9Hh9XNPwDh8QWAG7u7DeYUVg11IqEcC5RJPohjILe4k2gOnuT2X5qQwQ4O-eV-bcXlMS5ZzkFLGaG9ai_OBUThVU1TEpxhM05YIiRNNVWGhNiIoMU7_ZbawyEpT5N4q76rucauXfP7f-FfufErpTAVJ8zQDowEA_QHADPjUSz7giqKLFFE953CSEAg", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879190", "new_stream_id": "2037879190", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=GlRBHbTl6iQRFSateZUnetOwQ8ZrxQXg3hOFLwOSr3-GYUvK-56rkjCujkYBsLxv5zDq-uc6ZTVbPVt0a3pJw0d-MvgZ1IMkk2ZkzWrC1RUHCw6AltwbTplkjbT-sjKvhk4OezYSeTU3JBjJ_3ix8VAfYDIfjCZ-2uYRkHg1CHatAns8ZbqBhmKsJw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=_sYGp-4pNvLFUI9rcdUpq1Ihvfamf9gmH8wKuerHrWNAOln40QcGyysovG88SL6V_3hFgw8iGBjmqY5JWm4b-qSujYO359l1jmYiFV_wVadBwTWfqjcH-MA79NcdHuN3e55SAG9yZ2NfoOynta11PPwz8k0JwsO6Q4QiwbT4_dHqfEuZZ-56f0Dslw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=93dwSE9I4v4xsc2OzN7pbSIIKpKaK4AIQ48uC3WGZ25W2mrzBi7J9Ksue-Sfc6PxOvkAdvG001yqIkdmjU-9RFLfMREylXnXyMCgdvS2qSCB5NFRwBZZ8tT97neoRd_gISerXbFixk33uQCrRDJqAWdxd7rJ9z3IrJ3pnZINrtCTHbw_sOBBHXe-tQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621891", "new_stream_id": "2037621891", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "hi", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=s9W8uvY3Ob4yVQ8n-t6LHBeSMPAWEZ7agPRenrY7N6yudYJKY7Bll4sjkUf6yYc6Y6-rhY9Q0fwr3737VUyzqduFqeP5AqZ2dsMDaMZ5Ll0_hMy8nAD8wiEgHNursJL9VbJmN1otm3Qmpe8sgYbTbH8sEo7SHFUH5GPXNMdCcIi8thY3B71j6Uu1IQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=tWbP0EtHsFGIU6NhH6LyLdiUkiuZ8KfAh8Gucbnw5SZpB1d-qGCK8AsWUrpskysNgW2RJSpCQU5IW6ZlAfLMQS7ASo6DWLNSAnMxfnYIkJW7Gfq5mxY5n4wGa5hhcIPVjiedjIZyvRIocoD5JDB_AEugp9VkmjRjyZllOs4Km_ww3nuBqqdfpD3tGQ", "cdn_id": 2}, {"url": "http://182.79.164.55/?o=1&v=31&e=1637786312&t=E_PHfrYMRhuwvOP9HmgUJJK7FpwCwy6BXZI_PBj4jfCARw0Z1OIJWrgmgJfMHCgMv9CsHavS1-OjVWp1KZrauXdRP0gsocD01ImFId5xXMDbCGHbycdthDPTXAUGzkGMjyAORmMUWkog-PLVpzHchmITLE_Pm42iixMYVgBujWWL9MvSHjjcfcHe1g", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "languageDescription": "Tamil", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74617c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;ta;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 5, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038120294", "new_stream_id": "2038120294", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=FSwP9IuG9yrKpAlYdciQDmRvWV_UFTEHoLA_-MsD0Ms4QsTmB0WTEiWNOhXZwpnpULj9gVHJLamt3WTPPCDUAWKqxLPodGBc8CKZlLjBQC3YDQ4HHepmfLARV3lqv7RCioLHvi33JgeJhEE2BNhQCY88fC5SZB6Ms1gQHJ8TH5f_jNFSg2u-xUqgeg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=3viC52lh06KDmNq9__0EXZbrnazpT-eY4yM4PLTMT0YxkEifHy6Mdwht13pgtBREG1O2EZQQnWxiXMrIWPN41FlP2JTB8CUAmn7xT4fWQGiuc-xMT8fOjzxQHgvCsv8sI4ZsVswRhssPdeF9CrlPFmIB9RL1fnnk4zNsbPdXwM05l7qYuthsI0UBlQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=Rn-cpZUQPQ95TPOasOeYgSwjK7gSnuWGAAZRxEYBEa9Jadcj0Gsy84rrxRzReIBTT5X6dvYLnxdtnCABNYmWdINJacLiR7tUdOnFivMkVvtkzwb4qEgEer4rb10tNrtyU4muOP5JC06ICdLwbatBu2PNGhJO6umNktEeXD11PTZ2YS4Z04TZ7iGiBQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630472", "new_stream_id": "2037630472", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=2L0KlE-dVtVtWVeWbsRmyjcbF4-ogY5FnmKU7lJPKwOgk4anqDk6Y0ZbTfhGEcFXa9AqNs5qao5t4826JbIRy6FBLm9gJ1ma26fse0XaZYKEu3yNluZ4q1zM01WdSWu7nfsJQDPFRTg743b-DoJlWqFxJKjwnmTMrs-LUaYauDQTEH7X5KUjhziFyw", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=Vw1GaSbZIQTBx2TU66yuN7M1GgGXaRtv67G6zBiDeTyREQZcpXQ1RXfgvBT-9IMmsqp7Kw64-y826YT71jd8munb3k_4Oj3ypaasr81cVAv9eL4hd_VkShubhOSrUufhjGxRnPzsHkUP-ECzRW4FGEHs6_8Z67nvZ0SjVTr-7NvDedgQZE4eRjK4BQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=MOfU-GoMJJekV-YXxuGa4c7rkMc84jMq1jsmV23B3y4-9n24b4ci2mJNwpXMJnk-i01LvleASolv_SbLPWXXkvEjk8QKrkbnt6HXwKDBtnN9i2CJhgDouDzLSBIxK__B6fb9fbYMnjuhERM_ZSA9SfNzV-JCVPVrXpe7x77uO3TvDDAneYvqDOcH0g", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037887822", "new_stream_id": "2037887822", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=S0y5QfsfypZJae1fG9-epsHMwCZdRNB8G1Wiw9LL79RfO4yvRdkRrQWYCWvv5LdMQyvVQWnsdyaYy4LrXeqciRjCKfRwR1wjiWg5VIpzvihdkFTk8e0NmOk0i9t-h0Oph3Ml7oTFCKJn5TNng0eA433QkdYJmRbJ-cPzpphybFRXJep3riby5T9WyA", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=FtD6k4WmKSc96LaD_zkhimzqWUZxbt3vqwD-1jKRuJCrOFMDT3Kh5w1jBGpFpZEUv2NTMz_srLNXZsX1ptOFfeydQFw9NgL9mH4w02C78RBSpLuvZ6gSi5cCHy29SKMpJ0LELjYka_0Y030ZmbZYXnu3BErXRoOpqiJG7MBeWp723yF7HWRS2Nwzdg", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=YW3Karn6rv0JWmvcr3FD936rw9WzFzqRfx4D48wTahVYq1W4iStrbj2A47ONx7DBTD8IqaBTwWcYP3ElYGo2fHAHfAoJcFDdndkM7iB74gwL5EwhQ4g5gl-t5LCgSceIZpD236aGPKxVuUvArGWIZv2H23kTg7gRiD37j_0DNcrUTin26BHP846S3Q", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882712", "new_stream_id": "2037882712", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Ashr88jh7tkNWeSUyqmV7dAS67RbO2Ns4cdwM6avlOO3eWcueEzrvqqY9Ew9hDOamoWGeRzRAHS94Irl7QPErf03jcCRU3c57BKZd_DdhoUaf0bIt2fHUwLIEciPcz2ia_yB9jLDACPv6I1xIw7D6VEG8zQvLbG6ByM9Rt-auUpeHEpsror0ztWCgA", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=Yxgprh8801J7SKRJY5UsI4JGkbz7sIBfQABuBK-o_-ItAiA9hDpcp73oOcuLOEEyKO3Xqvbwj6xLC393dOgo0AexEIcHR0YtZUUH0ROjw6L8NoxFIQrijjXR2QzUpwXkEGlma7hgC7Q4J_d5DEjN6_rLSrP7MoBjE6VyiMp6-QhPelvVstwv5y1vrQ", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=azWACSFZlNvDlpPBr2gcKz5gOH9uGFFpbjxxKZC4UBDsJLrwXru1z9rEdkQw565eVbQQDjxz87U_svj894phvIKbZ_wkrpmcV0YQvcelNmNZ1kjIhySUQDpJCAYwcw_Ii0ugNCRHiz37437nkjPyqJ8mPASWzWRgXLgsVDUWhP0w8fyq1LtxIAQ0GA", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037621591", "new_stream_id": "2037621591", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "ta", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=CwdH-848sjtbu19xgxy5NgBECbvXHeiCyQUW1fkfw2uAqR4KAAtJbT_7BqisL7d5CUQa5Qgv4tYJqq16t7gDdPyYYr8_HKEBBbJRBPTD9qPmoVEqllTnfAF1a-TUgF_VpeKLKRJ14cHh3py3QOL9z4KOWJRZd2juhuCltLftmzedg5DqB_JbWzRdAg", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=1DD68ElqKpuDPmvS8O06PepLRA4BNnBKFQkr_pXeR8YPaE-7TX81Hj5ao3Hf32FRlz78K4eIb13a6-h4O90ltIE9inBP5oCUhNE-KqH1bbxgtPSHIs2hsl4rAWL1o5ciMUXxLvFQd2wv3UWdaAT2YBqB2WLiTsZLX6VPoUS4BaixsyYkVfPieF6fTw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=t84UFUFMH3gEWXzkNw9UuagybT2XjLHJtSO5WD2L3T4_90fEgMHyXHgp73S0Qhr1ObN0B_a1QKia2gwPOE9rfNlVPZDeT3QYBUDPtOv_odl67XBPp12x_3AW4FsZ463pQI6vUd7208at52RqwVSS2ZjK67VktmYqd72KDuZH5RrXArCH2BZxiliPdQ", "cdn_id": 3}]}]}, {"trackType": "PRIMARY", "rawTrackType": "primary", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "languageDescription": "Telugu", "disallowedSubtitleTracks": ["6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30"], "track_id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "74657c352e317c5072696d6172797c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:1;6;te;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": null, "rank": 4, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2038122469", "new_stream_id": "2038122469", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=X7wO7iGUA8Cfbr2nVaqm0MoqFaLh9I-vDGONdMd00YocVQ5BtrMN88LJmvt4yuiTIaLbCq77zzQ2x2s8XL3ae2W4y-VFzx0l64FpxB2-lWjTrhLGZTc0CY9qnt8Uu54gjSMqxremcwgiltRkdY5fuezpzvEd9MDzyKRQaPUg_AwdySxM6svGpOHudA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=XicsIFbOwIdHjHdAUVJx24okHj8N9-wA5nuVNKNcIOmlh99SVze3siQaO_tk_Z94jpVNnNgxTFNQ6V9fYaWhUyYupIfHfsEbYE8h3YeQSv-u-d6myJhX8McPN-XIjJJreoLRdPPSOAdeJvyDn0lnFuVI1Fq1BcFY4nmjnXwl6Wl4xTHvKFEEPZNYjw", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=T_UVakeWzsqRPxyhGzHn_FrUgDHXJ_NxhplOPk-9WVKfXTu2dpukpH7koNVopEBuoXCiWR5rJGUh9mkeX3NRrheT9IW1JLijgly0WYyDl1vceYCq_8VzgSlz6IJljr54yt18zMV05pFt7OqIs_pJtqOhphbmwbZvRGy6JJe1RTsr4T_kElYhi5fMIQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037633762", "new_stream_id": "2037633762", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=2ggqFhVYmY4lTvrjpKSfCfESKKgYfpL0iF194-lBIA_lLPFtnsMRUp7nOll-GZuRQ64QF_euLUw59tJgTRs7WQb141qfduKY9pXCsvuvnkPSEBzq1GNYTM-uPCufPkHdy0KEPdNVgTBcJyyeQG_bb-4jJqXyDYhN7G-RdEDmBIngiSzxuP1Zkp6KJQ", "cdn_id": 1}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=SmrA_unLfyp4UbycjEYQZ6Y8NDpKxj5zGb242G72tW0aroKADFqralLghGo7xh1xkxY54-lt69aPtXNg0F39-KH7NhCVCrIgSc9QghtqU190wX3i5dvlkyu1gdu6cXUY1tWLwygSGUfQz423uCTGLdH1GsiPDwlJ8xKRdZoGAMCIJrmRIdqpAWfESg", "cdn_id": 2}, {"url": "http://182.79.164.14/?o=1&v=69&e=1637786312&t=rYnWM1EUiHaTFQJfZN5QM35YbolOzC163OxBTfAtNxEL1xohJpjR3F6ivz5kP5LN6pExNy7tjQEy8rVGIGECav-QpCFmHMdZn7vefbTm6NFZFXJifqcGtAj3fRBTJpYYt3j5nF_Ec3plQKGbfah4_PpfnGJgKQNHwAIwJMSq7n2vbc5KAMcrz7ac-Q", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886203", "new_stream_id": "2037886203", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=gcziQeGfF-aZd8kb-23qEhgvb0DGUlPMOv-n5WUUt_qFhWVnSKM6GC8a8Z1iQZmp491rgxBr61U9E_1WmwEY4IyQvWqqWnqbIDN1vwMJDZgu42ytYSr4o5Vi0pnquoOeOif1qQMCPPD-e1lV2cfG5mfB3Ct3xIvYr0obKs63whRLsasgxCsE1yHjFQ", "cdn_id": 1}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=XqYdBbdfF9yuBcCfdAqFkXA_SPaYN1s_ygi0CMwkX-WPJeTFWRO3-KlPSTJwYE3zcbpPzKWq99-xomo5JvpxEBO1HsgASLEFnmF34GI7gnRcFls3DyU7vMChu1-DHyd2ylNyUZd9rQVbocTVSq-SGR8WZnsjNs7ww_knAf-DH6_f0b7MDX-1rV3Keg", "cdn_id": 2}, {"url": "http://45.57.51.148/?o=1&v=17&e=1637786312&t=LKqOXPrREnCNlcUjZHpYuf9D_0NBAS-Rca_EhCqCFthEgD7RdCCXR1i_whVOROwEtuNN0IbsStNLU3DN0giIJgAvBwh_g8glI4bCE6jEXdg5GvNIyTDLigP4b-36xFyFjXsbDUq80ju14b9KsYsEfbJIVVpAN84pjesNi3QRjHVC3_E6su3rW167zQ", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037879896", "new_stream_id": "2037879896", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=PVSNVUqI0A3MGnTCIW46qhU3lh_fIRGvp2VqiyzUEFqhDv2a8H75az5KMBw32mmzekPqbDcbrDIftGbePIenVT_Jv7eCbtKB9oNU3L8dzcDFjDacRZ0Uf9y_BXi92coyvA5ROwehNzJiiEKz-O3MmII8Xm_Vqword6hcU_O1QXN_vz_UbslAnx0rmQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=fWWdMgAsmARrni_p2lH8KTbxNgpDRLw3g7KoUnmJKnYaTKXbueKieI1abTd7VcvKc9JLueCzx6uI-wX987TDC219JQG2hl1UlcbPrtdzkszOGl-jopRX7jjhQ5ZIsLXRE7bx4j_jSIaCkaBhtAG548CnH4Nlq_Z1CUrwpT5bZrGEkOB-uJGKCp8cyA", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=zlVJNCAfRVUhNe0eR0MK0lnWluruYrN-McFI-cQzc-XfdJbxmeq4tJ2b4EYLo37AMkzlEy-HvrK2idu8bHODjVJh39v7HSo4U1X8vVEs30BmWYqQdVXT3peLhwHKBBkXy3kR4zv-fB0r2jApMO-5fnkQYe-S_I2qUsHDjxztHZOghradYsPMkJAw_Q", "cdn_id": 3}]}, {"trackType": "PRIMARY", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037622635", "new_stream_id": "2037622635", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "te", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=6ehwzuyssk83y4Tmlo6g11GeZk2j-l8_2V5fXY5-CETeEMA3K4dkAVZ8RT6qBKwih0zSFvFyBllGZH3VJXXoRdv1tHJgu2RUuq5apVeaQnZ0w7HuPx97pGlOG8eI2jD030Uct4kbLwzhfgIh2JjnOQdVdAXjq3-aa6CUJGJfNukzD56hpeKAtayUpQ", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=BK_EXqvgQscJ9J1gCWeXB5OsZ1Tg8SGZKBU1cSEim_zv2OUZ348UM_pFZKNKIxBfdm-W1lKtKPL3dvQzdXaVZQ3LvE8SWe5qB2UuoYarwqRHPCOW0-HxcnH11yQNrkQnaOUy4M4DIzhb2M8HYFatzpvAQs9k59dGpmJf0gym_aGObsL4Vx296TBaUg", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=R6giLPSPuwW9W7inhEjIRlVOWUU7acLqR5A5jqSpGAQyRvFezTmtxIagZbnaGQyyLd0EAl5s8cSXBLW9wIcolwqJJ9hqrMaqj9gTDe5Dv4P2Nyzl3a32AmpD06AEJ5CijXJpFD4FB7fPi-tocsZPNvWs_shSTNeSF3lIwlNBMmEMeF5UGULtSZKoaw", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c322e307c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;2;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 9, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-2.0-dash", "codecName": "DDPLUS", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 96, "size": 88088363, "isDrm": false, "downloadable_id": "2037429668", "new_stream_id": "2037429668", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=35FHpbSuw1_aWo_E4NzVJizy8Ur06cm6gDgNi73unQMYxBXSPooFc3Xtqfql2JpioeczVFAkKmZpJwl00H-AVCEljhd5nUTumr_vV_HJTNQMPWCdUK7GcCNGWPxaKYa121Oh6M8BPe_-5sgQN7GYiPmBogT3owMibJUZ9-3stTKIwRrBiYesCs0T", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=nWDdSljjtvTu-SufhPgFtnOJGD7BIbrnH_ZsW5B9T6G1BJh1ehvIU9LFiBAACQzGV768JsSfEUOOmF4Zx_QWRZ7lGTSNQo5PZt0T_977UE-B-Yvt6RatRGBD3CB67LNRegPAjkmF3NrhOVt8hbzRTGvaom_PvckO1lYcgUZo386xve3YC6FDjFOh", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=6eURmS0W9PFek7BO4QkUxl1OZOKWlINj8lTlRDHE-ggE_nQteBgSzbLGF3HSAtEkk5_EWHCmCIdrUJ6EbQshHZYMkqHIP2rrmmAdkopy4pe66sE_lih8LyyAjF03WTauwrIrG6GvSbFUO7c_I_8asXa8246ITJovQ4ZCKEM-dnf7ArHvfOfgmj1f", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-2.0-dash", "bitrate": 128, "size": 116291499, "isDrm": false, "downloadable_id": "2037400409", "new_stream_id": "2037400409", "type": 0, "channels": "2.0", "surroundFormatLabel": "2.0", "channelsFormat": "2.0", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=IfUpLEp4gjAsXPG_ocI94xYDLU-GKCHCW6WiR4Dn2qUFdlNWeDrAkRoGZm8JFriRqcqz8lVneJltm5pGGUZTfIOm8MKGi-bZjUG-Gyp8XS-KGi07P_bMjkwbVq5kbL5zUVpF0In-jnnXlx6QAkwTIyPKlGwHiWN8io_wGTjbtW9uOpRR9nKfKW6hKw", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=tXArKTc70xItu2gL1Xg5eNCbKBqvalVBbjPkIIY0ZWWWo_iUa8JzrxUSqES21_Vc8fOHM3CZRaC9qPuhdGiiyNHZjc0e8QvGNoMxMK84ij_kRhh_xTHh6_bmZPbu5fwx44GsqHCqOeDA6htvqtF9pBfjKND1r3qcytjp5v00konI6uvHmzfq5dObag", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=I76BbbB1d7fR5Rj8Q5FVQHKXCrbjzvmrsMAAp0Df25gD5BDNV2aA6-s5E2mTHhZwij_3ASp0Y8XBxvYrXdiG44_tl5ZnE2DBAslNQo2G_f9-YzXuo3XXYa4WMQO27KLkWMa5uFjDFA5kMX6-Q-oqlOj8gXzApdE3KJcYjt4JhvHeuJSDfiUEKZ4sHQ", "cdn_id": 3}]}]}, {"trackType": "ASSISTIVE", "rawTrackType": "assistive", "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "languageDescription": "English - Audio Description", "disallowedSubtitleTracks": ["none"], "track_id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "id": "656e7c352e317c4173736973746976657c66616c73657c6e6f6e657c756e6b6e6f776e7c756e6b6e6f776e7c417564696f7c756e6b6e6f776e7c7c7c6e6f6e657c30", "new_track_id": "A:2:2;6;en;0;0;", "type": 0, "profileType": "AbstractDynamicEnum{name='AUDIO'}", "isNative": false, "isNoneTrack": false, "defaultTimedText": "6e6f6e657c554e4b4e4f574e7c756e6b6e6f776e7c66616c73657c656e7c466f726365647c756e6b6e6f776e7c546578747c7072696d6172797c7c7c6e6f6e657c30", "rank": 8, "offTrackDisallowed": false, "hydrated": true, "stereo": false, "profile": "ddplus-5.1hq-dash", "streams": [{"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 256, "size": 229112339, "isDrm": false, "downloadable_id": "2039673808", "new_stream_id": "2039673808", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=s6p59hkWas_ja20FcsjiE2HgoYsMWkhu4m1IZbCY9I7HKgHGlZFX6aJUcL8SNXRRlkoYZdoyjGcSjN39Gee6RJjjMHe-iv05BVxcaLWYY-b361xKCgnAQnVHtW1CJO58immO8DNZdNvcqB_SJsvA2XutlZ-8YURWLoaqkdQNXuStvjCChAORHwXM8A", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=Q_rlASoaC_qlyCy39oAg20CbagWHTS-hyHSwaRqydCLbpmjIhRU5ypq2o2gYRpVHi3th4G8_JDWBm6XpYT4gG0i0iZXSp7f7TM-ZtK0db0jFfFwjENcZIDw_XCnRUDXT_X7OqybpVcRCPaDQH_ty6S98Vmb5X_jgtK86bgke3LpfUOhH04b70u0Nhg", "cdn_id": 2}, {"url": "http://182.79.164.55/?o=1&v=31&e=1637786312&t=JZ6NtXB9aGjlJ-vmOye0bgRAiFfJUNQdMClQwLWSwO96QfN1BiVJeYcLxkH5_ofaJOkf5ZLSlHO_6Hm1tOvb49jt81Fk164IBMtnXL6ucMUCD3tWU7hQwiCJExY8HuzzgWF5NaL0NDdR0dOyeNKc9ykpTo43CDmytfZrh9Vf1uGx_rChGrqLtcU3zA", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "dd-5.1-dash", "bitrate": 384, "size": 341928977, "isDrm": false, "downloadable_id": "2037630286", "new_stream_id": "2037630286", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 619, "offset": 241}, "sidx": {"size": 42352, "offset": 860}, "ssix": {"size": 42328, "offset": 43212}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=4Oz4-2nHcF86YoeKIHbcIA81cgRu3Ofvg8qEfBnUccGheKhgyk_6vxH0bGVgFQL0PrEGEk-sDRns7RITbHIHsQNeN2cLpULkhp4QJC_flzhbpRCIpKav4uBUDnA7Xr-M14-yhpN55QroRR8D4kvsK2kQe7kRj_pgr_wNge5BkgovH5uE_qFLtQ0M7w", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Fxnya0PltlF0knFZNfDskMoIQyZLOGq8k6dI4MX1aoayPPZD1prBksE4eVPagqzKwxJIHMRLNx8AVhAkRo2wmt6uuYdoYVan1LOKf_W1K4FsfiOTr5QlbF5FmawpckVypO9ve0Ou1IRyX-aq-O3xgB4T4n3vRa4IOJxT0Oh28NybTKvYGG4ZXfQxkg", "cdn_id": 2}, {"url": "http://45.57.84.138/?o=1&v=68&e=1637786312&t=urUMPklLDEANiXNhfKVyhZaSbDf7tniTDr165_H8HAuYnxw5vyRtcnYSMLziCVbCpSgfRKGAkzGwk_k9-r2vyeC9m7WKgfQD7JxRpzcdXJUTVSrxD4cWKWaTHIXmshlU7D-xcn1v1ZzWtzi52aMBrA_mJPKkC16Ys5ntYmxiZTSaY0cw9JanqYQRDQ", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 384, "size": 341928979, "isDrm": false, "downloadable_id": "2037886411", "new_stream_id": "2037886411", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=QjM6Qt0HNBoTl0g19dRAWeuQrvLygEJk6n3Ho7HlcF-2SMC_ytC6SW452rLhE1PxBTIs3hAJxRFSZNH7tZ0VRO-RqV_U-ZtQz_8kiAJb0TEjrd-SUmPIeSGhxOUO0j0YkzbcxN1IrR6Xwv0GxjngF3H6_GJmKsAZx4VesLX68lpGCSAM0vbXgxgRDA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=DkC6uIVRd0bAUySfFbfHor4sIPeFwGRG6ZuO-4FUujF9K1KRHzCySMDeVFudbvoNAFImfdKI-07N_AZlpKkJvNo7SC6zY46jLF87Ase529VWepsom1l18b-w7pB-Scjlt_Ojk7fL6e8GU7SxDo199g0LDpW3eArjXzoZCttd0HThG0H2_z-C47IepQ", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=dP3AgOqXqu8Q_reIgSMlgQDSs1S1wAgMAU0OCoKentfHcHRXvsJMD9nOxWXBSsooxni0pEebbmKOjq6rn_ybJZ4IgXCvb9Gm6Uoxb78-tEhZkMHyZKbmQuBBSOcgsPsVbBOB5eh4vUkWOB0siNcvv1Ew5RfhYBJAz12y8kTIRrHjK5iZ3ssFrLk4vw", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 448, "size": 398337299, "isDrm": false, "downloadable_id": "2037882117", "new_stream_id": "2037882117", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=33e_4gdlCpqzuDunP1Emf7BKw1WVGnEvGseWFz2HWDm_LTnmOuKASaDTtZruQ1fPswicHMslvUonoUt4DJAJHDDvkMTi2s109_JvWMwv0ClltpXWcqictVZfhQ041jd2SNvc9XeUp3SOT-UVSkuRtX4n4EJoTsuBgN_1uSgAMKrVddKL9fmqscMTjA", "cdn_id": 1}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=WH9sOn68fH32Nuvgu52DNgI5cRjq4_3yHn1GQNGKb7coNI4Uvct8TDqYQDIcVP-YPP22Eq2MDwwWjLIoZLeyrigVvpzTJchFDMFsxpQyzpQpAhzVgNvBaHGSmnNoJs1maPAezIDpmsvxhuvYcMnMyPwYmhR64B9_NFQAg6SL98XUigBKmrNgnOI88w", "cdn_id": 2}, {"url": "http://182.79.164.6/?o=1&v=69&e=1637786312&t=wLB6d6c33-h42oqf7xHYeVW-2P2hgBSjcMNPIbAS9WdOv0wfXtTjfcN2RKUozZYSV4gJv0A5tWaF_q1rKKJAtNf2G4R5GEFV8nkTARCbk-fZV-vbHf-grViLP9a_8MhgU0s03a4U7iKJtikbPRk-BWKwFQEvmd5VZ_xX0gKsil2qvDFd9worGm_TJg", "cdn_id": 3}]}, {"trackType": "ASSISTIVE", "content_profile": "ddplus-5.1hq-dash", "bitrate": 640, "size": 567562259, "isDrm": false, "downloadable_id": "2037623180", "new_stream_id": "2037623180", "type": 0, "channels": "5.1", "surroundFormatLabel": "5.1", "channelsFormat": "5.1", "language": "en", "audioKey": null, "tags": [], "moov": {"size": 621, "offset": 241}, "sidx": {"size": 42352, "offset": 862}, "ssix": {"size": 42328, "offset": 43214}, "urls": [{"url": "http://112.133.220.158/?o=1&v=57&e=1637786312&t=r2qg_1t-bYPbGqILtKXLfJWDNvk9Jq6p89qP4OGVVgIkLVx9NEb3Hted_mhZsfvuzVtBpLni5XHyDtXKWx4WE7lJD31xLuV3c5X6gWri1HHZtzQVaJudlVK02CNMTicJaZKAEyno4GDgU-CwhOqrD_ph9TK3z3-FrflPExe0s_uWCtU0o7N7rGFtSQ", "cdn_id": 1}, {"url": "http://182.79.223.246/?o=1&v=69&e=1637786312&t=tLZGJ394Er9FFVzncLvpaFvbJOfgfqP-WJtcnnH5DohB4EcSC_Hku668QpHaV0CbZ2ZBrgBsMwezGPMqHpJCYJXHvjXBXdqGICeZd9q9Q6AJWH8Fr3zsepqxsl3vYroS7rhS1-X9BxUQfQeVf2NuLI3NddMnro2gmIbnDstrzurMlzp8jUxzVf0_OA", "cdn_id": 2}, {"url": "http://182.79.164.61/?o=1&v=31&e=1637786312&t=Btt89S1lNFxYgHkRav-u5xNRjTXzmlCrWKWd6MHzEX_QQkG-dpIwFBF_jHpgjRhOxK1BfeO5g5GAOSd8koeUjEcCQBNmB5uNZNfQMbD6XfipAuJ9Hy_S6H39vy7FWGeKFqBolWNk3YgDkpGyfXU91PCvz8MOhHKqrGFov2axzEfrIOGc1y2BWbtKEA", "cdn_id": 3}]}]}], "trickplays": [], "servers": [{"id": 1, "key": "1-24186-high", "lowgrade": false, "name": "synthetic-1", "rank": 1, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 2, "key": "2-24186-high", "lowgrade": false, "name": "synthetic-2", "rank": 2, "type": "OPEN_CONNECT_APPLIANCE"}, {"id": 3, "key": "3-24186-high", "lowgrade": false, "name": "synthetic-3", "rank": 3, "type": "OPEN_CONNECT_APPLIANCE"}], "locations": [{"key": "1-24186-high", "rank": 1, "weight": 140, "level": 1}, {"key": "2-24186-high", "rank": 2, "weight": 120, "level": 1}, {"key": "3-24186-high", "rank": 3, "weight": 100, "level": 1}], "cdnResponseData": {"pbcid": "6.gdpDeoJeqIH_04bICrxKTRpi_xFfUJ9mGzuXpBa_mYI"}, "steeringAdditionalInfo": {"steeringId": "6.gdpDeoJeqIH_04bICrxKTRpi_xFfUJ9mGzuXpBa_mYI", "additionalGroupNames": [], "streamingClientConfig": {}}, "audioTextShortcuts": [{"id": "440783ab-e57a-4f08-b04f-231ebbfd9c5d", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:0;1;en;1;1;0;"}, {"id": "8387dbdc-e894-4867-a513-831332496256", "audioTrackId": "A:2:1;6;en;1;0;", "textTrackId": "T:2:1;1;en;0;0;0;"}]}} \ No newline at end of file diff --git a/netflix.py b/netflix.py new file mode 100644 index 0000000..58173ac --- /dev/null +++ b/netflix.py @@ -0,0 +1,382 @@ +import argparse +import logging +import sys +import requests +import re +import json + +try: + from http.cookiejar import CookieJar +except ImportError: + from cookielib import CookieJar + +import colorama +from pywidevine.clients.netflix.client import NetflixClient +from pywidevine.clients.netflix.config import NetflixConfig +from pywidevine.clients.netflix.profiles import NetflixProfiles +from pywidevine.downloader.wvdownloader import WvDownloader +from pywidevine.downloader.wvdownloaderconfig import WvDownloaderConfig + + + +parser = argparse.ArgumentParser( + description="netflix content downloader" +) + +parser.add_argument('-t', '--title', + help='title id', + nargs='+', + type=int, + required=True) +parser.add_argument('-o', '--outputfile', + default='out', + nargs='?', + help='output filename (no extension)') +parser.add_argument('-q', '--quality', + help='video resolution', + choices=['480p', '720p', '1080p', '2160p']) +parser.add_argument('-a', '--audiolang', + help='audio language', + type=lambda x: x.split(',')) +parser.add_argument('-p', '--profile', + default='h264', + #choices=['h264', 'hevc', 'hdr', 'all'], + choices=['h264_main', 'h264_high', 'hevc', 'hdr', 'vp9', 'all'], + #choices=['h264', 'h264_hpl', 'hevc', 'hdr', 'vp9', 'all'], + help='video type to download') +parser.add_argument('-k', '--skip-cleanup', action='store_true', help='skip cleanup step') +parser.add_argument('-m', '--dont-mux', + action='store_true', + help='move unmuxed tracks instead of muxing') +parser.add_argument('-i', '--info', action='store_true', help='print track information and exit') +parser.add_argument('-d', '--debug', action='store_true', help='print debug statements') +parser.add_argument('-S', '--subs-only', action='store_true', help='download subtitles and exit') +parser.add_argument('-u', '--sub-type', default='srt', choices=['srt', 'ass', 'none'], + help='subtitle type (or none)') +parser.add_argument('-s', '--season', type=int, help='lookup and download season from title id') +parser.add_argument('-e', + '--episode_start', + dest="episode_start", + help="Recursively rip season number that provided viewable ID belongs to, starting at the episode provided") +parser.add_argument('--skip', type=int, default=0, help='skip episodes in season mode') +parser.add_argument('--region', default='us', choices=['us', 'uk', 'jp', 'ca', 'se', 'ru'], help='region to proxy') +parser.add_argument('--license', + action='store_true', + help='do license request and print decryption keys only') + +args = parser.parse_args() +DEBUG_LEVELKEY_NUM = 21 +logging.addLevelName(DEBUG_LEVELKEY_NUM, "LOGKEY") + + +def logkey(self, message, *args, **kws): + # Yes, logger takes its '*args' as 'args'. + if self.isEnabledFor(DEBUG_LEVELKEY_NUM): + self._log(DEBUG_LEVELKEY_NUM, message, args, **kws) + + +logging.Logger.logkey = logkey + +logger = logging.getLogger() + +if args.license: + logger.setLevel(21) +else: + logger.setLevel(logging.INFO) + +if args.debug: + logger.setLevel(logging.DEBUG) + +ch = logging.StreamHandler(sys.stdout) +ch.setLevel(logging.DEBUG) +formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s - %(message)s') +ch.setFormatter(formatter) +logger.addHandler(ch) + +colorama.init() + +BUILD = '' +SESSION = requests.Session() + + +""" +login_pag = SESSION.get("https://www.netflix.com/login").text +authURL = re.search('name="authURL" value="([^"]+)"', login_pag) +print(authURL) +#authURL = re.search(r'authURL\" value\=\"(.*?)\"', login_pag) +authURL = authURL[1] + +def login(username, password): + # + post_data = { + 'email': username, + 'password': password, + 'rememberMe': 'true', + 'mode': 'login', + 'action': 'loginAction', + 'withFields': 'email,password,rememberMe,nextPage,showPassword', + 'nextPage': '', + 'showPassword': '', + 'authURL': authURL + } + + req = SESSION.post('https://www.netflix.com/login', post_data) + #match =re.search (r'.*"BUILD_IDENTIFIER":"([a-z0-9]+)"', req.text) + match = re.search(r'"BUILD_IDENTIFIER":"([a-z0-9]+)"', req.text) #fix by Castle / https://gist.github.com/xor10/8f65c1e66a34386e1131f8c28ff6bf64#gistcomment-2668063 + + if match is not None: + return match.group(1) + else: + return None +""" + + +def login(username, password): + r = SESSION.get('https://www.netflix.com/login', stream=True, allow_redirects=False, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'}) + loc = None + while 'Location' in r.headers: + loc = r.headers['Location'] + r = SESSION.get(loc, stream=True, allow_redirects=False, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'}) + + x = re.search('name="authURL" value="([^"]+)"', r.text) + if not x: + return + authURL = x.group(1) + post_data = {'userLoginId':username, + 'password':password, + 'rememberMe':'true', + 'mode':'login', + 'flow':'websiteSignUp', + 'action':'loginAction', + 'authURL':authURL, + 'withFields':'userLoginId,password,rememberMe,nextPage,showPassword', + 'nextPage':'', + 'showPassword':''} + req = SESSION.post(loc, post_data, headers={'User-Agent': 'Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.90 Safari/537.36 CrKey/1.17.46278'}) + try: + req.raise_for_status() + except requests.exceptions.HTTPError as e: + print(e) + logger.error(e) + sys.exit(1) + + match = re.search('"BUILD_IDENTIFIER":"([a-z0-9]+)"', req.text) + if match is not None: + return match.group(1) + else: + return + + + +""" +def fetch_metadata(movieid): + #Fetches metadata for a netflix id + req = SESSION.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid) + return json.loads(req.text) +""" + +def parseCookieFile(cookiefile): + """Parse a cookies.txt file and return a dictionary of key value pairs + compatible with requests.""" + + cookies = {} + with open (cookiefile, 'r') as fp: + for line in fp: + if not re.match(r'^\#', line): + lineFields = line.strip().split('\t') + cookies[lineFields[5]] = lineFields[6] + return cookies + + + +#proxies = {"https": "159.100.246.156:45382"} + +def get_build(): + cookies = parseCookieFile('cookies.txt') + post_data = '' + #req1 = SESSION.get('https://www.netflix.com', headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}, cookies=cookies, proxies=proxies) + #print(req1.text) + #exit(1) + req = SESSION.post('https://www.netflix.com/browse', post_data, headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, cookies=cookies) + #req = SESSION.get('https://www.netflix.com/browse', headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, cookies=cookies, proxies=proxies) + match = re.search(r'"BUILD_IDENTIFIER":"([a-z0-9]+)"', req.text) #fix by Castle / https://gist.github.com/xor10/8f65c1e66a34386e1131f8c28ff6bf64#gistcomment-2668063 + return match.group(1) + +def fetch_metadata(movieid): + global BUILD + cookies = parseCookieFile('cookies.txt') + #BUILD = get_build() + BUILD = 'vafe38bd5' + print(BUILD) + #cookies = 'on' + #if BUILD == '': + # BUILD = login(username, password) + """ + if cookies == 'off': + req = SESSION.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false') + else: + req = requests.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false', cookies=cookies) + """ + req = requests.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false', cookies=cookies) + return json.loads(req.text) + + +def fetch_metadata_movie(BUILD, movieid): + #global BUILD + #cookies = 'on' + #if BUILD == '': + # BUILD = login(username, password) + cookies = parseCookieFile('cookies.txt') + #BUILD = get_build() + BUILD = 'vafe38bd5' + print(BUILD) + """ + if cookies == 'off': + req = SESSION.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false') + else: + req = requests.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false', cookies=cookies) + """ + req = requests.get('https://www.netflix.com/api/shakti/' + BUILD + '/metadata?movieid=' + movieid + '&drmSystem=widevine&isWatchlistEnabled=false&isShortformEnabled=false&isVolatileBillboardsEnabled=false', cookies=cookies) + return json.loads(req.text) + +episodes = [] +if args.season: + nf_cfg = NetflixConfig(0, None, None, [], ['all'], None, args.region) + username, password = nf_cfg.get_login() + #BUILD = login(username, password) + if BUILD is not None: + info = fetch_metadata(str(args.title[0])) + serial_title = info['video']['title'] + serial_title = re.sub(r'[/\\:*?"<>|]', '', serial_title) + for season in info['video']['seasons']: + if season['seq'] == args.season: + episode_list = season['episodes'] + #print(len(episode_list)) + if args.episode_start: + #episode_list = episode_list[(int(args.episode_start) - 1):] + episode_list = [episode_list[(int(args.episode_start) - 1)]] + #print(episode_list) + for episode in episode_list: + if episode['seq'] > args.skip: + episodes.append(( + episode['episodeId'], + "{}.S{}E{}.{}".format( + serial_title.replace(' ', '.').replace('"', '.').replace('"', '.').replace('(', '').replace(')', ''), + str(season['seq']).zfill(2), + str(episode['seq']).zfill(2), + episode['title'].replace(',', '').replace(':', '').replace('?', '').replace("'", '').replace(' ', '.').replace('/', '').replace('"', '.').replace('"', '.').replace('(', '').replace(')', '')))) +else: + episodes = [(args.title[0], args.outputfile)] + +def get_movie_name(): + #nf_cfg = NetflixConfig(0, None, None, [], ['all'], None, args.region) + #username, password = nf_cfg.get_login() + #BUILD = '' + #BUILD = login(username, password) + #print(BUILD) + BUILD = globals()['BUILD'] + if BUILD is not None: + info = fetch_metadata_movie(BUILD, str(args.title[0])) + serial_title = info['video']['title'] + #serial_title = 'title' + synopsis = info['video']['synopsis'] + #synopsis = '' + year = info['video']['year'] + #year = str('2019') + try: + boxart = info['video']['boxart'][0]['url'] + except IndexError: + boxart = '' + serial_title = re.sub(r'[/\\:*?"<>|]', '', serial_title) + #print(serial_title) + logger.info("ripping {} {}".format(serial_title, serial_title.replace('"', '.').replace('"', '.').replace('(', '').replace(')', ''))) + logger.info("boxart {} ".format(boxart)) + logger.info("synopsis {} ".format(synopsis)) + logger.info("year {} ".format(year)) + return str(serial_title.replace('"', '.').replace('"', '.').replace('(', '').replace(')', '')) + else: + return str('') + +nf_profiles = NetflixProfiles(args.profile, args.quality) + + +for title, outputfile in episodes: + if args.season: + + if args.profile == 'h264': + codec_name = 'x264' + if args.profile == 'h264_main': + codec_name = 'x264' + if args.profile == 'h264_high': + codec_name = 'x264' + if args.profile == 'hevc': + codec_name = 'h265' + if args.profile == 'hdr': + codec_name = 'hdr' + if args.profile == 'vp9': + codec_name = 'VP9' + + if args.profile == 'all': + codec_name = 'x264' + + group = 'MI' + logger.info("ripping {}: {}".format(title, outputfile)) + outputfile = outputfile + '.' + str(args.quality) + '.NF.WEB-DL.' + 'AUDIOCODEC' + '.' + codec_name + '-' + group + outputfile1 = outputfile + '.' + str(args.quality) + '.NF.WEB-DL.' + 'AUDIOCODEC' + '.' + codec_name + '-' + group + if not args.season: + + if args.profile == 'h264': + codec_name = 'x264' + if args.profile == 'h264_main': + codec_name = 'x264' + if args.profile == 'h264_high': + codec_name = 'x264' + if args.profile == 'hevc': + codec_name = 'h265' + if args.profile == 'hdr': + codec_name = 'hdr' + if args.profile == 'vp9': + codec_name = 'VP9' + + if args.profile == 'all': + codec_name = 'x264' + + group = 'NFT' + logger.info("ripping {}: {}".format(title, outputfile)) + info = fetch_metadata_movie(BUILD, str(args.title[0])) + #print(info) + year = info['video']['year'] + #year = str('2019') + outputfile = get_movie_name().replace("'", '').replace(' ', '.').replace('"', '.').replace('"', '.').replace('(', '').replace(')', '') + '.'+ str(year) + '.' + str(args.quality) + '.NF.WEB-DL.'+ 'AUDIOCODEC' + '.' + codec_name + '-' + group + outputfile1 = get_movie_name().replace("'", '').replace(' ', '.').replace('"', '.').replace('"', '.').replace('(', '').replace(')', '') + '.'+ str(year) + '.' + str(args.quality) + '.NF.WEB-DL.'+ 'AUDIOCODEC' + '.' + codec_name + '-' + group + if args.audiolang: + audiolang = args.audiolang + else: + audiolang = None + if args.quality is not None: + profiles = nf_profiles.get_all() + else: + profiles = nf_profiles.get_all() + nf_cfg = NetflixConfig(title, profiles, None, [], ['all'], audiolang, args.region) + nf_client = NetflixClient(nf_cfg) + """ + if not args.season: + outputfile = outputfile + '_' + str(args.profile) + outputfile1 = outputfile + '_' + str(args.profile) + else: + outputfile1 = outputfile + '_' + str(args.profile) + outputfile = outputfile + '_' + str(args.profile) + """ + wvdownloader_config = WvDownloaderConfig(nf_client, + outputfile, + args.sub_type, + args.info, + args.skip_cleanup, + args.dont_mux, + args.subs_only, + args.license, + args.quality, + args.profile) + + wvdownloader = WvDownloader(wvdownloader_config) + wvdownloader.run() diff --git a/netflix.spec b/netflix.spec new file mode 100644 index 0000000..26c9625 --- /dev/null +++ b/netflix.spec @@ -0,0 +1,33 @@ +# -*- mode: python -*- + +block_cipher = None + + +a = Analysis(['netflix.py'], + pathex=['e:\\netflix\\NFTool'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + name='netflix', + debug=False, + strip=False, + upx=True, + console=True ) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + name='netflix') diff --git a/netflix_gui.py b/netflix_gui.py new file mode 100644 index 0000000..ba3b11f --- /dev/null +++ b/netflix_gui.py @@ -0,0 +1,24 @@ +# -*- coding: iso-8859-1 -*- +import wx +#import xenforo +#provider = wx.SimpleHelpProvider() +#wx.HelpProvider_Set(provider) + +import MyFrame + + +class App(wx.App): + def OnInit(self): + wx.InitAllImageHandlers() + self.main = MyFrame.MyFrame(None) + self.main.Show() + self.SetTopWindow(self.main) + return 1 + +def main(): + #application = App(0) + application = App() + application.MainLoop() + +if __name__ == '__main__': + main() diff --git a/pax_global_header b/pax_global_header new file mode 100644 index 0000000..a48d8c9 --- /dev/null +++ b/pax_global_header @@ -0,0 +1 @@ +52 comment=365978a0d3f430e2e24b025580c24cba75154132 diff --git a/pip.exe b/pip.exe new file mode 100644 index 0000000..68525ab Binary files /dev/null and b/pip.exe differ diff --git a/pywidevine/__init__.py b/pywidevine/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/__pycache__/__init__.cpython-36.pyc b/pywidevine/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..c43129c Binary files /dev/null and b/pywidevine/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/__pycache__/__init__.cpython-37.pyc b/pywidevine/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..0d09e5f Binary files /dev/null and b/pywidevine/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/__pycache__/__init__.cpython-39.pyc b/pywidevine/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..752f732 Binary files /dev/null and b/pywidevine/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/cdm/__init__.py b/pywidevine/cdm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/cdm/__pycache__/__init__.cpython-36.pyc b/pywidevine/cdm/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..251cfc1 Binary files /dev/null and b/pywidevine/cdm/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/__init__.cpython-37.pyc b/pywidevine/cdm/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..57be01c Binary files /dev/null and b/pywidevine/cdm/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/cdm/__pycache__/__init__.cpython-38.pyc b/pywidevine/cdm/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..b16facd Binary files /dev/null and b/pywidevine/cdm/__pycache__/__init__.cpython-38.pyc differ diff --git a/pywidevine/cdm/__pycache__/__init__.cpython-39.pyc b/pywidevine/cdm/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..0b867d6 Binary files /dev/null and b/pywidevine/cdm/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/cdm/__pycache__/cdm.cpython-36.pyc b/pywidevine/cdm/__pycache__/cdm.cpython-36.pyc new file mode 100644 index 0000000..02f2ca2 Binary files /dev/null and b/pywidevine/cdm/__pycache__/cdm.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/cdm.cpython-37.pyc b/pywidevine/cdm/__pycache__/cdm.cpython-37.pyc new file mode 100644 index 0000000..0e9971c Binary files /dev/null and b/pywidevine/cdm/__pycache__/cdm.cpython-37.pyc differ diff --git a/pywidevine/cdm/__pycache__/cdm.cpython-38.pyc b/pywidevine/cdm/__pycache__/cdm.cpython-38.pyc new file mode 100644 index 0000000..b8fe35d Binary files /dev/null and b/pywidevine/cdm/__pycache__/cdm.cpython-38.pyc differ diff --git a/pywidevine/cdm/__pycache__/cdm.cpython-39.pyc b/pywidevine/cdm/__pycache__/cdm.cpython-39.pyc new file mode 100644 index 0000000..15ee204 Binary files /dev/null and b/pywidevine/cdm/__pycache__/cdm.cpython-39.pyc differ diff --git a/pywidevine/cdm/__pycache__/deviceconfig.cpython-36.pyc b/pywidevine/cdm/__pycache__/deviceconfig.cpython-36.pyc new file mode 100644 index 0000000..f0aed77 Binary files /dev/null and b/pywidevine/cdm/__pycache__/deviceconfig.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/deviceconfig.cpython-37.pyc b/pywidevine/cdm/__pycache__/deviceconfig.cpython-37.pyc new file mode 100644 index 0000000..654c7e0 Binary files /dev/null and b/pywidevine/cdm/__pycache__/deviceconfig.cpython-37.pyc differ diff --git a/pywidevine/cdm/__pycache__/deviceconfig.cpython-38.pyc b/pywidevine/cdm/__pycache__/deviceconfig.cpython-38.pyc new file mode 100644 index 0000000..a9aad58 Binary files /dev/null and b/pywidevine/cdm/__pycache__/deviceconfig.cpython-38.pyc differ diff --git a/pywidevine/cdm/__pycache__/deviceconfig.cpython-39.pyc b/pywidevine/cdm/__pycache__/deviceconfig.cpython-39.pyc new file mode 100644 index 0000000..9ee3561 Binary files /dev/null and b/pywidevine/cdm/__pycache__/deviceconfig.cpython-39.pyc differ diff --git a/pywidevine/cdm/__pycache__/key.cpython-36.pyc b/pywidevine/cdm/__pycache__/key.cpython-36.pyc new file mode 100644 index 0000000..429e24f Binary files /dev/null and b/pywidevine/cdm/__pycache__/key.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/key.cpython-37.pyc b/pywidevine/cdm/__pycache__/key.cpython-37.pyc new file mode 100644 index 0000000..2e2092e Binary files /dev/null and b/pywidevine/cdm/__pycache__/key.cpython-37.pyc differ diff --git a/pywidevine/cdm/__pycache__/key.cpython-38.pyc b/pywidevine/cdm/__pycache__/key.cpython-38.pyc new file mode 100644 index 0000000..ebf4188 Binary files /dev/null and b/pywidevine/cdm/__pycache__/key.cpython-38.pyc differ diff --git a/pywidevine/cdm/__pycache__/key.cpython-39.pyc b/pywidevine/cdm/__pycache__/key.cpython-39.pyc new file mode 100644 index 0000000..4c9c917 Binary files /dev/null and b/pywidevine/cdm/__pycache__/key.cpython-39.pyc differ diff --git a/pywidevine/cdm/__pycache__/session.cpython-36.pyc b/pywidevine/cdm/__pycache__/session.cpython-36.pyc new file mode 100644 index 0000000..b813f65 Binary files /dev/null and b/pywidevine/cdm/__pycache__/session.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/session.cpython-37.pyc b/pywidevine/cdm/__pycache__/session.cpython-37.pyc new file mode 100644 index 0000000..bebc372 Binary files /dev/null and b/pywidevine/cdm/__pycache__/session.cpython-37.pyc differ diff --git a/pywidevine/cdm/__pycache__/session.cpython-38.pyc b/pywidevine/cdm/__pycache__/session.cpython-38.pyc new file mode 100644 index 0000000..0dc895d Binary files /dev/null and b/pywidevine/cdm/__pycache__/session.cpython-38.pyc differ diff --git a/pywidevine/cdm/__pycache__/session.cpython-39.pyc b/pywidevine/cdm/__pycache__/session.cpython-39.pyc new file mode 100644 index 0000000..3f5b490 Binary files /dev/null and b/pywidevine/cdm/__pycache__/session.cpython-39.pyc differ diff --git a/pywidevine/cdm/__pycache__/wvdecrypt.cpython-36.pyc b/pywidevine/cdm/__pycache__/wvdecrypt.cpython-36.pyc new file mode 100644 index 0000000..464b56b Binary files /dev/null and b/pywidevine/cdm/__pycache__/wvdecrypt.cpython-36.pyc differ diff --git a/pywidevine/cdm/__pycache__/wvdecrypt.cpython-38.pyc b/pywidevine/cdm/__pycache__/wvdecrypt.cpython-38.pyc new file mode 100644 index 0000000..eebd509 Binary files /dev/null and b/pywidevine/cdm/__pycache__/wvdecrypt.cpython-38.pyc differ diff --git a/pywidevine/cdm/cdm.py b/pywidevine/cdm/cdm.py new file mode 100644 index 0000000..e880f1e --- /dev/null +++ b/pywidevine/cdm/cdm.py @@ -0,0 +1,362 @@ +import base64 +import binascii +import logging +import os +import time + +from Cryptodome.Cipher import AES, PKCS1_OAEP +from Cryptodome.Hash import CMAC, HMAC, SHA1, SHA256 +from Cryptodome.PublicKey import RSA +from Cryptodome.Random import get_random_bytes, random +from Cryptodome.Signature import pss +from Cryptodome.Util import Padding +from google.protobuf import text_format +from google.protobuf.message import DecodeError + +from pywidevine.cdm.formats import wv_proto2_pb2 as wv_proto2 +from pywidevine.cdm.key import Key +from pywidevine.cdm.session import Session + + +class Cdm: + def __init__(self): + self.logger = logging.getLogger(__name__) + self.sessions = {} + + def open_session(self, init_data_b64, device, raw_init_data = None, offline=False): + + self.logger.debug("open_session(init_data_b64={}, device={}".format(init_data_b64, device)) + self.logger.info("opening new cdm session") + if device.session_id_type == 'android': + # format: 16 random hexdigits, 2 digit counter, 14 0s + rand_ascii = ''.join(random.choice('ABCDEF0123456789') for _ in range(16)) + counter = '01' # this resets regularly so its fine to use 01 + rest = '00000000000000' + session_id = rand_ascii + counter + rest + session_id = session_id.encode('ascii') + elif device.session_id_type == 'chrome': + rand_bytes = get_random_bytes(16) + session_id = rand_bytes + else: + # other formats NYI + self.logger.error("device type is unusable") + return 1 + if raw_init_data and isinstance(raw_init_data, (bytes, bytearray)): + # used for NF key exchange, where they don't provide a valid PSSH + init_data = raw_init_data + self.raw_pssh = True + else: + init_data = self._parse_init_data(init_data_b64) + self.raw_pssh = False + + if init_data: + new_session = Session(session_id, init_data, device, offline) + else: + self.logger.error("unable to parse init data") + return 1 + self.sessions[session_id] = new_session + self.logger.info("session opened and init data parsed successfully") + return session_id + + def _parse_init_data(self, init_data_b64): + parsed_init_data = wv_proto2.WidevineCencHeader() + try: + self.logger.debug("trying to parse init_data directly") + parsed_init_data.ParseFromString(base64.b64decode(init_data_b64)) + except DecodeError: + self.logger.debug("unable to parse as-is, trying with removed pssh box header") + try: + id_bytes = parsed_init_data.ParseFromString(base64.b64decode(init_data_b64)[32:]) + except DecodeError: + self.logger.error("unable to parse, unsupported init data format") + return None + self.logger.debug("init_data:") + for line in text_format.MessageToString(parsed_init_data).splitlines(): + self.logger.debug(line) + return parsed_init_data + + def close_session(self, session_id): + self.logger.debug("close_session(session_id={})".format(session_id)) + self.logger.info("closing cdm session") + if session_id in self.sessions: + self.sessions.pop(session_id) + self.logger.info("cdm session closed") + return 0 + else: + self.logger.info("session {} not found".format(session_id)) + return 1 + + def set_service_certificate(self, session_id, cert_b64): + self.logger.debug("set_service_certificate(session_id={}, cert={})".format(session_id, cert_b64)) + self.logger.info("setting service certificate") + + if session_id not in self.sessions: + self.logger.error("session id doesn't exist") + return 1 + + session = self.sessions[session_id] + + message = wv_proto2.SignedMessage() + + try: + message.ParseFromString(base64.b64decode(cert_b64)) + except DecodeError: + self.logger.error("failed to parse cert as SignedMessage") + + service_certificate = wv_proto2.SignedDeviceCertificate() + + if message.Type: + self.logger.debug("service cert provided as signedmessage") + try: + service_certificate.ParseFromString(message.Msg) + except DecodeError: + self.logger.error("failed to parse service certificate") + return 1 + else: + self.logger.debug("service cert provided as signeddevicecertificate") + try: + service_certificate.ParseFromString(base64.b64decode(cert_b64)) + except DecodeError: + self.logger.error("failed to parse service certificate") + return 1 + + self.logger.debug("service certificate:") + for line in text_format.MessageToString(service_certificate).splitlines(): + self.logger.debug(line) + + session.service_certificate = service_certificate + session.privacy_mode = True + + return 0 + + def get_license_request(self, session_id): + self.logger.debug("get_license_request(session_id={})".format(session_id)) + self.logger.info("getting license request") + + if session_id not in self.sessions: + self.logger.error("session ID does not exist") + return 1 + + session = self.sessions[session_id] + + # raw pssh will be treated as bytes and not parsed + if self.raw_pssh: + license_request = wv_proto2.SignedLicenseRequestRaw() + else: + license_request = wv_proto2.SignedLicenseRequest() + client_id = wv_proto2.ClientIdentification() + + + if not os.path.exists(session.device_config.device_client_id_blob_filename): + self.logger.error("no client ID blob available for this device") + return 1 + + with open(session.device_config.device_client_id_blob_filename, "rb") as f: + try: + cid_bytes = client_id.ParseFromString(f.read()) + except DecodeError: + self.logger.error("client id failed to parse as protobuf") + return 1 + + self.logger.debug("building license request") + if not self.raw_pssh: + license_request.Type = wv_proto2.SignedLicenseRequest.MessageType.Value('LICENSE_REQUEST') + license_request.Msg.ContentId.CencId.Pssh.CopyFrom(session.init_data) + else: + license_request.Type = wv_proto2.SignedLicenseRequestRaw.MessageType.Value('LICENSE_REQUEST') + license_request.Msg.ContentId.CencId.Pssh = session.init_data # bytes + + if session.offline: + license_type = wv_proto2.LicenseType.Value('OFFLINE') + else: + license_type = wv_proto2.LicenseType.Value('DEFAULT') + license_request.Msg.ContentId.CencId.LicenseType = license_type + license_request.Msg.ContentId.CencId.RequestId = session_id + license_request.Msg.Type = wv_proto2.LicenseRequest.RequestType.Value('NEW') + license_request.Msg.RequestTime = int(time.time()) + license_request.Msg.ProtocolVersion = wv_proto2.ProtocolVersion.Value('CURRENT') + if session.device_config.send_key_control_nonce: + license_request.Msg.KeyControlNonce = random.randrange(1, 2**31) + + if session.privacy_mode: + if session.device_config.vmp: + self.logger.debug("vmp required, adding to client_id") + self.logger.debug("reading vmp hashes") + vmp_hashes = wv_proto2.FileHashes() + with open(session.device_config.device_vmp_blob_filename, "rb") as f: + try: + vmp_bytes = vmp_hashes.ParseFromString(f.read()) + except DecodeError: + self.logger.error("vmp hashes failed to parse as protobuf") + return 1 + client_id._FileHashes.CopyFrom(vmp_hashes) + self.logger.debug("privacy mode & service certificate loaded, encrypting client id") + self.logger.debug("unencrypted client id:") + for line in text_format.MessageToString(client_id).splitlines(): + self.logger.debug(line) + cid_aes_key = get_random_bytes(16) + cid_iv = get_random_bytes(16) + + cid_cipher = AES.new(cid_aes_key, AES.MODE_CBC, cid_iv) + + encrypted_client_id = cid_cipher.encrypt(Padding.pad(client_id.SerializeToString(), 16)) + + service_public_key = RSA.importKey(session.service_certificate._DeviceCertificate.PublicKey) + + service_cipher = PKCS1_OAEP.new(service_public_key) + + encrypted_cid_key = service_cipher.encrypt(cid_aes_key) + + encrypted_client_id_proto = wv_proto2.EncryptedClientIdentification() + + encrypted_client_id_proto.ServiceId = session.service_certificate._DeviceCertificate.ServiceId + encrypted_client_id_proto.ServiceCertificateSerialNumber = session.service_certificate._DeviceCertificate.SerialNumber + encrypted_client_id_proto.EncryptedClientId = encrypted_client_id + encrypted_client_id_proto.EncryptedClientIdIv = cid_iv + encrypted_client_id_proto.EncryptedPrivacyKey = encrypted_cid_key + + license_request.Msg.EncryptedClientId.CopyFrom(encrypted_client_id_proto) + else: + license_request.Msg.ClientId.CopyFrom(client_id) + if session.device_config.private_key_available: + key = RSA.importKey(open(session.device_config.device_private_key_filename).read()) + session.device_key = key + else: + self.logger.error("need device private key, other methods unimplemented") + return 1 + + self.logger.debug("signing license request") + + hash = SHA1.new(license_request.Msg.SerializeToString()) + signature = pss.new(key).sign(hash) + + license_request.Signature = signature + + session.license_request = license_request + + self.logger.debug("license request:") + for line in text_format.MessageToString(session.license_request).splitlines(): + self.logger.debug(line) + self.logger.info("license request created") + self.logger.debug("license request b64: {}".format(base64.b64encode(license_request.SerializeToString()))) + return license_request.SerializeToString() + + def provide_license(self, session_id, license_b64): + self.logger.debug("provide_license(session_id={}, license_b64={})".format(session_id, license_b64)) + self.logger.info("decrypting provided license") + + if session_id not in self.sessions: + self.logger.error("session does not exist") + return 1 + + session = self.sessions[session_id] + + if not session.license_request: + self.logger.error("generate a license request first!") + return 1 + + license = wv_proto2.SignedLicense() + try: + license.ParseFromString(base64.b64decode(license_b64)) + except DecodeError: + self.logger.error("unable to parse license - check protobufs") + return 1 + + session.license = license + + self.logger.debug("license:") + for line in text_format.MessageToString(license).splitlines(): + self.logger.debug(line) + + self.logger.debug("deriving keys from session key") + + oaep_cipher = PKCS1_OAEP.new(session.device_key) + + session.session_key = oaep_cipher.decrypt(license.SessionKey) + + lic_req_msg = session.license_request.Msg.SerializeToString() + + enc_key_base = b"ENCRYPTION\000" + lic_req_msg + b"\0\0\0\x80" + auth_key_base = b"AUTHENTICATION\0" + lic_req_msg + b"\0\0\2\0" + + enc_key = b"\x01" + enc_key_base + auth_key_1 = b"\x01" + auth_key_base + auth_key_2 = b"\x02" + auth_key_base + auth_key_3 = b"\x03" + auth_key_base + auth_key_4 = b"\x04" + auth_key_base + + cmac_obj = CMAC.new(session.session_key, ciphermod=AES) + cmac_obj.update(enc_key) + + enc_cmac_key = cmac_obj.digest() + + cmac_obj = CMAC.new(session.session_key, ciphermod=AES) + cmac_obj.update(auth_key_1) + auth_cmac_key_1 = cmac_obj.digest() + + cmac_obj = CMAC.new(session.session_key, ciphermod=AES) + cmac_obj.update(auth_key_2) + auth_cmac_key_2 = cmac_obj.digest() + + cmac_obj = CMAC.new(session.session_key, ciphermod=AES) + cmac_obj.update(auth_key_3) + auth_cmac_key_3 = cmac_obj.digest() + + cmac_obj = CMAC.new(session.session_key, ciphermod=AES) + cmac_obj.update(auth_key_4) + auth_cmac_key_4 = cmac_obj.digest() + + auth_cmac_combined_1 = auth_cmac_key_1 + auth_cmac_key_2 + auth_cmac_combined_2 = auth_cmac_key_3 + auth_cmac_key_4 + + session.derived_keys['enc'] = enc_cmac_key + session.derived_keys['auth_1'] = auth_cmac_combined_1 + session.derived_keys['auth_2'] = auth_cmac_combined_2 + + self.logger.debug('verifying license signature') + + lic_hmac = HMAC.new(session.derived_keys['auth_1'], digestmod=SHA256) + lic_hmac.update(license.Msg.SerializeToString()) + + self.logger.debug("calculated sig: {} actual sig: {}".format(lic_hmac.hexdigest(), binascii.hexlify(license.Signature))) + + if lic_hmac.digest() != license.Signature: + self.logger.info("license signature doesn't match - writing bin so they can be debugged") + with open("original_lic.bin", "wb") as f: + f.write(base64.b64decode(license_b64)) + with open("parsed_lic.bin", "wb") as f: + f.write(license.SerializeToString()) + self.logger.info("continuing anyway") + + self.logger.debug("key count: {}".format(len(license.Msg.Key))) + for key in license.Msg.Key: + if key.Id: + key_id = key.Id + else: + key_id = wv_proto2.License.KeyContainer.KeyType.Name(key.Type).encode('utf-8') + encrypted_key = key.Key + iv = key.Iv + type = wv_proto2.License.KeyContainer.KeyType.Name(key.Type) + + cipher = AES.new(session.derived_keys['enc'], AES.MODE_CBC, iv=iv) + decrypted_key = cipher.decrypt(encrypted_key) + if type == "OPERATOR_SESSION": + permissions = [] + perms = key._OperatorSessionKeyPermissions + for (descriptor, value) in perms.ListFields(): + if value == 1: + permissions.append(descriptor.name) + print(permissions) + else: + permissions = [] + session.keys.append(Key(key_id, type, Padding.unpad(decrypted_key, 16), permissions)) + + self.logger.info("decrypted all keys") + return 0 + + def get_keys(self, session_id): + if session_id in self.sessions: + return self.sessions[session_id].keys + else: + self.logger.error("session not found") + return 1 diff --git a/pywidevine/cdm/deviceconfig.py b/pywidevine/cdm/deviceconfig.py new file mode 100644 index 0000000..7e7190f --- /dev/null +++ b/pywidevine/cdm/deviceconfig.py @@ -0,0 +1,61 @@ +import os + + + +device_android_generic_2 = { + 'name': 'android_generic_2', + 'description': 'Generic Field Provisioning 3.0', + 'security_level': 1, + 'session_id_type': 'android', + 'private_key_available': True, + 'vmp': False, + 'send_key_control_nonce': True +} + + + + + + + +devices_available = [device_android_generic_2] + +FILES_FOLDER = 'devices' + +class DeviceConfig: + def __init__(self, device): + self.device_name = device['name'] + self.description = device['description'] + self.security_level = device['security_level'] + self.session_id_type = device['session_id_type'] + self.private_key_available = device['private_key_available'] + self.vmp = device['vmp'] + self.send_key_control_nonce = device['send_key_control_nonce'] + + if 'keybox_filename' in device: + self.keybox_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['keybox_filename']) + else: + self.keybox_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'keybox') + + if 'device_cert_filename' in device: + self.device_cert_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_cert_filename']) + else: + self.device_cert_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_cert') + + if 'device_private_key_filename' in device: + self.device_private_key_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_private_key_filename']) + else: + self.device_private_key_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_private_key') + + if 'device_client_id_blob_filename' in device: + self.device_client_id_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_client_id_blob_filename']) + else: + self.device_client_id_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_client_id_blob') + + if 'device_vmp_blob_filename' in device: + self.device_vmp_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_vmp_blob_filename']) + else: + self.device_vmp_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_vmp_blob') + + def __repr__(self): + return "DeviceConfig(name={}, description={}, security_level={}, session_id_type={}, private_key_available={}, vmp={})".format(self.device_name, self.description, self.security_level, self.session_id_type, self.private_key_available, self.vmp) diff --git a/pywidevine/cdm/devices/android_generic_2/device_client_id_blob b/pywidevine/cdm/devices/android_generic_2/device_client_id_blob new file mode 100644 index 0000000..cc32780 Binary files /dev/null and b/pywidevine/cdm/devices/android_generic_2/device_client_id_blob differ diff --git a/pywidevine/cdm/devices/android_generic_2/device_private_key b/pywidevine/cdm/devices/android_generic_2/device_private_key new file mode 100644 index 0000000..8eab693 --- /dev/null +++ b/pywidevine/cdm/devices/android_generic_2/device_private_key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA4sUKDpvMG/idF8oCH5AVSwFd5Mk+rEwOBsLZMYdliXWe1hn9 +mdE6u9pjsr+bLrZjlKxMFqPPxbIUcC1Ii7BFSje2Fd8kxnaIprQWxDPgK+NSSx7v +Un452TyB1L9lx39ZBt0PlRfwjkCodX+I9y+oBga73NRh7hPbtLzXe/r/ubFBaEu+ +aRkDZBwYPqHgH1RoFLuyFNMjfqGcPosGxceDtvPysmBxB93Hk2evml5fjdYGg6tx +z510g+XFPDFv7GSy1KuWqit83MqzPls9qAQMkwUc05ggjDhGCKW4/p97fn23WDFE +3TzSSsQvyJLKA3s9oJbtJCD/gOHYqDvnWn8zPwIDAQABAoIBAQDCWe1Mp+o+7sx0 +XwWC15HoPruiIXg9YtGCqexLrqcvMEd5Z70Z32BfL8TSpbTyTA78lM6BeNPRs9Yg +bi8GyYQZH7ZG+IAkN+LWPPJmJa+y7ZjSGSkzoksiC+GZ3I/2cwZyA3Qfa+0XfgLi +8PMKJyXyREMt+DgWO57JQC/OakhRdCR19mM6NKd+ynd/IEz/NIbjMLDVKwW8HEPx +N3r5CU9O96nr62DI68KVj3jwUR3cDi/5xfhosYhCQjHJuobNbeFR18dY2nQNLWYd +S0wtskla1fl9eYHwYAzwru4wHT4WJC7+V4pscfCI0YZB6PslxDKrv73l5H1tz4cf +Vy58NRSBAoGBAPSmjoVtQzTvQ6PZIs81SF1ulJI9kUpyFaBoSSgt+2ZkeNtF6Hih +Zm7OVJ9wg9sfjpB3SFBUjuhXz/ts/t6dkA2PgCbrvhBMRKSGbfyhhtM2gRf002I4 +bJ7Y0C/ont4WzC/XbXEkAmh+fG2/JRvbdVQaIdyS6MmVHtCtRsHEQZS5AoGBAO1K +IXOKAFA+320+Hkbqskfevmxrv+JHIdetliaREZwQH+VYUUM8u5/Kt3oyMat+mH90 +rZOKQK2zM8cz4tKclTUT54nrtICxeo6UHVc56FqXZ6sVvVgm8Cnvt1md4XwG4FwQ +r/OlaM6Hr5HRf8dkzuzqm4ZQYRHGzZ6AMphj8Xu3AoGAdmo7p5dIJVH98kuCDrsi +iJ6iaNpF/buUfiyb5EfFXD0bRj7jE6hDdTSHPxjtqVzv2zrxFHipJwqBz5dlEYlA +FWA0ziHiv+66dsveZp4kLQ0/lMHaorre0E/vDJFSe/qa4DksbsvYIo2+WjxfkMk7 +U/bGFwZAiHmWDbkg+16rw3kCgYEAyyodWf9eJVavlakJ404vNrnP8KSQtfyRTUii +toKewTBNHuBvM1JckoPOdCFlxZ+ukfIka56DojU8r+IM4qaOWdOg+sWE1mses9S9 +CmHaPzZC3IjQhRlRp5ZHNcOnu7lnf2wKOmH1Sl+CQydMcDwvr0lvv6AyfDXq9zps +F2365CECgYEAmYgs/qwnh9m0aGDw/ZGrASoE0TxlpizPvsVDGx9t9UGC2Z+5QvAE +ZcQeKoLCbktr0BnRLI+W1g+KpXQGcnSF9VX/qwUlf72XA6C6kobQvW+Yd/H/IN5d +jPqoL/m41rRzm+J+9/Tfc8Aiy1kkllUYnVJdC5QLAIswuhI8lkaFTN4= +-----END RSA PRIVATE KEY----- diff --git a/pywidevine/cdm/formats/__init__.py b/pywidevine/cdm/formats/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-36.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..8e81502 Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..96cf079 Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..083ec49 Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-39.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..1ad47ea Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-36.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-36.pyc new file mode 100644 index 0000000..6d4ad6e Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-36.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc new file mode 100644 index 0000000..972368f Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc new file mode 100644 index 0000000..ea5b500 Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc differ diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-39.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-39.pyc new file mode 100644 index 0000000..0614a57 Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-39.pyc differ diff --git a/pywidevine/cdm/formats/wv_proto2.proto b/pywidevine/cdm/formats/wv_proto2.proto new file mode 100644 index 0000000..04c9809 --- /dev/null +++ b/pywidevine/cdm/formats/wv_proto2.proto @@ -0,0 +1,466 @@ +syntax = "proto2"; + +// from x86 (partial), most of it from the ARM version: +message ClientIdentification { + enum TokenType { + KEYBOX = 0; + DEVICE_CERTIFICATE = 1; + REMOTE_ATTESTATION_CERTIFICATE = 2; + } + message NameValue { + required string Name = 1; + required string Value = 2; + } + message ClientCapabilities { + enum HdcpVersion { + HDCP_NONE = 0; + HDCP_V1 = 1; + HDCP_V2 = 2; + HDCP_V2_1 = 3; + HDCP_V2_2 = 4; + } + optional uint32 ClientToken = 1; + optional uint32 SessionToken = 2; + optional uint32 VideoResolutionConstraints = 3; + optional HdcpVersion MaxHdcpVersion = 4; + optional uint32 OemCryptoApiVersion = 5; + } + required TokenType Type = 1; + //optional bytes Token = 2; // by default the client treats this as blob, but it's usually a DeviceCertificate, so for usefulness sake, I'm replacing it with this one: + optional SignedDeviceCertificate Token = 2; // use this when parsing, "bytes" when building a client id blob + repeated NameValue ClientInfo = 3; + optional bytes ProviderClientToken = 4; + optional uint32 LicenseCounter = 5; + optional ClientCapabilities _ClientCapabilities = 6; // how should we deal with duped names? will have to look at proto docs later + optional FileHashes _FileHashes = 7; // vmp blob goes here +} + +message DeviceCertificate { + enum CertificateType { + ROOT = 0; + INTERMEDIATE = 1; + USER_DEVICE = 2; + SERVICE = 3; + } + required CertificateType Type = 1; // the compiled code reused this as ProvisionedDeviceInfo.WvSecurityLevel, however that is incorrect (compiler aliased it as they're both identical as a structure) + optional bytes SerialNumber = 2; + optional uint32 CreationTimeSeconds = 3; + optional bytes PublicKey = 4; + optional uint32 SystemId = 5; + optional uint32 TestDeviceDeprecated = 6; // is it bool or int? + optional bytes ServiceId = 7; // service URL for service certificates +} + +// missing some references, +message DeviceCertificateStatus { + enum CertificateStatus { + VALID = 0; + REVOKED = 1; + } + optional bytes SerialNumber = 1; + optional CertificateStatus Status = 2; + optional ProvisionedDeviceInfo DeviceInfo = 4; // where is 3? is it deprecated? +} + +message DeviceCertificateStatusList { + optional uint32 CreationTimeSeconds = 1; + repeated DeviceCertificateStatus CertificateStatus = 2; +} + +message EncryptedClientIdentification { + required string ServiceId = 1; + optional bytes ServiceCertificateSerialNumber = 2; + required bytes EncryptedClientId = 3; + required bytes EncryptedClientIdIv = 4; + required bytes EncryptedPrivacyKey = 5; +} + +// todo: fill (for this top-level type, it might be impossible/difficult) +enum LicenseType { + ZERO = 0; + DEFAULT = 1; // 1 is STREAMING/temporary license; on recent versions may go up to 3 (latest x86); it might be persist/don't persist type, unconfirmed + OFFLINE = 2; +} + +// todo: fill (for this top-level type, it might be impossible/difficult) +// this is just a guess because these globals got lost, but really, do we need more? +enum ProtocolVersion { + CURRENT = 21; // don't have symbols for this +} + + +message LicenseIdentification { + optional bytes RequestId = 1; + optional bytes SessionId = 2; + optional bytes PurchaseId = 3; + optional LicenseType Type = 4; + optional uint32 Version = 5; + optional bytes ProviderSessionToken = 6; +} + + +message License { + message Policy { + optional bool CanPlay = 1; // changed from uint32 to bool + optional bool CanPersist = 2; + optional bool CanRenew = 3; + optional uint32 RentalDurationSeconds = 4; + optional uint32 PlaybackDurationSeconds = 5; + optional uint32 LicenseDurationSeconds = 6; + optional uint32 RenewalRecoveryDurationSeconds = 7; + optional string RenewalServerUrl = 8; + optional uint32 RenewalDelaySeconds = 9; + optional uint32 RenewalRetryIntervalSeconds = 10; + optional bool RenewWithUsage = 11; // was uint32 + } + message KeyContainer { + enum KeyType { + SIGNING = 1; + CONTENT = 2; + KEY_CONTROL = 3; + OPERATOR_SESSION = 4; + } + enum SecurityLevel { + SW_SECURE_CRYPTO = 1; + SW_SECURE_DECODE = 2; + HW_SECURE_CRYPTO = 3; + HW_SECURE_DECODE = 4; + HW_SECURE_ALL = 5; + } + message OutputProtection { + enum CGMS { + COPY_FREE = 0; + COPY_ONCE = 2; + COPY_NEVER = 3; + CGMS_NONE = 0x2A; // PC default! + } + optional ClientIdentification.ClientCapabilities.HdcpVersion Hdcp = 1; // it's most likely a copy of Hdcp version available here, but compiler optimized it away + optional CGMS CgmsFlags = 2; + } + message KeyControl { + required bytes KeyControlBlock = 1; // what is this? + required bytes Iv = 2; + } + message OperatorSessionKeyPermissions { + optional uint32 AllowEncrypt = 1; + optional uint32 AllowDecrypt = 2; + optional uint32 AllowSign = 3; + optional uint32 AllowSignatureVerify = 4; + } + message VideoResolutionConstraint { + optional uint32 MinResolutionPixels = 1; + optional uint32 MaxResolutionPixels = 2; + optional OutputProtection RequiredProtection = 3; + } + optional bytes Id = 1; + optional bytes Iv = 2; + optional bytes Key = 3; + optional KeyType Type = 4; + optional SecurityLevel Level = 5; + optional OutputProtection RequiredProtection = 6; + optional OutputProtection RequestedProtection = 7; + optional KeyControl _KeyControl = 8; // duped names, etc + optional OperatorSessionKeyPermissions _OperatorSessionKeyPermissions = 9; // duped names, etc + repeated VideoResolutionConstraint VideoResolutionConstraints = 10; + } + optional LicenseIdentification Id = 1; + optional Policy _Policy = 2; // duped names, etc + repeated KeyContainer Key = 3; + optional uint32 LicenseStartTime = 4; + optional uint32 RemoteAttestationVerified = 5; // bool? + optional bytes ProviderClientToken = 6; + // there might be more, check with newer versions (I see field 7-8 in a lic) + // this appeared in latest x86: + optional uint32 ProtectionScheme = 7; // type unconfirmed fully, but it's likely as WidevineCencHeader describesit (fourcc) +} + +message LicenseError { + enum Error { + INVALID_DEVICE_CERTIFICATE = 1; + REVOKED_DEVICE_CERTIFICATE = 2; + SERVICE_UNAVAILABLE = 3; + } + //LicenseRequest.RequestType ErrorCode; // clang mismatch + optional Error ErrorCode = 1; +} + +message LicenseRequest { + message ContentIdentification { + message CENC { + //optional bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with: + optional WidevineCencHeader Pssh = 1; + optional LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1 (is this persist/don't persist? look into it!) + optional bytes RequestId = 3; + } + message WebM { + optional bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used + optional LicenseType LicenseType = 2; + optional bytes RequestId = 3; + } + message ExistingLicense { + optional LicenseIdentification LicenseId = 1; + optional uint32 SecondsSinceStarted = 2; + optional uint32 SecondsSinceLastPlayed = 3; + optional bytes SessionUsageTableEntry = 4; // interesting! try to figure out the connection between the usage table blob and KCB! + } + optional CENC CencId = 1; + optional WebM WebmId = 2; + optional ExistingLicense License = 3; + } + enum RequestType { + NEW = 1; + RENEWAL = 2; + RELEASE = 3; + } + optional ClientIdentification ClientId = 1; + optional ContentIdentification ContentId = 2; + optional RequestType Type = 3; + optional uint32 RequestTime = 4; + optional bytes KeyControlNonceDeprecated = 5; + optional ProtocolVersion ProtocolVersion = 6; // lacking symbols for this + optional uint32 KeyControlNonce = 7; + optional EncryptedClientIdentification EncryptedClientId = 8; +} + +// raw pssh hack +message LicenseRequestRaw { + message ContentIdentification { + message CENC { + optional bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with: + //optional WidevineCencHeader Pssh = 1; + optional LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1 (is this persist/don't persist? look into it!) + optional bytes RequestId = 3; + } + message WebM { + optional bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used + optional LicenseType LicenseType = 2; + optional bytes RequestId = 3; + } + message ExistingLicense { + optional LicenseIdentification LicenseId = 1; + optional uint32 SecondsSinceStarted = 2; + optional uint32 SecondsSinceLastPlayed = 3; + optional bytes SessionUsageTableEntry = 4; // interesting! try to figure out the connection between the usage table blob and KCB! + } + optional CENC CencId = 1; + optional WebM WebmId = 2; + optional ExistingLicense License = 3; + } + enum RequestType { + NEW = 1; + RENEWAL = 2; + RELEASE = 3; + } + optional ClientIdentification ClientId = 1; + optional ContentIdentification ContentId = 2; + optional RequestType Type = 3; + optional uint32 RequestTime = 4; + optional bytes KeyControlNonceDeprecated = 5; + optional ProtocolVersion ProtocolVersion = 6; // lacking symbols for this + optional uint32 KeyControlNonce = 7; + optional EncryptedClientIdentification EncryptedClientId = 8; +} + + +message ProvisionedDeviceInfo { + enum WvSecurityLevel { + LEVEL_UNSPECIFIED = 0; + LEVEL_1 = 1; + LEVEL_2 = 2; + LEVEL_3 = 3; + } + optional uint32 SystemId = 1; + optional string Soc = 2; + optional string Manufacturer = 3; + optional string Model = 4; + optional string DeviceType = 5; + optional uint32 ModelYear = 6; + optional WvSecurityLevel SecurityLevel = 7; + optional uint32 TestDevice = 8; // bool? +} + + +// todo: fill +message ProvisioningOptions { +} + +// todo: fill +message ProvisioningRequest { +} + +// todo: fill +message ProvisioningResponse { +} + +message RemoteAttestation { + optional EncryptedClientIdentification Certificate = 1; + optional string Salt = 2; + optional string Signature = 3; +} + +// todo: fill +message SessionInit { +} + +// todo: fill +message SessionState { +} + +// todo: fill +message SignedCertificateStatusList { +} + +message SignedDeviceCertificate { + + //optional bytes DeviceCertificate = 1; // again, they use a buffer where it's supposed to be a message, so we'll replace it with what it really is: + optional DeviceCertificate _DeviceCertificate = 1; // how should we deal with duped names? will have to look at proto docs later + optional bytes Signature = 2; + optional SignedDeviceCertificate Signer = 3; +} + + +// todo: fill +message SignedProvisioningMessage { +} + +// the root of all messages, from either server or client +message SignedMessage { + enum MessageType { + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + optional bytes Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + optional bytes SessionKey = 4; // often RSA wrapped for licenses + optional RemoteAttestation RemoteAttestation = 5; +} + + + +// This message is copied from google's docs, not reversed: +message WidevineCencHeader { + enum Algorithm { + UNENCRYPTED = 0; + AESCTR = 1; + }; + optional Algorithm algorithm = 1; + repeated bytes key_id = 2; + + // Content provider name. + optional string provider = 3; + + // A content identifier, specified by content provider. + optional bytes content_id = 4; + + // Track type. Acceptable values are SD, HD and AUDIO. Used to + // differentiate content keys used by an asset. + optional string track_type_deprecated = 5; + + // The name of a registered policy to be used for this asset. + optional string policy = 6; + + // Crypto period index, for media using key rotation. + optional uint32 crypto_period_index = 7; + + // Optional protected context for group content. The grouped_license is a + // serialized SignedMessage. + optional bytes grouped_license = 8; + + // Protection scheme identifying the encryption algorithm. + // Represented as one of the following 4CC values: + // 'cenc' (AESCTR), 'cbc1' (AESCBC), + // 'cens' (AESCTR subsample), 'cbcs' (AESCBC subsample). + optional uint32 protection_scheme = 9; + + // Optional. For media using key rotation, this represents the duration + // of each crypto period in seconds. + optional uint32 crypto_period_seconds = 10; +} + + +// remove these when using it outside of protoc: + +// from here on, it's just for testing, these messages don't exist in the binaries, I'm adding them to avoid detecting type programmatically +message SignedLicenseRequest { + enum MessageType { + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + optional LicenseRequest Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + optional bytes SessionKey = 4; // often RSA wrapped for licenses + optional RemoteAttestation RemoteAttestation = 5; +} + +// hack +message SignedLicenseRequestRaw { + enum MessageType { + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + optional LicenseRequestRaw Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + optional bytes SessionKey = 4; // often RSA wrapped for licenses + optional RemoteAttestation RemoteAttestation = 5; +} + + +message SignedLicense { + enum MessageType { + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + optional License Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + optional bytes SessionKey = 4; // often RSA wrapped for licenses + optional RemoteAttestation RemoteAttestation = 5; +} + +message SignedServiceCertificate { + enum MessageType { + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + optional SignedDeviceCertificate Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + optional bytes SessionKey = 4; // often RSA wrapped for licenses + optional RemoteAttestation RemoteAttestation = 5; +} + +//vmp support +message FileHashes { + message Signature { + optional string filename = 1; + optional bool test_signing = 2; //0 - release, 1 - testing + optional bytes SHA512Hash = 3; + optional bool main_exe = 4; //0 for dlls, 1 for exe, this is field 3 in file + optional bytes signature = 5; + } + optional bytes signer = 1; + repeated Signature signatures = 2; +} diff --git a/pywidevine/cdm/formats/wv_proto2_pb2.py b/pywidevine/cdm/formats/wv_proto2_pb2.py new file mode 100644 index 0000000..4c2a6d1 --- /dev/null +++ b/pywidevine/cdm/formats/wv_proto2_pb2.py @@ -0,0 +1,3324 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: pywidevine/cdm/formats/wv_proto2.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='pywidevine/cdm/formats/wv_proto2.proto', + package='', + syntax='proto2', + serialized_pb=_b('\n&pywidevine/cdm/formats/wv_proto2.proto\"\xe7\x05\n\x14\x43lientIdentification\x12-\n\x04Type\x18\x01 \x02(\x0e\x32\x1f.ClientIdentification.TokenType\x12\'\n\x05Token\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x33\n\nClientInfo\x18\x03 \x03(\x0b\x32\x1f.ClientIdentification.NameValue\x12\x1b\n\x13ProviderClientToken\x18\x04 \x01(\x0c\x12\x16\n\x0eLicenseCounter\x18\x05 \x01(\r\x12\x45\n\x13_ClientCapabilities\x18\x06 \x01(\x0b\x32(.ClientIdentification.ClientCapabilities\x12 \n\x0b_FileHashes\x18\x07 \x01(\x0b\x32\x0b.FileHashes\x1a(\n\tNameValue\x12\x0c\n\x04Name\x18\x01 \x02(\t\x12\r\n\x05Value\x18\x02 \x02(\t\x1a\xa4\x02\n\x12\x43lientCapabilities\x12\x13\n\x0b\x43lientToken\x18\x01 \x01(\r\x12\x14\n\x0cSessionToken\x18\x02 \x01(\r\x12\"\n\x1aVideoResolutionConstraints\x18\x03 \x01(\r\x12L\n\x0eMaxHdcpVersion\x18\x04 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12\x1b\n\x13OemCryptoApiVersion\x18\x05 \x01(\r\"T\n\x0bHdcpVersion\x12\r\n\tHDCP_NONE\x10\x00\x12\x0b\n\x07HDCP_V1\x10\x01\x12\x0b\n\x07HDCP_V2\x10\x02\x12\r\n\tHDCP_V2_1\x10\x03\x12\r\n\tHDCP_V2_2\x10\x04\"S\n\tTokenType\x12\n\n\x06KEYBOX\x10\x00\x12\x16\n\x12\x44\x45VICE_CERTIFICATE\x10\x01\x12\"\n\x1eREMOTE_ATTESTATION_CERTIFICATE\x10\x02\"\x9b\x02\n\x11\x44\x65viceCertificate\x12\x30\n\x04Type\x18\x01 \x02(\x0e\x32\".DeviceCertificate.CertificateType\x12\x14\n\x0cSerialNumber\x18\x02 \x01(\x0c\x12\x1b\n\x13\x43reationTimeSeconds\x18\x03 \x01(\r\x12\x11\n\tPublicKey\x18\x04 \x01(\x0c\x12\x10\n\x08SystemId\x18\x05 \x01(\r\x12\x1c\n\x14TestDeviceDeprecated\x18\x06 \x01(\r\x12\x11\n\tServiceId\x18\x07 \x01(\x0c\"K\n\x0f\x43\x65rtificateType\x12\x08\n\x04ROOT\x10\x00\x12\x10\n\x0cINTERMEDIATE\x10\x01\x12\x0f\n\x0bUSER_DEVICE\x10\x02\x12\x0b\n\x07SERVICE\x10\x03\"\xc4\x01\n\x17\x44\x65viceCertificateStatus\x12\x14\n\x0cSerialNumber\x18\x01 \x01(\x0c\x12:\n\x06Status\x18\x02 \x01(\x0e\x32*.DeviceCertificateStatus.CertificateStatus\x12*\n\nDeviceInfo\x18\x04 \x01(\x0b\x32\x16.ProvisionedDeviceInfo\"+\n\x11\x43\x65rtificateStatus\x12\t\n\x05VALID\x10\x00\x12\x0b\n\x07REVOKED\x10\x01\"o\n\x1b\x44\x65viceCertificateStatusList\x12\x1b\n\x13\x43reationTimeSeconds\x18\x01 \x01(\r\x12\x33\n\x11\x43\x65rtificateStatus\x18\x02 \x03(\x0b\x32\x18.DeviceCertificateStatus\"\xaf\x01\n\x1d\x45ncryptedClientIdentification\x12\x11\n\tServiceId\x18\x01 \x02(\t\x12&\n\x1eServiceCertificateSerialNumber\x18\x02 \x01(\x0c\x12\x19\n\x11\x45ncryptedClientId\x18\x03 \x02(\x0c\x12\x1b\n\x13\x45ncryptedClientIdIv\x18\x04 \x02(\x0c\x12\x1b\n\x13\x45ncryptedPrivacyKey\x18\x05 \x02(\x0c\"\x9c\x01\n\x15LicenseIdentification\x12\x11\n\tRequestId\x18\x01 \x01(\x0c\x12\x11\n\tSessionId\x18\x02 \x01(\x0c\x12\x12\n\nPurchaseId\x18\x03 \x01(\x0c\x12\x1a\n\x04Type\x18\x04 \x01(\x0e\x32\x0c.LicenseType\x12\x0f\n\x07Version\x18\x05 \x01(\r\x12\x1c\n\x14ProviderSessionToken\x18\x06 \x01(\x0c\"\xa1\x0e\n\x07License\x12\"\n\x02Id\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12 \n\x07_Policy\x18\x02 \x01(\x0b\x32\x0f.License.Policy\x12\"\n\x03Key\x18\x03 \x03(\x0b\x32\x15.License.KeyContainer\x12\x18\n\x10LicenseStartTime\x18\x04 \x01(\r\x12!\n\x19RemoteAttestationVerified\x18\x05 \x01(\r\x12\x1b\n\x13ProviderClientToken\x18\x06 \x01(\x0c\x12\x18\n\x10ProtectionScheme\x18\x07 \x01(\r\x1a\xbb\x02\n\x06Policy\x12\x0f\n\x07\x43\x61nPlay\x18\x01 \x01(\x08\x12\x12\n\nCanPersist\x18\x02 \x01(\x08\x12\x10\n\x08\x43\x61nRenew\x18\x03 \x01(\x08\x12\x1d\n\x15RentalDurationSeconds\x18\x04 \x01(\r\x12\x1f\n\x17PlaybackDurationSeconds\x18\x05 \x01(\r\x12\x1e\n\x16LicenseDurationSeconds\x18\x06 \x01(\r\x12&\n\x1eRenewalRecoveryDurationSeconds\x18\x07 \x01(\r\x12\x18\n\x10RenewalServerUrl\x18\x08 \x01(\t\x12\x1b\n\x13RenewalDelaySeconds\x18\t \x01(\r\x12#\n\x1bRenewalRetryIntervalSeconds\x18\n \x01(\r\x12\x16\n\x0eRenewWithUsage\x18\x0b \x01(\x08\x1a\xf9\t\n\x0cKeyContainer\x12\n\n\x02Id\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x12\x0b\n\x03Key\x18\x03 \x01(\x0c\x12+\n\x04Type\x18\x04 \x01(\x0e\x32\x1d.License.KeyContainer.KeyType\x12\x32\n\x05Level\x18\x05 \x01(\x0e\x32#.License.KeyContainer.SecurityLevel\x12\x42\n\x12RequiredProtection\x18\x06 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x43\n\x13RequestedProtection\x18\x07 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x35\n\x0b_KeyControl\x18\x08 \x01(\x0b\x32 .License.KeyContainer.KeyControl\x12[\n\x1e_OperatorSessionKeyPermissions\x18\t \x01(\x0b\x32\x33.License.KeyContainer.OperatorSessionKeyPermissions\x12S\n\x1aVideoResolutionConstraints\x18\n \x03(\x0b\x32/.License.KeyContainer.VideoResolutionConstraint\x1a\xdb\x01\n\x10OutputProtection\x12\x42\n\x04Hdcp\x18\x01 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12>\n\tCgmsFlags\x18\x02 \x01(\x0e\x32+.License.KeyContainer.OutputProtection.CGMS\"C\n\x04\x43GMS\x12\r\n\tCOPY_FREE\x10\x00\x12\r\n\tCOPY_ONCE\x10\x02\x12\x0e\n\nCOPY_NEVER\x10\x03\x12\r\n\tCGMS_NONE\x10*\x1a\x31\n\nKeyControl\x12\x17\n\x0fKeyControlBlock\x18\x01 \x02(\x0c\x12\n\n\x02Iv\x18\x02 \x02(\x0c\x1a|\n\x1dOperatorSessionKeyPermissions\x12\x14\n\x0c\x41llowEncrypt\x18\x01 \x01(\r\x12\x14\n\x0c\x41llowDecrypt\x18\x02 \x01(\r\x12\x11\n\tAllowSign\x18\x03 \x01(\r\x12\x1c\n\x14\x41llowSignatureVerify\x18\x04 \x01(\r\x1a\x99\x01\n\x19VideoResolutionConstraint\x12\x1b\n\x13MinResolutionPixels\x18\x01 \x01(\r\x12\x1b\n\x13MaxResolutionPixels\x18\x02 \x01(\r\x12\x42\n\x12RequiredProtection\x18\x03 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\"J\n\x07KeyType\x12\x0b\n\x07SIGNING\x10\x01\x12\x0b\n\x07\x43ONTENT\x10\x02\x12\x0f\n\x0bKEY_CONTROL\x10\x03\x12\x14\n\x10OPERATOR_SESSION\x10\x04\"z\n\rSecurityLevel\x12\x14\n\x10SW_SECURE_CRYPTO\x10\x01\x12\x14\n\x10SW_SECURE_DECODE\x10\x02\x12\x14\n\x10HW_SECURE_CRYPTO\x10\x03\x12\x14\n\x10HW_SECURE_DECODE\x10\x04\x12\x11\n\rHW_SECURE_ALL\x10\x05\"\x98\x01\n\x0cLicenseError\x12&\n\tErrorCode\x18\x01 \x01(\x0e\x32\x13.LicenseError.Error\"`\n\x05\x45rror\x12\x1e\n\x1aINVALID_DEVICE_CERTIFICATE\x10\x01\x12\x1e\n\x1aREVOKED_DEVICE_CERTIFICATE\x10\x02\x12\x17\n\x13SERVICE_UNAVAILABLE\x10\x03\"\xac\x07\n\x0eLicenseRequest\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12\x38\n\tContentId\x18\x02 \x01(\x0b\x32%.LicenseRequest.ContentIdentification\x12)\n\x04Type\x18\x03 \x01(\x0e\x32\x1b.LicenseRequest.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\xa2\x04\n\x15\x43ontentIdentification\x12:\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.CENC\x12:\n\x06WebmId\x18\x02 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.WebM\x12\x46\n\x07License\x18\x03 \x01(\x0b\x32\x35.LicenseRequest.ContentIdentification.ExistingLicense\x1a_\n\x04\x43\x45NC\x12!\n\x04Pssh\x18\x01 \x01(\x0b\x32\x13.WidevineCencHeader\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"0\n\x0bRequestType\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa9\x07\n\x11LicenseRequestRaw\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12;\n\tContentId\x18\x02 \x01(\x0b\x32(.LicenseRequestRaw.ContentIdentification\x12,\n\x04Type\x18\x03 \x01(\x0e\x32\x1e.LicenseRequestRaw.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\x96\x04\n\x15\x43ontentIdentification\x12=\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32-.LicenseRequestRaw.ContentIdentification.CENC\x12=\n\x06WebmId\x18\x02 \x01(\x0b\x32-.LicenseRequestRaw.ContentIdentification.WebM\x12I\n\x07License\x18\x03 \x01(\x0b\x32\x38.LicenseRequestRaw.ContentIdentification.ExistingLicense\x1aJ\n\x04\x43\x45NC\x12\x0c\n\x04Pssh\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"0\n\x0bRequestType\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa6\x02\n\x15ProvisionedDeviceInfo\x12\x10\n\x08SystemId\x18\x01 \x01(\r\x12\x0b\n\x03Soc\x18\x02 \x01(\t\x12\x14\n\x0cManufacturer\x18\x03 \x01(\t\x12\r\n\x05Model\x18\x04 \x01(\t\x12\x12\n\nDeviceType\x18\x05 \x01(\t\x12\x11\n\tModelYear\x18\x06 \x01(\r\x12=\n\rSecurityLevel\x18\x07 \x01(\x0e\x32&.ProvisionedDeviceInfo.WvSecurityLevel\x12\x12\n\nTestDevice\x18\x08 \x01(\r\"O\n\x0fWvSecurityLevel\x12\x15\n\x11LEVEL_UNSPECIFIED\x10\x00\x12\x0b\n\x07LEVEL_1\x10\x01\x12\x0b\n\x07LEVEL_2\x10\x02\x12\x0b\n\x07LEVEL_3\x10\x03\"\x15\n\x13ProvisioningOptions\"\x15\n\x13ProvisioningRequest\"\x16\n\x14ProvisioningResponse\"i\n\x11RemoteAttestation\x12\x33\n\x0b\x43\x65rtificate\x18\x01 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x12\x0c\n\x04Salt\x18\x02 \x01(\t\x12\x11\n\tSignature\x18\x03 \x01(\t\"\r\n\x0bSessionInit\"\x0e\n\x0cSessionState\"\x1d\n\x1bSignedCertificateStatusList\"\x86\x01\n\x17SignedDeviceCertificate\x12.\n\x12_DeviceCertificate\x18\x01 \x01(\x0b\x32\x12.DeviceCertificate\x12\x11\n\tSignature\x18\x02 \x01(\x0c\x12(\n\x06Signer\x18\x03 \x01(\x0b\x32\x18.SignedDeviceCertificate\"\x1b\n\x19SignedProvisioningMessage\"\x9b\x02\n\rSignedMessage\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedMessage.MessageType\x12\x0b\n\x03Msg\x18\x02 \x01(\x0c\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc5\x02\n\x12WidevineCencHeader\x12\x30\n\talgorithm\x18\x01 \x01(\x0e\x32\x1d.WidevineCencHeader.Algorithm\x12\x0e\n\x06key_id\x18\x02 \x03(\x0c\x12\x10\n\x08provider\x18\x03 \x01(\t\x12\x12\n\ncontent_id\x18\x04 \x01(\x0c\x12\x1d\n\x15track_type_deprecated\x18\x05 \x01(\t\x12\x0e\n\x06policy\x18\x06 \x01(\t\x12\x1b\n\x13\x63rypto_period_index\x18\x07 \x01(\r\x12\x17\n\x0fgrouped_license\x18\x08 \x01(\x0c\x12\x19\n\x11protection_scheme\x18\t \x01(\r\x12\x1d\n\x15\x63rypto_period_seconds\x18\n \x01(\r\"(\n\tAlgorithm\x12\x0f\n\x0bUNENCRYPTED\x10\x00\x12\n\n\x06\x41\x45SCTR\x10\x01\"\xba\x02\n\x14SignedLicenseRequest\x12/\n\x04Type\x18\x01 \x01(\x0e\x32!.SignedLicenseRequest.MessageType\x12\x1c\n\x03Msg\x18\x02 \x01(\x0b\x32\x0f.LicenseRequest\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc3\x02\n\x17SignedLicenseRequestRaw\x12\x32\n\x04Type\x18\x01 \x01(\x0e\x32$.SignedLicenseRequestRaw.MessageType\x12\x1f\n\x03Msg\x18\x02 \x01(\x0b\x32\x12.LicenseRequestRaw\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xa5\x02\n\rSignedLicense\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedLicense.MessageType\x12\x15\n\x03Msg\x18\x02 \x01(\x0b\x32\x08.License\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xcb\x02\n\x18SignedServiceCertificate\x12\x33\n\x04Type\x18\x01 \x01(\x0e\x32%.SignedServiceCertificate.MessageType\x12%\n\x03Msg\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xb5\x01\n\nFileHashes\x12\x0e\n\x06signer\x18\x01 \x01(\x0c\x12)\n\nsignatures\x18\x02 \x03(\x0b\x32\x15.FileHashes.Signature\x1al\n\tSignature\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x14\n\x0ctest_signing\x18\x02 \x01(\x08\x12\x12\n\nSHA512Hash\x18\x03 \x01(\x0c\x12\x10\n\x08main_exe\x18\x04 \x01(\x08\x12\x11\n\tsignature\x18\x05 \x01(\x0c*1\n\x0bLicenseType\x12\x08\n\x04ZERO\x10\x00\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x01\x12\x0b\n\x07OFFLINE\x10\x02*\x1e\n\x0fProtocolVersion\x12\x0b\n\x07\x43URRENT\x10\x15') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +_LICENSETYPE = _descriptor.EnumDescriptor( + name='LicenseType', + full_name='LicenseType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='OFFLINE', index=2, number=2, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=8362, + serialized_end=8411, +) +_sym_db.RegisterEnumDescriptor(_LICENSETYPE) + +LicenseType = enum_type_wrapper.EnumTypeWrapper(_LICENSETYPE) +_PROTOCOLVERSION = _descriptor.EnumDescriptor( + name='ProtocolVersion', + full_name='ProtocolVersion', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='CURRENT', index=0, number=21, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=8413, + serialized_end=8443, +) +_sym_db.RegisterEnumDescriptor(_PROTOCOLVERSION) + +ProtocolVersion = enum_type_wrapper.EnumTypeWrapper(_PROTOCOLVERSION) +ZERO = 0 +DEFAULT = 1 +OFFLINE = 2 +CURRENT = 21 + + +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION = _descriptor.EnumDescriptor( + name='HdcpVersion', + full_name='ClientIdentification.ClientCapabilities.HdcpVersion', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='HDCP_NONE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V1', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2_1', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2_2', index=4, number=4, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=617, + serialized_end=701, +) +_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION) + +_CLIENTIDENTIFICATION_TOKENTYPE = _descriptor.EnumDescriptor( + name='TokenType', + full_name='ClientIdentification.TokenType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='KEYBOX', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEVICE_CERTIFICATE', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REMOTE_ATTESTATION_CERTIFICATE', index=2, number=2, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=703, + serialized_end=786, +) +_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_TOKENTYPE) + +_DEVICECERTIFICATE_CERTIFICATETYPE = _descriptor.EnumDescriptor( + name='CertificateType', + full_name='DeviceCertificate.CertificateType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ROOT', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='INTERMEDIATE', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='USER_DEVICE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=997, + serialized_end=1072, +) +_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATE_CERTIFICATETYPE) + +_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS = _descriptor.EnumDescriptor( + name='CertificateStatus', + full_name='DeviceCertificateStatus.CertificateStatus', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='VALID', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REVOKED', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=1228, + serialized_end=1271, +) +_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS) + +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS = _descriptor.EnumDescriptor( + name='CGMS', + full_name='License.KeyContainer.OutputProtection.CGMS', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='COPY_FREE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='COPY_ONCE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='COPY_NEVER', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CGMS_NONE', index=3, number=42, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=2949, + serialized_end=3016, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS) + +_LICENSE_KEYCONTAINER_KEYTYPE = _descriptor.EnumDescriptor( + name='KeyType', + full_name='License.KeyContainer.KeyType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SIGNING', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CONTENT', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='KEY_CONTROL', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='OPERATOR_SESSION', index=3, number=4, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3351, + serialized_end=3425, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_KEYTYPE) + +_LICENSE_KEYCONTAINER_SECURITYLEVEL = _descriptor.EnumDescriptor( + name='SecurityLevel', + full_name='License.KeyContainer.SecurityLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SW_SECURE_CRYPTO', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SW_SECURE_DECODE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_CRYPTO', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_DECODE', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_ALL', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3427, + serialized_end=3549, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_SECURITYLEVEL) + +_LICENSEERROR_ERROR = _descriptor.EnumDescriptor( + name='Error', + full_name='LicenseError.Error', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='INVALID_DEVICE_CERTIFICATE', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REVOKED_DEVICE_CERTIFICATE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_UNAVAILABLE', index=2, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3608, + serialized_end=3704, +) +_sym_db.RegisterEnumDescriptor(_LICENSEERROR_ERROR) + +_LICENSEREQUEST_REQUESTTYPE = _descriptor.EnumDescriptor( + name='RequestType', + full_name='LicenseRequest.RequestType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NEW', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RENEWAL', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RELEASE', index=2, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4599, + serialized_end=4647, +) +_sym_db.RegisterEnumDescriptor(_LICENSEREQUEST_REQUESTTYPE) + +_LICENSEREQUESTRAW_REQUESTTYPE = _descriptor.EnumDescriptor( + name='RequestType', + full_name='LicenseRequestRaw.RequestType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NEW', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RENEWAL', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RELEASE', index=2, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4599, + serialized_end=4647, +) +_sym_db.RegisterEnumDescriptor(_LICENSEREQUESTRAW_REQUESTTYPE) + +_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL = _descriptor.EnumDescriptor( + name='WvSecurityLevel', + full_name='ProvisionedDeviceInfo.WvSecurityLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LEVEL_UNSPECIFIED', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_1', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_2', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_3', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=5805, + serialized_end=5884, +) +_sym_db.RegisterEnumDescriptor(_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL) + +_SIGNEDMESSAGE_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedMessage.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6450, + serialized_end=6575, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDMESSAGE_MESSAGETYPE) + +_WIDEVINECENCHEADER_ALGORITHM = _descriptor.EnumDescriptor( + name='Algorithm', + full_name='WidevineCencHeader.Algorithm', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNENCRYPTED', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='AESCTR', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6863, + serialized_end=6903, +) +_sym_db.RegisterEnumDescriptor(_WIDEVINECENCHEADER_ALGORITHM) + +_SIGNEDLICENSEREQUEST_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedLicenseRequest.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6450, + serialized_end=6575, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUEST_MESSAGETYPE) + +_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedLicenseRequestRaw.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6450, + serialized_end=6575, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE) + +_SIGNEDLICENSE_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedLicense.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6450, + serialized_end=6575, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSE_MESSAGETYPE) + +_SIGNEDSERVICECERTIFICATE_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedServiceCertificate.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=0, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=4, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6450, + serialized_end=6575, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDSERVICECERTIFICATE_MESSAGETYPE) + + +_CLIENTIDENTIFICATION_NAMEVALUE = _descriptor.Descriptor( + name='NameValue', + full_name='ClientIdentification.NameValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Name', full_name='ClientIdentification.NameValue.Name', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Value', full_name='ClientIdentification.NameValue.Value', index=1, + number=2, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=366, + serialized_end=406, +) + +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES = _descriptor.Descriptor( + name='ClientCapabilities', + full_name='ClientIdentification.ClientCapabilities', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ClientToken', full_name='ClientIdentification.ClientCapabilities.ClientToken', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionToken', full_name='ClientIdentification.ClientCapabilities.SessionToken', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='VideoResolutionConstraints', full_name='ClientIdentification.ClientCapabilities.VideoResolutionConstraints', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='MaxHdcpVersion', full_name='ClientIdentification.ClientCapabilities.MaxHdcpVersion', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='OemCryptoApiVersion', full_name='ClientIdentification.ClientCapabilities.OemCryptoApiVersion', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=409, + serialized_end=701, +) + +_CLIENTIDENTIFICATION = _descriptor.Descriptor( + name='ClientIdentification', + full_name='ClientIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='ClientIdentification.Type', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Token', full_name='ClientIdentification.Token', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ClientInfo', full_name='ClientIdentification.ClientInfo', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderClientToken', full_name='ClientIdentification.ProviderClientToken', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseCounter', full_name='ClientIdentification.LicenseCounter', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_ClientCapabilities', full_name='ClientIdentification._ClientCapabilities', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_FileHashes', full_name='ClientIdentification._FileHashes', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_CLIENTIDENTIFICATION_NAMEVALUE, _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, ], + enum_types=[ + _CLIENTIDENTIFICATION_TOKENTYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=43, + serialized_end=786, +) + + +_DEVICECERTIFICATE = _descriptor.Descriptor( + name='DeviceCertificate', + full_name='DeviceCertificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='DeviceCertificate.Type', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SerialNumber', full_name='DeviceCertificate.SerialNumber', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CreationTimeSeconds', full_name='DeviceCertificate.CreationTimeSeconds', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PublicKey', full_name='DeviceCertificate.PublicKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SystemId', full_name='DeviceCertificate.SystemId', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='TestDeviceDeprecated', full_name='DeviceCertificate.TestDeviceDeprecated', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ServiceId', full_name='DeviceCertificate.ServiceId', index=6, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DEVICECERTIFICATE_CERTIFICATETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=789, + serialized_end=1072, +) + + +_DEVICECERTIFICATESTATUS = _descriptor.Descriptor( + name='DeviceCertificateStatus', + full_name='DeviceCertificateStatus', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='SerialNumber', full_name='DeviceCertificateStatus.SerialNumber', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Status', full_name='DeviceCertificateStatus.Status', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='DeviceInfo', full_name='DeviceCertificateStatus.DeviceInfo', index=2, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1075, + serialized_end=1271, +) + + +_DEVICECERTIFICATESTATUSLIST = _descriptor.Descriptor( + name='DeviceCertificateStatusList', + full_name='DeviceCertificateStatusList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CreationTimeSeconds', full_name='DeviceCertificateStatusList.CreationTimeSeconds', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CertificateStatus', full_name='DeviceCertificateStatusList.CertificateStatus', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1273, + serialized_end=1384, +) + + +_ENCRYPTEDCLIENTIDENTIFICATION = _descriptor.Descriptor( + name='EncryptedClientIdentification', + full_name='EncryptedClientIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ServiceId', full_name='EncryptedClientIdentification.ServiceId', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ServiceCertificateSerialNumber', full_name='EncryptedClientIdentification.ServiceCertificateSerialNumber', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientId', full_name='EncryptedClientIdentification.EncryptedClientId', index=2, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientIdIv', full_name='EncryptedClientIdentification.EncryptedClientIdIv', index=3, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedPrivacyKey', full_name='EncryptedClientIdentification.EncryptedPrivacyKey', index=4, + number=5, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1387, + serialized_end=1562, +) + + +_LICENSEIDENTIFICATION = _descriptor.Descriptor( + name='LicenseIdentification', + full_name='LicenseIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseIdentification.RequestId', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionId', full_name='LicenseIdentification.SessionId', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PurchaseId', full_name='LicenseIdentification.PurchaseId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='LicenseIdentification.Type', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Version', full_name='LicenseIdentification.Version', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderSessionToken', full_name='LicenseIdentification.ProviderSessionToken', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1565, + serialized_end=1721, +) + + +_LICENSE_POLICY = _descriptor.Descriptor( + name='Policy', + full_name='License.Policy', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CanPlay', full_name='License.Policy.CanPlay', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CanPersist', full_name='License.Policy.CanPersist', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CanRenew', full_name='License.Policy.CanRenew', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RentalDurationSeconds', full_name='License.Policy.RentalDurationSeconds', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PlaybackDurationSeconds', full_name='License.Policy.PlaybackDurationSeconds', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseDurationSeconds', full_name='License.Policy.LicenseDurationSeconds', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalRecoveryDurationSeconds', full_name='License.Policy.RenewalRecoveryDurationSeconds', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalServerUrl', full_name='License.Policy.RenewalServerUrl', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalDelaySeconds', full_name='License.Policy.RenewalDelaySeconds', index=8, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalRetryIntervalSeconds', full_name='License.Policy.RenewalRetryIntervalSeconds', index=9, + number=10, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewWithUsage', full_name='License.Policy.RenewWithUsage', index=10, + number=11, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1958, + serialized_end=2273, +) + +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION = _descriptor.Descriptor( + name='OutputProtection', + full_name='License.KeyContainer.OutputProtection', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Hdcp', full_name='License.KeyContainer.OutputProtection.Hdcp', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CgmsFlags', full_name='License.KeyContainer.OutputProtection.CgmsFlags', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2797, + serialized_end=3016, +) + +_LICENSE_KEYCONTAINER_KEYCONTROL = _descriptor.Descriptor( + name='KeyControl', + full_name='License.KeyContainer.KeyControl', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='KeyControlBlock', full_name='License.KeyContainer.KeyControl.KeyControlBlock', index=0, + number=1, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Iv', full_name='License.KeyContainer.KeyControl.Iv', index=1, + number=2, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3018, + serialized_end=3067, +) + +_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS = _descriptor.Descriptor( + name='OperatorSessionKeyPermissions', + full_name='License.KeyContainer.OperatorSessionKeyPermissions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='AllowEncrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowEncrypt', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowDecrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowDecrypt', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowSign', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSign', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowSignatureVerify', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSignatureVerify', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3069, + serialized_end=3193, +) + +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT = _descriptor.Descriptor( + name='VideoResolutionConstraint', + full_name='License.KeyContainer.VideoResolutionConstraint', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='MinResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MinResolutionPixels', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='MaxResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MaxResolutionPixels', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequiredProtection', full_name='License.KeyContainer.VideoResolutionConstraint.RequiredProtection', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3196, + serialized_end=3349, +) + +_LICENSE_KEYCONTAINER = _descriptor.Descriptor( + name='KeyContainer', + full_name='License.KeyContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Id', full_name='License.KeyContainer.Id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Iv', full_name='License.KeyContainer.Iv', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Key', full_name='License.KeyContainer.Key', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='License.KeyContainer.Type', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Level', full_name='License.KeyContainer.Level', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequiredProtection', full_name='License.KeyContainer.RequiredProtection', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestedProtection', full_name='License.KeyContainer.RequestedProtection', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_KeyControl', full_name='License.KeyContainer._KeyControl', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_OperatorSessionKeyPermissions', full_name='License.KeyContainer._OperatorSessionKeyPermissions', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='VideoResolutionConstraints', full_name='License.KeyContainer.VideoResolutionConstraints', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSE_KEYCONTAINER_OUTPUTPROTECTION, _LICENSE_KEYCONTAINER_KEYCONTROL, _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, ], + enum_types=[ + _LICENSE_KEYCONTAINER_KEYTYPE, + _LICENSE_KEYCONTAINER_SECURITYLEVEL, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2276, + serialized_end=3549, +) + +_LICENSE = _descriptor.Descriptor( + name='License', + full_name='License', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Id', full_name='License.Id', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_Policy', full_name='License._Policy', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Key', full_name='License.Key', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseStartTime', full_name='License.LicenseStartTime', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestationVerified', full_name='License.RemoteAttestationVerified', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderClientToken', full_name='License.ProviderClientToken', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProtectionScheme', full_name='License.ProtectionScheme', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSE_POLICY, _LICENSE_KEYCONTAINER, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1724, + serialized_end=3549, +) + + +_LICENSEERROR = _descriptor.Descriptor( + name='LicenseError', + full_name='LicenseError', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ErrorCode', full_name='LicenseError.ErrorCode', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _LICENSEERROR_ERROR, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3552, + serialized_end=3704, +) + + +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor( + name='CENC', + full_name='LicenseRequest.ContentIdentification.CENC', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Pssh', full_name='LicenseRequest.ContentIdentification.CENC.Pssh', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequest.ContentIdentification.CENC.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequest.ContentIdentification.CENC.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4268, + serialized_end=4363, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor( + name='WebM', + full_name='LicenseRequest.ContentIdentification.WebM', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Header', full_name='LicenseRequest.ContentIdentification.WebM.Header', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequest.ContentIdentification.WebM.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequest.ContentIdentification.WebM.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4365, + serialized_end=4441, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor( + name='ExistingLicense', + full_name='LicenseRequest.ContentIdentification.ExistingLicense', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='LicenseId', full_name='LicenseRequest.ContentIdentification.ExistingLicense.LicenseId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceStarted', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceLastPlayed', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionUsageTableEntry', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4444, + serialized_end=4597, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION = _descriptor.Descriptor( + name='ContentIdentification', + full_name='LicenseRequest.ContentIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CencId', full_name='LicenseRequest.ContentIdentification.CencId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='WebmId', full_name='LicenseRequest.ContentIdentification.WebmId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='License', full_name='LicenseRequest.ContentIdentification.License', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4051, + serialized_end=4597, +) + +_LICENSEREQUEST = _descriptor.Descriptor( + name='LicenseRequest', + full_name='LicenseRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ClientId', full_name='LicenseRequest.ClientId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ContentId', full_name='LicenseRequest.ContentId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='LicenseRequest.Type', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestTime', full_name='LicenseRequest.RequestTime', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonceDeprecated', full_name='LicenseRequest.KeyControlNonceDeprecated', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProtocolVersion', full_name='LicenseRequest.ProtocolVersion', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=21, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonce', full_name='LicenseRequest.KeyControlNonce', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientId', full_name='LicenseRequest.EncryptedClientId', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION, ], + enum_types=[ + _LICENSEREQUEST_REQUESTTYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3707, + serialized_end=4647, +) + + +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor( + name='CENC', + full_name='LicenseRequestRaw.ContentIdentification.CENC', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Pssh', full_name='LicenseRequestRaw.ContentIdentification.CENC.Pssh', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequestRaw.ContentIdentification.CENC.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequestRaw.ContentIdentification.CENC.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5229, + serialized_end=5303, +) + +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor( + name='WebM', + full_name='LicenseRequestRaw.ContentIdentification.WebM', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Header', full_name='LicenseRequestRaw.ContentIdentification.WebM.Header', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequestRaw.ContentIdentification.WebM.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequestRaw.ContentIdentification.WebM.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4365, + serialized_end=4441, +) + +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor( + name='ExistingLicense', + full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='LicenseId', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.LicenseId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceStarted', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceLastPlayed', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionUsageTableEntry', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4444, + serialized_end=4597, +) + +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION = _descriptor.Descriptor( + name='ContentIdentification', + full_name='LicenseRequestRaw.ContentIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CencId', full_name='LicenseRequestRaw.ContentIdentification.CencId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='WebmId', full_name='LicenseRequestRaw.ContentIdentification.WebmId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='License', full_name='LicenseRequestRaw.ContentIdentification.License', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC, _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5003, + serialized_end=5537, +) + +_LICENSEREQUESTRAW = _descriptor.Descriptor( + name='LicenseRequestRaw', + full_name='LicenseRequestRaw', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ClientId', full_name='LicenseRequestRaw.ClientId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ContentId', full_name='LicenseRequestRaw.ContentId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='LicenseRequestRaw.Type', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestTime', full_name='LicenseRequestRaw.RequestTime', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonceDeprecated', full_name='LicenseRequestRaw.KeyControlNonceDeprecated', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProtocolVersion', full_name='LicenseRequestRaw.ProtocolVersion', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=21, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonce', full_name='LicenseRequestRaw.KeyControlNonce', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientId', full_name='LicenseRequestRaw.EncryptedClientId', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUESTRAW_CONTENTIDENTIFICATION, ], + enum_types=[ + _LICENSEREQUESTRAW_REQUESTTYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4650, + serialized_end=5587, +) + + +_PROVISIONEDDEVICEINFO = _descriptor.Descriptor( + name='ProvisionedDeviceInfo', + full_name='ProvisionedDeviceInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='SystemId', full_name='ProvisionedDeviceInfo.SystemId', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Soc', full_name='ProvisionedDeviceInfo.Soc', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Manufacturer', full_name='ProvisionedDeviceInfo.Manufacturer', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Model', full_name='ProvisionedDeviceInfo.Model', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='DeviceType', full_name='ProvisionedDeviceInfo.DeviceType', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ModelYear', full_name='ProvisionedDeviceInfo.ModelYear', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecurityLevel', full_name='ProvisionedDeviceInfo.SecurityLevel', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='TestDevice', full_name='ProvisionedDeviceInfo.TestDevice', index=7, + number=8, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5590, + serialized_end=5884, +) + + +_PROVISIONINGOPTIONS = _descriptor.Descriptor( + name='ProvisioningOptions', + full_name='ProvisioningOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5886, + serialized_end=5907, +) + + +_PROVISIONINGREQUEST = _descriptor.Descriptor( + name='ProvisioningRequest', + full_name='ProvisioningRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5909, + serialized_end=5930, +) + + +_PROVISIONINGRESPONSE = _descriptor.Descriptor( + name='ProvisioningResponse', + full_name='ProvisioningResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5932, + serialized_end=5954, +) + + +_REMOTEATTESTATION = _descriptor.Descriptor( + name='RemoteAttestation', + full_name='RemoteAttestation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Certificate', full_name='RemoteAttestation.Certificate', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Salt', full_name='RemoteAttestation.Salt', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='RemoteAttestation.Signature', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5956, + serialized_end=6061, +) + + +_SESSIONINIT = _descriptor.Descriptor( + name='SessionInit', + full_name='SessionInit', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6063, + serialized_end=6076, +) + + +_SESSIONSTATE = _descriptor.Descriptor( + name='SessionState', + full_name='SessionState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6078, + serialized_end=6092, +) + + +_SIGNEDCERTIFICATESTATUSLIST = _descriptor.Descriptor( + name='SignedCertificateStatusList', + full_name='SignedCertificateStatusList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6094, + serialized_end=6123, +) + + +_SIGNEDDEVICECERTIFICATE = _descriptor.Descriptor( + name='SignedDeviceCertificate', + full_name='SignedDeviceCertificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='_DeviceCertificate', full_name='SignedDeviceCertificate._DeviceCertificate', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedDeviceCertificate.Signature', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signer', full_name='SignedDeviceCertificate.Signer', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6126, + serialized_end=6260, +) + + +_SIGNEDPROVISIONINGMESSAGE = _descriptor.Descriptor( + name='SignedProvisioningMessage', + full_name='SignedProvisioningMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6262, + serialized_end=6289, +) + + +_SIGNEDMESSAGE = _descriptor.Descriptor( + name='SignedMessage', + full_name='SignedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedMessage.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedMessage.Msg', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedMessage.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedMessage.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedMessage.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDMESSAGE_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6292, + serialized_end=6575, +) + + +_WIDEVINECENCHEADER = _descriptor.Descriptor( + name='WidevineCencHeader', + full_name='WidevineCencHeader', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='algorithm', full_name='WidevineCencHeader.algorithm', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='key_id', full_name='WidevineCencHeader.key_id', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='provider', full_name='WidevineCencHeader.provider', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='content_id', full_name='WidevineCencHeader.content_id', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='track_type_deprecated', full_name='WidevineCencHeader.track_type_deprecated', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='policy', full_name='WidevineCencHeader.policy', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='crypto_period_index', full_name='WidevineCencHeader.crypto_period_index', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='grouped_license', full_name='WidevineCencHeader.grouped_license', index=7, + number=8, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='protection_scheme', full_name='WidevineCencHeader.protection_scheme', index=8, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='crypto_period_seconds', full_name='WidevineCencHeader.crypto_period_seconds', index=9, + number=10, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _WIDEVINECENCHEADER_ALGORITHM, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6578, + serialized_end=6903, +) + + +_SIGNEDLICENSEREQUEST = _descriptor.Descriptor( + name='SignedLicenseRequest', + full_name='SignedLicenseRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedLicenseRequest.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedLicenseRequest.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedLicenseRequest.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedLicenseRequest.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedLicenseRequest.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDLICENSEREQUEST_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6906, + serialized_end=7220, +) + + +_SIGNEDLICENSEREQUESTRAW = _descriptor.Descriptor( + name='SignedLicenseRequestRaw', + full_name='SignedLicenseRequestRaw', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedLicenseRequestRaw.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedLicenseRequestRaw.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedLicenseRequestRaw.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedLicenseRequestRaw.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedLicenseRequestRaw.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDLICENSEREQUESTRAW_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7223, + serialized_end=7546, +) + + +_SIGNEDLICENSE = _descriptor.Descriptor( + name='SignedLicense', + full_name='SignedLicense', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedLicense.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedLicense.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedLicense.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedLicense.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedLicense.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDLICENSE_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7549, + serialized_end=7842, +) + + +_SIGNEDSERVICECERTIFICATE = _descriptor.Descriptor( + name='SignedServiceCertificate', + full_name='SignedServiceCertificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedServiceCertificate.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedServiceCertificate.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedServiceCertificate.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedServiceCertificate.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedServiceCertificate.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDSERVICECERTIFICATE_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7845, + serialized_end=8176, +) + + +_FILEHASHES_SIGNATURE = _descriptor.Descriptor( + name='Signature', + full_name='FileHashes.Signature', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='filename', full_name='FileHashes.Signature.filename', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='test_signing', full_name='FileHashes.Signature.test_signing', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SHA512Hash', full_name='FileHashes.Signature.SHA512Hash', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='main_exe', full_name='FileHashes.Signature.main_exe', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='signature', full_name='FileHashes.Signature.signature', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8252, + serialized_end=8360, +) + +_FILEHASHES = _descriptor.Descriptor( + name='FileHashes', + full_name='FileHashes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='signer', full_name='FileHashes.signer', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='signatures', full_name='FileHashes.signatures', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_FILEHASHES_SIGNATURE, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8179, + serialized_end=8360, +) + +_CLIENTIDENTIFICATION_NAMEVALUE.containing_type = _CLIENTIDENTIFICATION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.fields_by_name['MaxHdcpVersion'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.containing_type = _CLIENTIDENTIFICATION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION.containing_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES +_CLIENTIDENTIFICATION.fields_by_name['Type'].enum_type = _CLIENTIDENTIFICATION_TOKENTYPE +_CLIENTIDENTIFICATION.fields_by_name['Token'].message_type = _SIGNEDDEVICECERTIFICATE +_CLIENTIDENTIFICATION.fields_by_name['ClientInfo'].message_type = _CLIENTIDENTIFICATION_NAMEVALUE +_CLIENTIDENTIFICATION.fields_by_name['_ClientCapabilities'].message_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES +_CLIENTIDENTIFICATION.fields_by_name['_FileHashes'].message_type = _FILEHASHES +_CLIENTIDENTIFICATION_TOKENTYPE.containing_type = _CLIENTIDENTIFICATION +_DEVICECERTIFICATE.fields_by_name['Type'].enum_type = _DEVICECERTIFICATE_CERTIFICATETYPE +_DEVICECERTIFICATE_CERTIFICATETYPE.containing_type = _DEVICECERTIFICATE +_DEVICECERTIFICATESTATUS.fields_by_name['Status'].enum_type = _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS +_DEVICECERTIFICATESTATUS.fields_by_name['DeviceInfo'].message_type = _PROVISIONEDDEVICEINFO +_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS.containing_type = _DEVICECERTIFICATESTATUS +_DEVICECERTIFICATESTATUSLIST.fields_by_name['CertificateStatus'].message_type = _DEVICECERTIFICATESTATUS +_LICENSEIDENTIFICATION.fields_by_name['Type'].enum_type = _LICENSETYPE +_LICENSE_POLICY.containing_type = _LICENSE +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['Hdcp'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['CgmsFlags'].enum_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS.containing_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER_KEYCONTROL.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER.fields_by_name['Type'].enum_type = _LICENSE_KEYCONTAINER_KEYTYPE +_LICENSE_KEYCONTAINER.fields_by_name['Level'].enum_type = _LICENSE_KEYCONTAINER_SECURITYLEVEL +_LICENSE_KEYCONTAINER.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER.fields_by_name['RequestedProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER.fields_by_name['_KeyControl'].message_type = _LICENSE_KEYCONTAINER_KEYCONTROL +_LICENSE_KEYCONTAINER.fields_by_name['_OperatorSessionKeyPermissions'].message_type = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS +_LICENSE_KEYCONTAINER.fields_by_name['VideoResolutionConstraints'].message_type = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT +_LICENSE_KEYCONTAINER.containing_type = _LICENSE +_LICENSE_KEYCONTAINER_KEYTYPE.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_SECURITYLEVEL.containing_type = _LICENSE_KEYCONTAINER +_LICENSE.fields_by_name['Id'].message_type = _LICENSEIDENTIFICATION +_LICENSE.fields_by_name['_Policy'].message_type = _LICENSE_POLICY +_LICENSE.fields_by_name['Key'].message_type = _LICENSE_KEYCONTAINER +_LICENSEERROR.fields_by_name['ErrorCode'].enum_type = _LICENSEERROR_ERROR +_LICENSEERROR_ERROR.containing_type = _LICENSEERROR +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['Pssh'].message_type = _WIDEVINECENCHEADER +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE +_LICENSEREQUEST_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUEST +_LICENSEREQUEST.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION +_LICENSEREQUEST.fields_by_name['ContentId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST.fields_by_name['Type'].enum_type = _LICENSEREQUEST_REQUESTTYPE +_LICENSEREQUEST.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION +_LICENSEREQUEST.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION +_LICENSEREQUEST_REQUESTTYPE.containing_type = _LICENSEREQUEST +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE +_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUESTRAW +_LICENSEREQUESTRAW.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION +_LICENSEREQUESTRAW.fields_by_name['ContentId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION +_LICENSEREQUESTRAW.fields_by_name['Type'].enum_type = _LICENSEREQUESTRAW_REQUESTTYPE +_LICENSEREQUESTRAW.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION +_LICENSEREQUESTRAW.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION +_LICENSEREQUESTRAW_REQUESTTYPE.containing_type = _LICENSEREQUESTRAW +_PROVISIONEDDEVICEINFO.fields_by_name['SecurityLevel'].enum_type = _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL +_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL.containing_type = _PROVISIONEDDEVICEINFO +_REMOTEATTESTATION.fields_by_name['Certificate'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION +_SIGNEDDEVICECERTIFICATE.fields_by_name['_DeviceCertificate'].message_type = _DEVICECERTIFICATE +_SIGNEDDEVICECERTIFICATE.fields_by_name['Signer'].message_type = _SIGNEDDEVICECERTIFICATE +_SIGNEDMESSAGE.fields_by_name['Type'].enum_type = _SIGNEDMESSAGE_MESSAGETYPE +_SIGNEDMESSAGE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDMESSAGE_MESSAGETYPE.containing_type = _SIGNEDMESSAGE +_WIDEVINECENCHEADER.fields_by_name['algorithm'].enum_type = _WIDEVINECENCHEADER_ALGORITHM +_WIDEVINECENCHEADER_ALGORITHM.containing_type = _WIDEVINECENCHEADER +_SIGNEDLICENSEREQUEST.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUEST_MESSAGETYPE +_SIGNEDLICENSEREQUEST.fields_by_name['Msg'].message_type = _LICENSEREQUEST +_SIGNEDLICENSEREQUEST.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDLICENSEREQUEST_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUEST +_SIGNEDLICENSEREQUESTRAW.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUESTRAW_MESSAGETYPE +_SIGNEDLICENSEREQUESTRAW.fields_by_name['Msg'].message_type = _LICENSEREQUESTRAW +_SIGNEDLICENSEREQUESTRAW.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUESTRAW +_SIGNEDLICENSE.fields_by_name['Type'].enum_type = _SIGNEDLICENSE_MESSAGETYPE +_SIGNEDLICENSE.fields_by_name['Msg'].message_type = _LICENSE +_SIGNEDLICENSE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDLICENSE_MESSAGETYPE.containing_type = _SIGNEDLICENSE +_SIGNEDSERVICECERTIFICATE.fields_by_name['Type'].enum_type = _SIGNEDSERVICECERTIFICATE_MESSAGETYPE +_SIGNEDSERVICECERTIFICATE.fields_by_name['Msg'].message_type = _SIGNEDDEVICECERTIFICATE +_SIGNEDSERVICECERTIFICATE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDSERVICECERTIFICATE_MESSAGETYPE.containing_type = _SIGNEDSERVICECERTIFICATE +_FILEHASHES_SIGNATURE.containing_type = _FILEHASHES +_FILEHASHES.fields_by_name['signatures'].message_type = _FILEHASHES_SIGNATURE +DESCRIPTOR.message_types_by_name['ClientIdentification'] = _CLIENTIDENTIFICATION +DESCRIPTOR.message_types_by_name['DeviceCertificate'] = _DEVICECERTIFICATE +DESCRIPTOR.message_types_by_name['DeviceCertificateStatus'] = _DEVICECERTIFICATESTATUS +DESCRIPTOR.message_types_by_name['DeviceCertificateStatusList'] = _DEVICECERTIFICATESTATUSLIST +DESCRIPTOR.message_types_by_name['EncryptedClientIdentification'] = _ENCRYPTEDCLIENTIDENTIFICATION +DESCRIPTOR.message_types_by_name['LicenseIdentification'] = _LICENSEIDENTIFICATION +DESCRIPTOR.message_types_by_name['License'] = _LICENSE +DESCRIPTOR.message_types_by_name['LicenseError'] = _LICENSEERROR +DESCRIPTOR.message_types_by_name['LicenseRequest'] = _LICENSEREQUEST +DESCRIPTOR.message_types_by_name['LicenseRequestRaw'] = _LICENSEREQUESTRAW +DESCRIPTOR.message_types_by_name['ProvisionedDeviceInfo'] = _PROVISIONEDDEVICEINFO +DESCRIPTOR.message_types_by_name['ProvisioningOptions'] = _PROVISIONINGOPTIONS +DESCRIPTOR.message_types_by_name['ProvisioningRequest'] = _PROVISIONINGREQUEST +DESCRIPTOR.message_types_by_name['ProvisioningResponse'] = _PROVISIONINGRESPONSE +DESCRIPTOR.message_types_by_name['RemoteAttestation'] = _REMOTEATTESTATION +DESCRIPTOR.message_types_by_name['SessionInit'] = _SESSIONINIT +DESCRIPTOR.message_types_by_name['SessionState'] = _SESSIONSTATE +DESCRIPTOR.message_types_by_name['SignedCertificateStatusList'] = _SIGNEDCERTIFICATESTATUSLIST +DESCRIPTOR.message_types_by_name['SignedDeviceCertificate'] = _SIGNEDDEVICECERTIFICATE +DESCRIPTOR.message_types_by_name['SignedProvisioningMessage'] = _SIGNEDPROVISIONINGMESSAGE +DESCRIPTOR.message_types_by_name['SignedMessage'] = _SIGNEDMESSAGE +DESCRIPTOR.message_types_by_name['WidevineCencHeader'] = _WIDEVINECENCHEADER +DESCRIPTOR.message_types_by_name['SignedLicenseRequest'] = _SIGNEDLICENSEREQUEST +DESCRIPTOR.message_types_by_name['SignedLicenseRequestRaw'] = _SIGNEDLICENSEREQUESTRAW +DESCRIPTOR.message_types_by_name['SignedLicense'] = _SIGNEDLICENSE +DESCRIPTOR.message_types_by_name['SignedServiceCertificate'] = _SIGNEDSERVICECERTIFICATE +DESCRIPTOR.message_types_by_name['FileHashes'] = _FILEHASHES +DESCRIPTOR.enum_types_by_name['LicenseType'] = _LICENSETYPE +DESCRIPTOR.enum_types_by_name['ProtocolVersion'] = _PROTOCOLVERSION + +ClientIdentification = _reflection.GeneratedProtocolMessageType('ClientIdentification', (_message.Message,), dict( + + NameValue = _reflection.GeneratedProtocolMessageType('NameValue', (_message.Message,), dict( + DESCRIPTOR = _CLIENTIDENTIFICATION_NAMEVALUE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification.NameValue) + )) + , + + ClientCapabilities = _reflection.GeneratedProtocolMessageType('ClientCapabilities', (_message.Message,), dict( + DESCRIPTOR = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification.ClientCapabilities) + )) + , + DESCRIPTOR = _CLIENTIDENTIFICATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification) + )) +_sym_db.RegisterMessage(ClientIdentification) +_sym_db.RegisterMessage(ClientIdentification.NameValue) +_sym_db.RegisterMessage(ClientIdentification.ClientCapabilities) + +DeviceCertificate = _reflection.GeneratedProtocolMessageType('DeviceCertificate', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificate) + )) +_sym_db.RegisterMessage(DeviceCertificate) + +DeviceCertificateStatus = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatus', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATESTATUS, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificateStatus) + )) +_sym_db.RegisterMessage(DeviceCertificateStatus) + +DeviceCertificateStatusList = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatusList', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATESTATUSLIST, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificateStatusList) + )) +_sym_db.RegisterMessage(DeviceCertificateStatusList) + +EncryptedClientIdentification = _reflection.GeneratedProtocolMessageType('EncryptedClientIdentification', (_message.Message,), dict( + DESCRIPTOR = _ENCRYPTEDCLIENTIDENTIFICATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:EncryptedClientIdentification) + )) +_sym_db.RegisterMessage(EncryptedClientIdentification) + +LicenseIdentification = _reflection.GeneratedProtocolMessageType('LicenseIdentification', (_message.Message,), dict( + DESCRIPTOR = _LICENSEIDENTIFICATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseIdentification) + )) +_sym_db.RegisterMessage(LicenseIdentification) + +License = _reflection.GeneratedProtocolMessageType('License', (_message.Message,), dict( + + Policy = _reflection.GeneratedProtocolMessageType('Policy', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_POLICY, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.Policy) + )) + , + + KeyContainer = _reflection.GeneratedProtocolMessageType('KeyContainer', (_message.Message,), dict( + + OutputProtection = _reflection.GeneratedProtocolMessageType('OutputProtection', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.OutputProtection) + )) + , + + KeyControl = _reflection.GeneratedProtocolMessageType('KeyControl', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_KEYCONTROL, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.KeyControl) + )) + , + + OperatorSessionKeyPermissions = _reflection.GeneratedProtocolMessageType('OperatorSessionKeyPermissions', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.OperatorSessionKeyPermissions) + )) + , + + VideoResolutionConstraint = _reflection.GeneratedProtocolMessageType('VideoResolutionConstraint', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.VideoResolutionConstraint) + )) + , + DESCRIPTOR = _LICENSE_KEYCONTAINER, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer) + )) + , + DESCRIPTOR = _LICENSE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:License) + )) +_sym_db.RegisterMessage(License) +_sym_db.RegisterMessage(License.Policy) +_sym_db.RegisterMessage(License.KeyContainer) +_sym_db.RegisterMessage(License.KeyContainer.OutputProtection) +_sym_db.RegisterMessage(License.KeyContainer.KeyControl) +_sym_db.RegisterMessage(License.KeyContainer.OperatorSessionKeyPermissions) +_sym_db.RegisterMessage(License.KeyContainer.VideoResolutionConstraint) + +LicenseError = _reflection.GeneratedProtocolMessageType('LicenseError', (_message.Message,), dict( + DESCRIPTOR = _LICENSEERROR, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseError) + )) +_sym_db.RegisterMessage(LicenseError) + +LicenseRequest = _reflection.GeneratedProtocolMessageType('LicenseRequest', (_message.Message,), dict( + + ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict( + + CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.CENC) + )) + , + + WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.WebM) + )) + , + + ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.ExistingLicense) + )) + , + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification) + )) + , + DESCRIPTOR = _LICENSEREQUEST, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest) + )) +_sym_db.RegisterMessage(LicenseRequest) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.CENC) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.WebM) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.ExistingLicense) + +LicenseRequestRaw = _reflection.GeneratedProtocolMessageType('LicenseRequestRaw', (_message.Message,), dict( + + ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict( + + CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.CENC) + )) + , + + WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.WebM) + )) + , + + ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.ExistingLicense) + )) + , + DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification) + )) + , + DESCRIPTOR = _LICENSEREQUESTRAW, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequestRaw) + )) +_sym_db.RegisterMessage(LicenseRequestRaw) +_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification) +_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.CENC) +_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.WebM) +_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.ExistingLicense) + +ProvisionedDeviceInfo = _reflection.GeneratedProtocolMessageType('ProvisionedDeviceInfo', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONEDDEVICEINFO, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ProvisionedDeviceInfo) + )) +_sym_db.RegisterMessage(ProvisionedDeviceInfo) + +ProvisioningOptions = _reflection.GeneratedProtocolMessageType('ProvisioningOptions', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGOPTIONS, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningOptions) + )) +_sym_db.RegisterMessage(ProvisioningOptions) + +ProvisioningRequest = _reflection.GeneratedProtocolMessageType('ProvisioningRequest', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGREQUEST, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningRequest) + )) +_sym_db.RegisterMessage(ProvisioningRequest) + +ProvisioningResponse = _reflection.GeneratedProtocolMessageType('ProvisioningResponse', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGRESPONSE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningResponse) + )) +_sym_db.RegisterMessage(ProvisioningResponse) + +RemoteAttestation = _reflection.GeneratedProtocolMessageType('RemoteAttestation', (_message.Message,), dict( + DESCRIPTOR = _REMOTEATTESTATION, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:RemoteAttestation) + )) +_sym_db.RegisterMessage(RemoteAttestation) + +SessionInit = _reflection.GeneratedProtocolMessageType('SessionInit', (_message.Message,), dict( + DESCRIPTOR = _SESSIONINIT, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SessionInit) + )) +_sym_db.RegisterMessage(SessionInit) + +SessionState = _reflection.GeneratedProtocolMessageType('SessionState', (_message.Message,), dict( + DESCRIPTOR = _SESSIONSTATE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SessionState) + )) +_sym_db.RegisterMessage(SessionState) + +SignedCertificateStatusList = _reflection.GeneratedProtocolMessageType('SignedCertificateStatusList', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDCERTIFICATESTATUSLIST, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedCertificateStatusList) + )) +_sym_db.RegisterMessage(SignedCertificateStatusList) + +SignedDeviceCertificate = _reflection.GeneratedProtocolMessageType('SignedDeviceCertificate', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDDEVICECERTIFICATE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedDeviceCertificate) + )) +_sym_db.RegisterMessage(SignedDeviceCertificate) + +SignedProvisioningMessage = _reflection.GeneratedProtocolMessageType('SignedProvisioningMessage', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDPROVISIONINGMESSAGE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedProvisioningMessage) + )) +_sym_db.RegisterMessage(SignedProvisioningMessage) + +SignedMessage = _reflection.GeneratedProtocolMessageType('SignedMessage', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDMESSAGE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedMessage) + )) +_sym_db.RegisterMessage(SignedMessage) + +WidevineCencHeader = _reflection.GeneratedProtocolMessageType('WidevineCencHeader', (_message.Message,), dict( + DESCRIPTOR = _WIDEVINECENCHEADER, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:WidevineCencHeader) + )) +_sym_db.RegisterMessage(WidevineCencHeader) + +SignedLicenseRequest = _reflection.GeneratedProtocolMessageType('SignedLicenseRequest', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDLICENSEREQUEST, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedLicenseRequest) + )) +_sym_db.RegisterMessage(SignedLicenseRequest) + +SignedLicenseRequestRaw = _reflection.GeneratedProtocolMessageType('SignedLicenseRequestRaw', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDLICENSEREQUESTRAW, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedLicenseRequestRaw) + )) +_sym_db.RegisterMessage(SignedLicenseRequestRaw) + +SignedLicense = _reflection.GeneratedProtocolMessageType('SignedLicense', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDLICENSE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedLicense) + )) +_sym_db.RegisterMessage(SignedLicense) + +SignedServiceCertificate = _reflection.GeneratedProtocolMessageType('SignedServiceCertificate', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDSERVICECERTIFICATE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:SignedServiceCertificate) + )) +_sym_db.RegisterMessage(SignedServiceCertificate) + +FileHashes = _reflection.GeneratedProtocolMessageType('FileHashes', (_message.Message,), dict( + + Signature = _reflection.GeneratedProtocolMessageType('Signature', (_message.Message,), dict( + DESCRIPTOR = _FILEHASHES_SIGNATURE, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:FileHashes.Signature) + )) + , + DESCRIPTOR = _FILEHASHES, + __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2' + # @@protoc_insertion_point(class_scope:FileHashes) + )) +_sym_db.RegisterMessage(FileHashes) +_sym_db.RegisterMessage(FileHashes.Signature) + + +# @@protoc_insertion_point(module_scope) diff --git a/pywidevine/cdm/formats/wv_proto3.proto b/pywidevine/cdm/formats/wv_proto3.proto new file mode 100644 index 0000000..7861b02 --- /dev/null +++ b/pywidevine/cdm/formats/wv_proto3.proto @@ -0,0 +1,389 @@ +// beware proto3 won't show missing fields it seems, need to change to "proto2" and add "optional" before every field, and remove all the dummy enum members I added: +syntax = "proto3"; + +// from x86 (partial), most of it from the ARM version: +message ClientIdentification { + enum TokenType { + KEYBOX = 0; + DEVICE_CERTIFICATE = 1; + REMOTE_ATTESTATION_CERTIFICATE = 2; + } + message NameValue { + string Name = 1; + string Value = 2; + } + message ClientCapabilities { + enum HdcpVersion { + HDCP_NONE = 0; + HDCP_V1 = 1; + HDCP_V2 = 2; + HDCP_V2_1 = 3; + HDCP_V2_2 = 4; + } + uint32 ClientToken = 1; + uint32 SessionToken = 2; + uint32 VideoResolutionConstraints = 3; + HdcpVersion MaxHdcpVersion = 4; + uint32 OemCryptoApiVersion = 5; + } + TokenType Type = 1; + //bytes Token = 2; // by default the client treats this as blob, but it's usually a DeviceCertificate, so for usefulness sake, I'm replacing it with this one: + SignedDeviceCertificate Token = 2; + repeated NameValue ClientInfo = 3; + bytes ProviderClientToken = 4; + uint32 LicenseCounter = 5; + ClientCapabilities _ClientCapabilities = 6; // how should we deal with duped names? will have to look at proto docs later +} + +message DeviceCertificate { + enum CertificateType { + ROOT = 0; + INTERMEDIATE = 1; + USER_DEVICE = 2; + SERVICE = 3; + } + //ProvisionedDeviceInfo.WvSecurityLevel Type = 1; // is this how one is supposed to call it? (it's an enum) there might be a bug here, with CertificateType getting confused with WvSecurityLevel, for now renaming it (verify against other binaries) + CertificateType Type = 1; + bytes SerialNumber = 2; + uint32 CreationTimeSeconds = 3; + bytes PublicKey = 4; + uint32 SystemId = 5; + uint32 TestDeviceDeprecated = 6; // is it bool or int? + bytes ServiceId = 7; // service URL for service certificates +} + +// missing some references, +message DeviceCertificateStatus { + enum CertificateStatus { + VALID = 0; + REVOKED = 1; + } + bytes SerialNumber = 1; + CertificateStatus Status = 2; + ProvisionedDeviceInfo DeviceInfo = 4; // where is 3? is it deprecated? +} + +message DeviceCertificateStatusList { + uint32 CreationTimeSeconds = 1; + repeated DeviceCertificateStatus CertificateStatus = 2; +} + +message EncryptedClientIdentification { + string ServiceId = 1; + bytes ServiceCertificateSerialNumber = 2; + bytes EncryptedClientId = 3; + bytes EncryptedClientIdIv = 4; + bytes EncryptedPrivacyKey = 5; +} + +// todo: fill (for this top-level type, it might be impossible/difficult) +enum LicenseType { + ZERO = 0; + DEFAULT = 1; // do not know what this is either, but should be 1; on recent versions may go up to 3 (latest x86) +} + +// todo: fill (for this top-level type, it might be impossible/difficult) +// this is just a guess because these globals got lost, but really, do we need more? +enum ProtocolVersion { + DUMMY = 0; + CURRENT = 21; // don't have symbols for this +} + + +message LicenseIdentification { + bytes RequestId = 1; + bytes SessionId = 2; + bytes PurchaseId = 3; + LicenseType Type = 4; + uint32 Version = 5; + bytes ProviderSessionToken = 6; +} + + +message License { + message Policy { + uint32 CanPlay = 1; + uint32 CanPersist = 2; + uint32 CanRenew = 3; + uint32 RentalDurationSeconds = 4; + uint32 PlaybackDurationSeconds = 5; + uint32 LicenseDurationSeconds = 6; + uint32 RenewalRecoveryDurationSeconds = 7; + string RenewalServerUrl = 8; + uint32 RenewalDelaySeconds = 9; + uint32 RenewalRetryIntervalSeconds = 10; + uint32 RenewWithUsage = 11; + uint32 UnknownPolicy12 = 12; + } + message KeyContainer { + enum KeyType { + _NOKEYTYPE = 0; // dummy, added to satisfy proto3, not present in original + SIGNING = 1; + CONTENT = 2; + KEY_CONTROL = 3; + OPERATOR_SESSION = 4; + } + enum SecurityLevel { + _NOSECLEVEL = 0; // dummy, added to satisfy proto3, not present in original + SW_SECURE_CRYPTO = 1; + SW_SECURE_DECODE = 2; + HW_SECURE_CRYPTO = 3; + HW_SECURE_DECODE = 4; + HW_SECURE_ALL = 5; + } + message OutputProtection { + enum CGMS { + COPY_FREE = 0; + COPY_ONCE = 2; + COPY_NEVER = 3; + CGMS_NONE = 0x2A; // PC default! + } + ClientIdentification.ClientCapabilities.HdcpVersion Hdcp = 1; // it's most likely a copy of Hdcp version available here, but compiler optimized it away + CGMS CgmsFlags = 2; + } + message KeyControl { + bytes KeyControlBlock = 1; // what is this? + bytes Iv = 2; + } + message OperatorSessionKeyPermissions { + uint32 AllowEncrypt = 1; + uint32 AllowDecrypt = 2; + uint32 AllowSign = 3; + uint32 AllowSignatureVerify = 4; + } + message VideoResolutionConstraint { + uint32 MinResolutionPixels = 1; + uint32 MaxResolutionPixels = 2; + OutputProtection RequiredProtection = 3; + } + bytes Id = 1; + bytes Iv = 2; + bytes Key = 3; + KeyType Type = 4; + SecurityLevel Level = 5; + OutputProtection RequiredProtection = 6; + OutputProtection RequestedProtection = 7; + KeyControl _KeyControl = 8; // duped names, etc + OperatorSessionKeyPermissions _OperatorSessionKeyPermissions = 9; // duped names, etc + repeated VideoResolutionConstraint VideoResolutionConstraints = 10; + } + LicenseIdentification Id = 1; + Policy _Policy = 2; // duped names, etc + repeated KeyContainer Key = 3; + uint32 LicenseStartTime = 4; + uint32 RemoteAttestationVerified = 5; // bool? + bytes ProviderClientToken = 6; + // there might be more, check with newer versions (I see field 7-8 in a lic) + // this appeared in latest x86: + uint32 ProtectionScheme = 7; // type unconfirmed fully, but it's likely as WidevineCencHeader describesit (fourcc) + bytes UnknownHdcpDataField = 8; +} + +message LicenseError { + enum Error { + DUMMY_NO_ERROR = 0; // dummy, added to satisfy proto3 + INVALID_DEVICE_CERTIFICATE = 1; + REVOKED_DEVICE_CERTIFICATE = 2; + SERVICE_UNAVAILABLE = 3; + } + //LicenseRequest.RequestType ErrorCode; // clang mismatch + Error ErrorCode = 1; +} + +message LicenseRequest { + message ContentIdentification { + message CENC { + // bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with: + WidevineCencHeader Pssh = 1; + LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1 + bytes RequestId = 3; + } + message WebM { + bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used + LicenseType LicenseType = 2; + bytes RequestId = 3; + } + message ExistingLicense { + LicenseIdentification LicenseId = 1; + uint32 SecondsSinceStarted = 2; + uint32 SecondsSinceLastPlayed = 3; + bytes SessionUsageTableEntry = 4; + } + CENC CencId = 1; + WebM WebmId = 2; + ExistingLicense License = 3; + } + enum RequestType { + DUMMY_REQ_TYPE = 0; // dummy, added to satisfy proto3 + NEW = 1; + RENEWAL = 2; + RELEASE = 3; + } + ClientIdentification ClientId = 1; + ContentIdentification ContentId = 2; + RequestType Type = 3; + uint32 RequestTime = 4; + bytes KeyControlNonceDeprecated = 5; + ProtocolVersion ProtocolVersion = 6; // lacking symbols for this + uint32 KeyControlNonce = 7; + EncryptedClientIdentification EncryptedClientId = 8; +} + +message ProvisionedDeviceInfo { + enum WvSecurityLevel { + LEVEL_UNSPECIFIED = 0; + LEVEL_1 = 1; + LEVEL_2 = 2; + LEVEL_3 = 3; + } + uint32 SystemId = 1; + string Soc = 2; + string Manufacturer = 3; + string Model = 4; + string DeviceType = 5; + uint32 ModelYear = 6; + WvSecurityLevel SecurityLevel = 7; + uint32 TestDevice = 8; // bool? +} + + +// todo: fill +message ProvisioningOptions { +} + +// todo: fill +message ProvisioningRequest { +} + +// todo: fill +message ProvisioningResponse { +} + +message RemoteAttestation { + EncryptedClientIdentification Certificate = 1; + string Salt = 2; + string Signature = 3; +} + +// todo: fill +message SessionInit { +} + +// todo: fill +message SessionState { +} + +// todo: fill +message SignedCertificateStatusList { +} + +message SignedDeviceCertificate { + + //bytes DeviceCertificate = 1; // again, they use a buffer where it's supposed to be a message, so we'll replace it with what it really is: + DeviceCertificate _DeviceCertificate = 1; // how should we deal with duped names? will have to look at proto docs later + bytes Signature = 2; + SignedDeviceCertificate Signer = 3; +} + + +// todo: fill +message SignedProvisioningMessage { +} + +// the root of all messages, from either server or client +message SignedMessage { + enum MessageType { + DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3 + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + bytes Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + bytes SessionKey = 4; // often RSA wrapped for licenses + RemoteAttestation RemoteAttestation = 5; +} + + + +// This message is copied from google's docs, not reversed: +message WidevineCencHeader { + enum Algorithm { + UNENCRYPTED = 0; + AESCTR = 1; + }; + Algorithm algorithm = 1; + repeated bytes key_id = 2; + + // Content provider name. + string provider = 3; + + // A content identifier, specified by content provider. + bytes content_id = 4; + + // Track type. Acceptable values are SD, HD and AUDIO. Used to + // differentiate content keys used by an asset. + string track_type_deprecated = 5; + + // The name of a registered policy to be used for this asset. + string policy = 6; + + // Crypto period index, for media using key rotation. + uint32 crypto_period_index = 7; + + // Optional protected context for group content. The grouped_license is a + // serialized SignedMessage. + bytes grouped_license = 8; + + // Protection scheme identifying the encryption algorithm. + // Represented as one of the following 4CC values: + // 'cenc' (AESCTR), 'cbc1' (AESCBC), + // 'cens' (AESCTR subsample), 'cbcs' (AESCBC subsample). + uint32 protection_scheme = 9; + + // Optional. For media using key rotation, this represents the duration + // of each crypto period in seconds. + uint32 crypto_period_seconds = 10; +} + + + + +// from here on, it's just for testing, these messages don't exist in the binaries, I'm adding them to avoid detecting type programmatically +message SignedLicenseRequest { + enum MessageType { + DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3 + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + LicenseRequest Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + bytes SessionKey = 4; // often RSA wrapped for licenses + RemoteAttestation RemoteAttestation = 5; +} + +message SignedLicense { + enum MessageType { + DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3 + LICENSE_REQUEST = 1; + LICENSE = 2; + ERROR_RESPONSE = 3; + SERVICE_CERTIFICATE_REQUEST = 4; + SERVICE_CERTIFICATE = 5; + } + MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel + License Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present + // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE + bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now) + bytes SessionKey = 4; // often RSA wrapped for licenses + RemoteAttestation RemoteAttestation = 5; +} \ No newline at end of file diff --git a/pywidevine/cdm/formats/wv_proto3_pb2.py b/pywidevine/cdm/formats/wv_proto3_pb2.py new file mode 100644 index 0000000..11ae09f --- /dev/null +++ b/pywidevine/cdm/formats/wv_proto3_pb2.py @@ -0,0 +1,2686 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: wv_proto3.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='wv_proto3.proto', + package='', + syntax='proto3', + serialized_pb=_b('\n\x0fwv_proto3.proto\"\xc5\x05\n\x14\x43lientIdentification\x12-\n\x04Type\x18\x01 \x01(\x0e\x32\x1f.ClientIdentification.TokenType\x12\'\n\x05Token\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x33\n\nClientInfo\x18\x03 \x03(\x0b\x32\x1f.ClientIdentification.NameValue\x12\x1b\n\x13ProviderClientToken\x18\x04 \x01(\x0c\x12\x16\n\x0eLicenseCounter\x18\x05 \x01(\r\x12\x45\n\x13_ClientCapabilities\x18\x06 \x01(\x0b\x32(.ClientIdentification.ClientCapabilities\x1a(\n\tNameValue\x12\x0c\n\x04Name\x18\x01 \x01(\t\x12\r\n\x05Value\x18\x02 \x01(\t\x1a\xa4\x02\n\x12\x43lientCapabilities\x12\x13\n\x0b\x43lientToken\x18\x01 \x01(\r\x12\x14\n\x0cSessionToken\x18\x02 \x01(\r\x12\"\n\x1aVideoResolutionConstraints\x18\x03 \x01(\r\x12L\n\x0eMaxHdcpVersion\x18\x04 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12\x1b\n\x13OemCryptoApiVersion\x18\x05 \x01(\r\"T\n\x0bHdcpVersion\x12\r\n\tHDCP_NONE\x10\x00\x12\x0b\n\x07HDCP_V1\x10\x01\x12\x0b\n\x07HDCP_V2\x10\x02\x12\r\n\tHDCP_V2_1\x10\x03\x12\r\n\tHDCP_V2_2\x10\x04\"S\n\tTokenType\x12\n\n\x06KEYBOX\x10\x00\x12\x16\n\x12\x44\x45VICE_CERTIFICATE\x10\x01\x12\"\n\x1eREMOTE_ATTESTATION_CERTIFICATE\x10\x02\"\x9b\x02\n\x11\x44\x65viceCertificate\x12\x30\n\x04Type\x18\x01 \x01(\x0e\x32\".DeviceCertificate.CertificateType\x12\x14\n\x0cSerialNumber\x18\x02 \x01(\x0c\x12\x1b\n\x13\x43reationTimeSeconds\x18\x03 \x01(\r\x12\x11\n\tPublicKey\x18\x04 \x01(\x0c\x12\x10\n\x08SystemId\x18\x05 \x01(\r\x12\x1c\n\x14TestDeviceDeprecated\x18\x06 \x01(\r\x12\x11\n\tServiceId\x18\x07 \x01(\x0c\"K\n\x0f\x43\x65rtificateType\x12\x08\n\x04ROOT\x10\x00\x12\x10\n\x0cINTERMEDIATE\x10\x01\x12\x0f\n\x0bUSER_DEVICE\x10\x02\x12\x0b\n\x07SERVICE\x10\x03\"\xc4\x01\n\x17\x44\x65viceCertificateStatus\x12\x14\n\x0cSerialNumber\x18\x01 \x01(\x0c\x12:\n\x06Status\x18\x02 \x01(\x0e\x32*.DeviceCertificateStatus.CertificateStatus\x12*\n\nDeviceInfo\x18\x04 \x01(\x0b\x32\x16.ProvisionedDeviceInfo\"+\n\x11\x43\x65rtificateStatus\x12\t\n\x05VALID\x10\x00\x12\x0b\n\x07REVOKED\x10\x01\"o\n\x1b\x44\x65viceCertificateStatusList\x12\x1b\n\x13\x43reationTimeSeconds\x18\x01 \x01(\r\x12\x33\n\x11\x43\x65rtificateStatus\x18\x02 \x03(\x0b\x32\x18.DeviceCertificateStatus\"\xaf\x01\n\x1d\x45ncryptedClientIdentification\x12\x11\n\tServiceId\x18\x01 \x01(\t\x12&\n\x1eServiceCertificateSerialNumber\x18\x02 \x01(\x0c\x12\x19\n\x11\x45ncryptedClientId\x18\x03 \x01(\x0c\x12\x1b\n\x13\x45ncryptedClientIdIv\x18\x04 \x01(\x0c\x12\x1b\n\x13\x45ncryptedPrivacyKey\x18\x05 \x01(\x0c\"\x9c\x01\n\x15LicenseIdentification\x12\x11\n\tRequestId\x18\x01 \x01(\x0c\x12\x11\n\tSessionId\x18\x02 \x01(\x0c\x12\x12\n\nPurchaseId\x18\x03 \x01(\x0c\x12\x1a\n\x04Type\x18\x04 \x01(\x0e\x32\x0c.LicenseType\x12\x0f\n\x07Version\x18\x05 \x01(\r\x12\x1c\n\x14ProviderSessionToken\x18\x06 \x01(\x0c\"\xfa\x0e\n\x07License\x12\"\n\x02Id\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12 \n\x07_Policy\x18\x02 \x01(\x0b\x32\x0f.License.Policy\x12\"\n\x03Key\x18\x03 \x03(\x0b\x32\x15.License.KeyContainer\x12\x18\n\x10LicenseStartTime\x18\x04 \x01(\r\x12!\n\x19RemoteAttestationVerified\x18\x05 \x01(\r\x12\x1b\n\x13ProviderClientToken\x18\x06 \x01(\x0c\x12\x18\n\x10ProtectionScheme\x18\x07 \x01(\r\x12\x1c\n\x14UnknownHdcpDataField\x18\x08 \x01(\x0c\x1a\xd4\x02\n\x06Policy\x12\x0f\n\x07\x43\x61nPlay\x18\x01 \x01(\r\x12\x12\n\nCanPersist\x18\x02 \x01(\r\x12\x10\n\x08\x43\x61nRenew\x18\x03 \x01(\r\x12\x1d\n\x15RentalDurationSeconds\x18\x04 \x01(\r\x12\x1f\n\x17PlaybackDurationSeconds\x18\x05 \x01(\r\x12\x1e\n\x16LicenseDurationSeconds\x18\x06 \x01(\r\x12&\n\x1eRenewalRecoveryDurationSeconds\x18\x07 \x01(\r\x12\x18\n\x10RenewalServerUrl\x18\x08 \x01(\t\x12\x1b\n\x13RenewalDelaySeconds\x18\t \x01(\r\x12#\n\x1bRenewalRetryIntervalSeconds\x18\n \x01(\r\x12\x16\n\x0eRenewWithUsage\x18\x0b \x01(\r\x12\x17\n\x0fUnknownPolicy12\x18\x0c \x01(\r\x1a\x9b\n\n\x0cKeyContainer\x12\n\n\x02Id\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x12\x0b\n\x03Key\x18\x03 \x01(\x0c\x12+\n\x04Type\x18\x04 \x01(\x0e\x32\x1d.License.KeyContainer.KeyType\x12\x32\n\x05Level\x18\x05 \x01(\x0e\x32#.License.KeyContainer.SecurityLevel\x12\x42\n\x12RequiredProtection\x18\x06 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x43\n\x13RequestedProtection\x18\x07 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x35\n\x0b_KeyControl\x18\x08 \x01(\x0b\x32 .License.KeyContainer.KeyControl\x12[\n\x1e_OperatorSessionKeyPermissions\x18\t \x01(\x0b\x32\x33.License.KeyContainer.OperatorSessionKeyPermissions\x12S\n\x1aVideoResolutionConstraints\x18\n \x03(\x0b\x32/.License.KeyContainer.VideoResolutionConstraint\x1a\xdb\x01\n\x10OutputProtection\x12\x42\n\x04Hdcp\x18\x01 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12>\n\tCgmsFlags\x18\x02 \x01(\x0e\x32+.License.KeyContainer.OutputProtection.CGMS\"C\n\x04\x43GMS\x12\r\n\tCOPY_FREE\x10\x00\x12\r\n\tCOPY_ONCE\x10\x02\x12\x0e\n\nCOPY_NEVER\x10\x03\x12\r\n\tCGMS_NONE\x10*\x1a\x31\n\nKeyControl\x12\x17\n\x0fKeyControlBlock\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x1a|\n\x1dOperatorSessionKeyPermissions\x12\x14\n\x0c\x41llowEncrypt\x18\x01 \x01(\r\x12\x14\n\x0c\x41llowDecrypt\x18\x02 \x01(\r\x12\x11\n\tAllowSign\x18\x03 \x01(\r\x12\x1c\n\x14\x41llowSignatureVerify\x18\x04 \x01(\r\x1a\x99\x01\n\x19VideoResolutionConstraint\x12\x1b\n\x13MinResolutionPixels\x18\x01 \x01(\r\x12\x1b\n\x13MaxResolutionPixels\x18\x02 \x01(\r\x12\x42\n\x12RequiredProtection\x18\x03 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\"Z\n\x07KeyType\x12\x0e\n\n_NOKEYTYPE\x10\x00\x12\x0b\n\x07SIGNING\x10\x01\x12\x0b\n\x07\x43ONTENT\x10\x02\x12\x0f\n\x0bKEY_CONTROL\x10\x03\x12\x14\n\x10OPERATOR_SESSION\x10\x04\"\x8b\x01\n\rSecurityLevel\x12\x0f\n\x0b_NOSECLEVEL\x10\x00\x12\x14\n\x10SW_SECURE_CRYPTO\x10\x01\x12\x14\n\x10SW_SECURE_DECODE\x10\x02\x12\x14\n\x10HW_SECURE_CRYPTO\x10\x03\x12\x14\n\x10HW_SECURE_DECODE\x10\x04\x12\x11\n\rHW_SECURE_ALL\x10\x05\"\xac\x01\n\x0cLicenseError\x12&\n\tErrorCode\x18\x01 \x01(\x0e\x32\x13.LicenseError.Error\"t\n\x05\x45rror\x12\x12\n\x0e\x44UMMY_NO_ERROR\x10\x00\x12\x1e\n\x1aINVALID_DEVICE_CERTIFICATE\x10\x01\x12\x1e\n\x1aREVOKED_DEVICE_CERTIFICATE\x10\x02\x12\x17\n\x13SERVICE_UNAVAILABLE\x10\x03\"\xc0\x07\n\x0eLicenseRequest\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12\x38\n\tContentId\x18\x02 \x01(\x0b\x32%.LicenseRequest.ContentIdentification\x12)\n\x04Type\x18\x03 \x01(\x0e\x32\x1b.LicenseRequest.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\xa2\x04\n\x15\x43ontentIdentification\x12:\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.CENC\x12:\n\x06WebmId\x18\x02 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.WebM\x12\x46\n\x07License\x18\x03 \x01(\x0b\x32\x35.LicenseRequest.ContentIdentification.ExistingLicense\x1a_\n\x04\x43\x45NC\x12!\n\x04Pssh\x18\x01 \x01(\x0b\x32\x13.WidevineCencHeader\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"D\n\x0bRequestType\x12\x12\n\x0e\x44UMMY_REQ_TYPE\x10\x00\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa6\x02\n\x15ProvisionedDeviceInfo\x12\x10\n\x08SystemId\x18\x01 \x01(\r\x12\x0b\n\x03Soc\x18\x02 \x01(\t\x12\x14\n\x0cManufacturer\x18\x03 \x01(\t\x12\r\n\x05Model\x18\x04 \x01(\t\x12\x12\n\nDeviceType\x18\x05 \x01(\t\x12\x11\n\tModelYear\x18\x06 \x01(\r\x12=\n\rSecurityLevel\x18\x07 \x01(\x0e\x32&.ProvisionedDeviceInfo.WvSecurityLevel\x12\x12\n\nTestDevice\x18\x08 \x01(\r\"O\n\x0fWvSecurityLevel\x12\x15\n\x11LEVEL_UNSPECIFIED\x10\x00\x12\x0b\n\x07LEVEL_1\x10\x01\x12\x0b\n\x07LEVEL_2\x10\x02\x12\x0b\n\x07LEVEL_3\x10\x03\"\x15\n\x13ProvisioningOptions\"\x15\n\x13ProvisioningRequest\"\x16\n\x14ProvisioningResponse\"i\n\x11RemoteAttestation\x12\x33\n\x0b\x43\x65rtificate\x18\x01 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x12\x0c\n\x04Salt\x18\x02 \x01(\t\x12\x11\n\tSignature\x18\x03 \x01(\t\"\r\n\x0bSessionInit\"\x0e\n\x0cSessionState\"\x1d\n\x1bSignedCertificateStatusList\"\x86\x01\n\x17SignedDeviceCertificate\x12.\n\x12_DeviceCertificate\x18\x01 \x01(\x0b\x32\x12.DeviceCertificate\x12\x11\n\tSignature\x18\x02 \x01(\x0c\x12(\n\x06Signer\x18\x03 \x01(\x0b\x32\x18.SignedDeviceCertificate\"\x1b\n\x19SignedProvisioningMessage\"\xb0\x02\n\rSignedMessage\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedMessage.MessageType\x12\x0b\n\x03Msg\x18\x02 \x01(\x0c\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc5\x02\n\x12WidevineCencHeader\x12\x30\n\talgorithm\x18\x01 \x01(\x0e\x32\x1d.WidevineCencHeader.Algorithm\x12\x0e\n\x06key_id\x18\x02 \x03(\x0c\x12\x10\n\x08provider\x18\x03 \x01(\t\x12\x12\n\ncontent_id\x18\x04 \x01(\x0c\x12\x1d\n\x15track_type_deprecated\x18\x05 \x01(\t\x12\x0e\n\x06policy\x18\x06 \x01(\t\x12\x1b\n\x13\x63rypto_period_index\x18\x07 \x01(\r\x12\x17\n\x0fgrouped_license\x18\x08 \x01(\x0c\x12\x19\n\x11protection_scheme\x18\t \x01(\r\x12\x1d\n\x15\x63rypto_period_seconds\x18\n \x01(\r\"(\n\tAlgorithm\x12\x0f\n\x0bUNENCRYPTED\x10\x00\x12\n\n\x06\x41\x45SCTR\x10\x01\"\xcf\x02\n\x14SignedLicenseRequest\x12/\n\x04Type\x18\x01 \x01(\x0e\x32!.SignedLicenseRequest.MessageType\x12\x1c\n\x03Msg\x18\x02 \x01(\x0b\x32\x0f.LicenseRequest\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xba\x02\n\rSignedLicense\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedLicense.MessageType\x12\x15\n\x03Msg\x18\x02 \x01(\x0b\x32\x08.License\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05*$\n\x0bLicenseType\x12\x08\n\x04ZERO\x10\x00\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x01*)\n\x0fProtocolVersion\x12\t\n\x05\x44UMMY\x10\x00\x12\x0b\n\x07\x43URRENT\x10\x15\x62\x06proto3') +) + +_LICENSETYPE = _descriptor.EnumDescriptor( + name='LicenseType', + full_name='LicenseType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6713, + serialized_end=6749, +) +_sym_db.RegisterEnumDescriptor(_LICENSETYPE) + +LicenseType = enum_type_wrapper.EnumTypeWrapper(_LICENSETYPE) +_PROTOCOLVERSION = _descriptor.EnumDescriptor( + name='ProtocolVersion', + full_name='ProtocolVersion', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CURRENT', index=1, number=21, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6751, + serialized_end=6792, +) +_sym_db.RegisterEnumDescriptor(_PROTOCOLVERSION) + +ProtocolVersion = enum_type_wrapper.EnumTypeWrapper(_PROTOCOLVERSION) +ZERO = 0 +DEFAULT = 1 +DUMMY = 0 +CURRENT = 21 + + +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION = _descriptor.EnumDescriptor( + name='HdcpVersion', + full_name='ClientIdentification.ClientCapabilities.HdcpVersion', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='HDCP_NONE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V1', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2_1', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HDCP_V2_2', index=4, number=4, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=560, + serialized_end=644, +) +_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION) + +_CLIENTIDENTIFICATION_TOKENTYPE = _descriptor.EnumDescriptor( + name='TokenType', + full_name='ClientIdentification.TokenType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='KEYBOX', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEVICE_CERTIFICATE', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REMOTE_ATTESTATION_CERTIFICATE', index=2, number=2, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=646, + serialized_end=729, +) +_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_TOKENTYPE) + +_DEVICECERTIFICATE_CERTIFICATETYPE = _descriptor.EnumDescriptor( + name='CertificateType', + full_name='DeviceCertificate.CertificateType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ROOT', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='INTERMEDIATE', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='USER_DEVICE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=940, + serialized_end=1015, +) +_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATE_CERTIFICATETYPE) + +_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS = _descriptor.EnumDescriptor( + name='CertificateStatus', + full_name='DeviceCertificateStatus.CertificateStatus', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='VALID', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REVOKED', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=1171, + serialized_end=1214, +) +_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS) + +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS = _descriptor.EnumDescriptor( + name='CGMS', + full_name='License.KeyContainer.OutputProtection.CGMS', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='COPY_FREE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='COPY_ONCE', index=1, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='COPY_NEVER', index=2, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CGMS_NONE', index=3, number=42, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=2947, + serialized_end=3014, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS) + +_LICENSE_KEYCONTAINER_KEYTYPE = _descriptor.EnumDescriptor( + name='KeyType', + full_name='License.KeyContainer.KeyType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='_NOKEYTYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SIGNING', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CONTENT', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='KEY_CONTROL', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='OPERATOR_SESSION', index=4, number=4, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3349, + serialized_end=3439, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_KEYTYPE) + +_LICENSE_KEYCONTAINER_SECURITYLEVEL = _descriptor.EnumDescriptor( + name='SecurityLevel', + full_name='License.KeyContainer.SecurityLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='_NOSECLEVEL', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SW_SECURE_CRYPTO', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SW_SECURE_DECODE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_CRYPTO', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_DECODE', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HW_SECURE_ALL', index=5, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3442, + serialized_end=3581, +) +_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_SECURITYLEVEL) + +_LICENSEERROR_ERROR = _descriptor.EnumDescriptor( + name='Error', + full_name='LicenseError.Error', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY_NO_ERROR', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='INVALID_DEVICE_CERTIFICATE', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='REVOKED_DEVICE_CERTIFICATE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_UNAVAILABLE', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=3640, + serialized_end=3756, +) +_sym_db.RegisterEnumDescriptor(_LICENSEERROR_ERROR) + +_LICENSEREQUEST_REQUESTTYPE = _descriptor.EnumDescriptor( + name='RequestType', + full_name='LicenseRequest.RequestType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY_REQ_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEW', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RENEWAL', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RELEASE', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4651, + serialized_end=4719, +) +_sym_db.RegisterEnumDescriptor(_LICENSEREQUEST_REQUESTTYPE) + +_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL = _descriptor.EnumDescriptor( + name='WvSecurityLevel', + full_name='ProvisionedDeviceInfo.WvSecurityLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LEVEL_UNSPECIFIED', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_1', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_2', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LEVEL_3', index=3, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4937, + serialized_end=5016, +) +_sym_db.RegisterEnumDescriptor(_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL) + +_SIGNEDMESSAGE_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedMessage.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY_MSG_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=5, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=5583, + serialized_end=5728, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDMESSAGE_MESSAGETYPE) + +_WIDEVINECENCHEADER_ALGORITHM = _descriptor.EnumDescriptor( + name='Algorithm', + full_name='WidevineCencHeader.Algorithm', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNENCRYPTED', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='AESCTR', index=1, number=1, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=6016, + serialized_end=6056, +) +_sym_db.RegisterEnumDescriptor(_WIDEVINECENCHEADER_ALGORITHM) + +_SIGNEDLICENSEREQUEST_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedLicenseRequest.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY_MSG_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=5, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=5583, + serialized_end=5728, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUEST_MESSAGETYPE) + +_SIGNEDLICENSE_MESSAGETYPE = _descriptor.EnumDescriptor( + name='MessageType', + full_name='SignedLicense.MessageType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DUMMY_MSG_TYPE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE_REQUEST', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LICENSE', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR_RESPONSE', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SERVICE_CERTIFICATE', index=5, number=5, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=5583, + serialized_end=5728, +) +_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSE_MESSAGETYPE) + + +_CLIENTIDENTIFICATION_NAMEVALUE = _descriptor.Descriptor( + name='NameValue', + full_name='ClientIdentification.NameValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Name', full_name='ClientIdentification.NameValue.Name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Value', full_name='ClientIdentification.NameValue.Value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=309, + serialized_end=349, +) + +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES = _descriptor.Descriptor( + name='ClientCapabilities', + full_name='ClientIdentification.ClientCapabilities', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ClientToken', full_name='ClientIdentification.ClientCapabilities.ClientToken', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionToken', full_name='ClientIdentification.ClientCapabilities.SessionToken', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='VideoResolutionConstraints', full_name='ClientIdentification.ClientCapabilities.VideoResolutionConstraints', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='MaxHdcpVersion', full_name='ClientIdentification.ClientCapabilities.MaxHdcpVersion', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='OemCryptoApiVersion', full_name='ClientIdentification.ClientCapabilities.OemCryptoApiVersion', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=352, + serialized_end=644, +) + +_CLIENTIDENTIFICATION = _descriptor.Descriptor( + name='ClientIdentification', + full_name='ClientIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='ClientIdentification.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Token', full_name='ClientIdentification.Token', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ClientInfo', full_name='ClientIdentification.ClientInfo', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderClientToken', full_name='ClientIdentification.ProviderClientToken', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseCounter', full_name='ClientIdentification.LicenseCounter', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_ClientCapabilities', full_name='ClientIdentification._ClientCapabilities', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_CLIENTIDENTIFICATION_NAMEVALUE, _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, ], + enum_types=[ + _CLIENTIDENTIFICATION_TOKENTYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=20, + serialized_end=729, +) + + +_DEVICECERTIFICATE = _descriptor.Descriptor( + name='DeviceCertificate', + full_name='DeviceCertificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='DeviceCertificate.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SerialNumber', full_name='DeviceCertificate.SerialNumber', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CreationTimeSeconds', full_name='DeviceCertificate.CreationTimeSeconds', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PublicKey', full_name='DeviceCertificate.PublicKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SystemId', full_name='DeviceCertificate.SystemId', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='TestDeviceDeprecated', full_name='DeviceCertificate.TestDeviceDeprecated', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ServiceId', full_name='DeviceCertificate.ServiceId', index=6, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DEVICECERTIFICATE_CERTIFICATETYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=732, + serialized_end=1015, +) + + +_DEVICECERTIFICATESTATUS = _descriptor.Descriptor( + name='DeviceCertificateStatus', + full_name='DeviceCertificateStatus', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='SerialNumber', full_name='DeviceCertificateStatus.SerialNumber', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Status', full_name='DeviceCertificateStatus.Status', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='DeviceInfo', full_name='DeviceCertificateStatus.DeviceInfo', index=2, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1018, + serialized_end=1214, +) + + +_DEVICECERTIFICATESTATUSLIST = _descriptor.Descriptor( + name='DeviceCertificateStatusList', + full_name='DeviceCertificateStatusList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CreationTimeSeconds', full_name='DeviceCertificateStatusList.CreationTimeSeconds', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CertificateStatus', full_name='DeviceCertificateStatusList.CertificateStatus', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1216, + serialized_end=1327, +) + + +_ENCRYPTEDCLIENTIDENTIFICATION = _descriptor.Descriptor( + name='EncryptedClientIdentification', + full_name='EncryptedClientIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ServiceId', full_name='EncryptedClientIdentification.ServiceId', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ServiceCertificateSerialNumber', full_name='EncryptedClientIdentification.ServiceCertificateSerialNumber', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientId', full_name='EncryptedClientIdentification.EncryptedClientId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientIdIv', full_name='EncryptedClientIdentification.EncryptedClientIdIv', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedPrivacyKey', full_name='EncryptedClientIdentification.EncryptedPrivacyKey', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1330, + serialized_end=1505, +) + + +_LICENSEIDENTIFICATION = _descriptor.Descriptor( + name='LicenseIdentification', + full_name='LicenseIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseIdentification.RequestId', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionId', full_name='LicenseIdentification.SessionId', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PurchaseId', full_name='LicenseIdentification.PurchaseId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='LicenseIdentification.Type', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Version', full_name='LicenseIdentification.Version', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderSessionToken', full_name='LicenseIdentification.ProviderSessionToken', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1508, + serialized_end=1664, +) + + +_LICENSE_POLICY = _descriptor.Descriptor( + name='Policy', + full_name='License.Policy', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CanPlay', full_name='License.Policy.CanPlay', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CanPersist', full_name='License.Policy.CanPersist', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CanRenew', full_name='License.Policy.CanRenew', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RentalDurationSeconds', full_name='License.Policy.RentalDurationSeconds', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='PlaybackDurationSeconds', full_name='License.Policy.PlaybackDurationSeconds', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseDurationSeconds', full_name='License.Policy.LicenseDurationSeconds', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalRecoveryDurationSeconds', full_name='License.Policy.RenewalRecoveryDurationSeconds', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalServerUrl', full_name='License.Policy.RenewalServerUrl', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalDelaySeconds', full_name='License.Policy.RenewalDelaySeconds', index=8, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewalRetryIntervalSeconds', full_name='License.Policy.RenewalRetryIntervalSeconds', index=9, + number=10, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RenewWithUsage', full_name='License.Policy.RenewWithUsage', index=10, + number=11, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='UnknownPolicy12', full_name='License.Policy.UnknownPolicy12', index=11, + number=12, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1931, + serialized_end=2271, +) + +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION = _descriptor.Descriptor( + name='OutputProtection', + full_name='License.KeyContainer.OutputProtection', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Hdcp', full_name='License.KeyContainer.OutputProtection.Hdcp', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='CgmsFlags', full_name='License.KeyContainer.OutputProtection.CgmsFlags', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2795, + serialized_end=3014, +) + +_LICENSE_KEYCONTAINER_KEYCONTROL = _descriptor.Descriptor( + name='KeyControl', + full_name='License.KeyContainer.KeyControl', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='KeyControlBlock', full_name='License.KeyContainer.KeyControl.KeyControlBlock', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Iv', full_name='License.KeyContainer.KeyControl.Iv', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3016, + serialized_end=3065, +) + +_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS = _descriptor.Descriptor( + name='OperatorSessionKeyPermissions', + full_name='License.KeyContainer.OperatorSessionKeyPermissions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='AllowEncrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowEncrypt', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowDecrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowDecrypt', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowSign', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSign', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='AllowSignatureVerify', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSignatureVerify', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3067, + serialized_end=3191, +) + +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT = _descriptor.Descriptor( + name='VideoResolutionConstraint', + full_name='License.KeyContainer.VideoResolutionConstraint', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='MinResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MinResolutionPixels', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='MaxResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MaxResolutionPixels', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequiredProtection', full_name='License.KeyContainer.VideoResolutionConstraint.RequiredProtection', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3194, + serialized_end=3347, +) + +_LICENSE_KEYCONTAINER = _descriptor.Descriptor( + name='KeyContainer', + full_name='License.KeyContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Id', full_name='License.KeyContainer.Id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Iv', full_name='License.KeyContainer.Iv', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Key', full_name='License.KeyContainer.Key', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='License.KeyContainer.Type', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Level', full_name='License.KeyContainer.Level', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequiredProtection', full_name='License.KeyContainer.RequiredProtection', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestedProtection', full_name='License.KeyContainer.RequestedProtection', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_KeyControl', full_name='License.KeyContainer._KeyControl', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_OperatorSessionKeyPermissions', full_name='License.KeyContainer._OperatorSessionKeyPermissions', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='VideoResolutionConstraints', full_name='License.KeyContainer.VideoResolutionConstraints', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSE_KEYCONTAINER_OUTPUTPROTECTION, _LICENSE_KEYCONTAINER_KEYCONTROL, _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, ], + enum_types=[ + _LICENSE_KEYCONTAINER_KEYTYPE, + _LICENSE_KEYCONTAINER_SECURITYLEVEL, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2274, + serialized_end=3581, +) + +_LICENSE = _descriptor.Descriptor( + name='License', + full_name='License', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Id', full_name='License.Id', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='_Policy', full_name='License._Policy', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Key', full_name='License.Key', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseStartTime', full_name='License.LicenseStartTime', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestationVerified', full_name='License.RemoteAttestationVerified', index=4, + number=5, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProviderClientToken', full_name='License.ProviderClientToken', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProtectionScheme', full_name='License.ProtectionScheme', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='UnknownHdcpDataField', full_name='License.UnknownHdcpDataField', index=7, + number=8, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSE_POLICY, _LICENSE_KEYCONTAINER, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1667, + serialized_end=3581, +) + + +_LICENSEERROR = _descriptor.Descriptor( + name='LicenseError', + full_name='LicenseError', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ErrorCode', full_name='LicenseError.ErrorCode', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _LICENSEERROR_ERROR, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3584, + serialized_end=3756, +) + + +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor( + name='CENC', + full_name='LicenseRequest.ContentIdentification.CENC', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Pssh', full_name='LicenseRequest.ContentIdentification.CENC.Pssh', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequest.ContentIdentification.CENC.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequest.ContentIdentification.CENC.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4320, + serialized_end=4415, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor( + name='WebM', + full_name='LicenseRequest.ContentIdentification.WebM', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Header', full_name='LicenseRequest.ContentIdentification.WebM.Header', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='LicenseType', full_name='LicenseRequest.ContentIdentification.WebM.LicenseType', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestId', full_name='LicenseRequest.ContentIdentification.WebM.RequestId', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4417, + serialized_end=4493, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor( + name='ExistingLicense', + full_name='LicenseRequest.ContentIdentification.ExistingLicense', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='LicenseId', full_name='LicenseRequest.ContentIdentification.ExistingLicense.LicenseId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceStarted', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecondsSinceLastPlayed', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionUsageTableEntry', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4496, + serialized_end=4649, +) + +_LICENSEREQUEST_CONTENTIDENTIFICATION = _descriptor.Descriptor( + name='ContentIdentification', + full_name='LicenseRequest.ContentIdentification', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='CencId', full_name='LicenseRequest.ContentIdentification.CencId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='WebmId', full_name='LicenseRequest.ContentIdentification.WebmId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='License', full_name='LicenseRequest.ContentIdentification.License', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4103, + serialized_end=4649, +) + +_LICENSEREQUEST = _descriptor.Descriptor( + name='LicenseRequest', + full_name='LicenseRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ClientId', full_name='LicenseRequest.ClientId', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ContentId', full_name='LicenseRequest.ContentId', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Type', full_name='LicenseRequest.Type', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RequestTime', full_name='LicenseRequest.RequestTime', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonceDeprecated', full_name='LicenseRequest.KeyControlNonceDeprecated', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ProtocolVersion', full_name='LicenseRequest.ProtocolVersion', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='KeyControlNonce', full_name='LicenseRequest.KeyControlNonce', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='EncryptedClientId', full_name='LicenseRequest.EncryptedClientId', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION, ], + enum_types=[ + _LICENSEREQUEST_REQUESTTYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3759, + serialized_end=4719, +) + + +_PROVISIONEDDEVICEINFO = _descriptor.Descriptor( + name='ProvisionedDeviceInfo', + full_name='ProvisionedDeviceInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='SystemId', full_name='ProvisionedDeviceInfo.SystemId', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Soc', full_name='ProvisionedDeviceInfo.Soc', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Manufacturer', full_name='ProvisionedDeviceInfo.Manufacturer', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Model', full_name='ProvisionedDeviceInfo.Model', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='DeviceType', full_name='ProvisionedDeviceInfo.DeviceType', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='ModelYear', full_name='ProvisionedDeviceInfo.ModelYear', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SecurityLevel', full_name='ProvisionedDeviceInfo.SecurityLevel', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='TestDevice', full_name='ProvisionedDeviceInfo.TestDevice', index=7, + number=8, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4722, + serialized_end=5016, +) + + +_PROVISIONINGOPTIONS = _descriptor.Descriptor( + name='ProvisioningOptions', + full_name='ProvisioningOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5018, + serialized_end=5039, +) + + +_PROVISIONINGREQUEST = _descriptor.Descriptor( + name='ProvisioningRequest', + full_name='ProvisioningRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5041, + serialized_end=5062, +) + + +_PROVISIONINGRESPONSE = _descriptor.Descriptor( + name='ProvisioningResponse', + full_name='ProvisioningResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5064, + serialized_end=5086, +) + + +_REMOTEATTESTATION = _descriptor.Descriptor( + name='RemoteAttestation', + full_name='RemoteAttestation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Certificate', full_name='RemoteAttestation.Certificate', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Salt', full_name='RemoteAttestation.Salt', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='RemoteAttestation.Signature', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5088, + serialized_end=5193, +) + + +_SESSIONINIT = _descriptor.Descriptor( + name='SessionInit', + full_name='SessionInit', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5195, + serialized_end=5208, +) + + +_SESSIONSTATE = _descriptor.Descriptor( + name='SessionState', + full_name='SessionState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5210, + serialized_end=5224, +) + + +_SIGNEDCERTIFICATESTATUSLIST = _descriptor.Descriptor( + name='SignedCertificateStatusList', + full_name='SignedCertificateStatusList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5226, + serialized_end=5255, +) + + +_SIGNEDDEVICECERTIFICATE = _descriptor.Descriptor( + name='SignedDeviceCertificate', + full_name='SignedDeviceCertificate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='_DeviceCertificate', full_name='SignedDeviceCertificate._DeviceCertificate', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedDeviceCertificate.Signature', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signer', full_name='SignedDeviceCertificate.Signer', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5258, + serialized_end=5392, +) + + +_SIGNEDPROVISIONINGMESSAGE = _descriptor.Descriptor( + name='SignedProvisioningMessage', + full_name='SignedProvisioningMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5394, + serialized_end=5421, +) + + +_SIGNEDMESSAGE = _descriptor.Descriptor( + name='SignedMessage', + full_name='SignedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedMessage.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedMessage.Msg', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedMessage.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedMessage.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedMessage.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDMESSAGE_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5424, + serialized_end=5728, +) + + +_WIDEVINECENCHEADER = _descriptor.Descriptor( + name='WidevineCencHeader', + full_name='WidevineCencHeader', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='algorithm', full_name='WidevineCencHeader.algorithm', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='key_id', full_name='WidevineCencHeader.key_id', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='provider', full_name='WidevineCencHeader.provider', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='content_id', full_name='WidevineCencHeader.content_id', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='track_type_deprecated', full_name='WidevineCencHeader.track_type_deprecated', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='policy', full_name='WidevineCencHeader.policy', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='crypto_period_index', full_name='WidevineCencHeader.crypto_period_index', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='grouped_license', full_name='WidevineCencHeader.grouped_license', index=7, + number=8, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='protection_scheme', full_name='WidevineCencHeader.protection_scheme', index=8, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='crypto_period_seconds', full_name='WidevineCencHeader.crypto_period_seconds', index=9, + number=10, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _WIDEVINECENCHEADER_ALGORITHM, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5731, + serialized_end=6056, +) + + +_SIGNEDLICENSEREQUEST = _descriptor.Descriptor( + name='SignedLicenseRequest', + full_name='SignedLicenseRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedLicenseRequest.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedLicenseRequest.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedLicenseRequest.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedLicenseRequest.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedLicenseRequest.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDLICENSEREQUEST_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6059, + serialized_end=6394, +) + + +_SIGNEDLICENSE = _descriptor.Descriptor( + name='SignedLicense', + full_name='SignedLicense', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='Type', full_name='SignedLicense.Type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Msg', full_name='SignedLicense.Msg', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='Signature', full_name='SignedLicense.Signature', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='SessionKey', full_name='SignedLicense.SessionKey', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='RemoteAttestation', full_name='SignedLicense.RemoteAttestation', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SIGNEDLICENSE_MESSAGETYPE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6397, + serialized_end=6711, +) + +_CLIENTIDENTIFICATION_NAMEVALUE.containing_type = _CLIENTIDENTIFICATION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.fields_by_name['MaxHdcpVersion'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.containing_type = _CLIENTIDENTIFICATION +_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION.containing_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES +_CLIENTIDENTIFICATION.fields_by_name['Type'].enum_type = _CLIENTIDENTIFICATION_TOKENTYPE +_CLIENTIDENTIFICATION.fields_by_name['Token'].message_type = _SIGNEDDEVICECERTIFICATE +_CLIENTIDENTIFICATION.fields_by_name['ClientInfo'].message_type = _CLIENTIDENTIFICATION_NAMEVALUE +_CLIENTIDENTIFICATION.fields_by_name['_ClientCapabilities'].message_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES +_CLIENTIDENTIFICATION_TOKENTYPE.containing_type = _CLIENTIDENTIFICATION +_DEVICECERTIFICATE.fields_by_name['Type'].enum_type = _DEVICECERTIFICATE_CERTIFICATETYPE +_DEVICECERTIFICATE_CERTIFICATETYPE.containing_type = _DEVICECERTIFICATE +_DEVICECERTIFICATESTATUS.fields_by_name['Status'].enum_type = _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS +_DEVICECERTIFICATESTATUS.fields_by_name['DeviceInfo'].message_type = _PROVISIONEDDEVICEINFO +_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS.containing_type = _DEVICECERTIFICATESTATUS +_DEVICECERTIFICATESTATUSLIST.fields_by_name['CertificateStatus'].message_type = _DEVICECERTIFICATESTATUS +_LICENSEIDENTIFICATION.fields_by_name['Type'].enum_type = _LICENSETYPE +_LICENSE_POLICY.containing_type = _LICENSE +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['Hdcp'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['CgmsFlags'].enum_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS.containing_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER_KEYCONTROL.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER.fields_by_name['Type'].enum_type = _LICENSE_KEYCONTAINER_KEYTYPE +_LICENSE_KEYCONTAINER.fields_by_name['Level'].enum_type = _LICENSE_KEYCONTAINER_SECURITYLEVEL +_LICENSE_KEYCONTAINER.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER.fields_by_name['RequestedProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION +_LICENSE_KEYCONTAINER.fields_by_name['_KeyControl'].message_type = _LICENSE_KEYCONTAINER_KEYCONTROL +_LICENSE_KEYCONTAINER.fields_by_name['_OperatorSessionKeyPermissions'].message_type = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS +_LICENSE_KEYCONTAINER.fields_by_name['VideoResolutionConstraints'].message_type = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT +_LICENSE_KEYCONTAINER.containing_type = _LICENSE +_LICENSE_KEYCONTAINER_KEYTYPE.containing_type = _LICENSE_KEYCONTAINER +_LICENSE_KEYCONTAINER_SECURITYLEVEL.containing_type = _LICENSE_KEYCONTAINER +_LICENSE.fields_by_name['Id'].message_type = _LICENSEIDENTIFICATION +_LICENSE.fields_by_name['_Policy'].message_type = _LICENSE_POLICY +_LICENSE.fields_by_name['Key'].message_type = _LICENSE_KEYCONTAINER +_LICENSEERROR.fields_by_name['ErrorCode'].enum_type = _LICENSEERROR_ERROR +_LICENSEERROR_ERROR.containing_type = _LICENSEERROR +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['Pssh'].message_type = _WIDEVINECENCHEADER +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE +_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM +_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE +_LICENSEREQUEST_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUEST +_LICENSEREQUEST.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION +_LICENSEREQUEST.fields_by_name['ContentId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION +_LICENSEREQUEST.fields_by_name['Type'].enum_type = _LICENSEREQUEST_REQUESTTYPE +_LICENSEREQUEST.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION +_LICENSEREQUEST.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION +_LICENSEREQUEST_REQUESTTYPE.containing_type = _LICENSEREQUEST +_PROVISIONEDDEVICEINFO.fields_by_name['SecurityLevel'].enum_type = _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL +_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL.containing_type = _PROVISIONEDDEVICEINFO +_REMOTEATTESTATION.fields_by_name['Certificate'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION +_SIGNEDDEVICECERTIFICATE.fields_by_name['_DeviceCertificate'].message_type = _DEVICECERTIFICATE +_SIGNEDDEVICECERTIFICATE.fields_by_name['Signer'].message_type = _SIGNEDDEVICECERTIFICATE +_SIGNEDMESSAGE.fields_by_name['Type'].enum_type = _SIGNEDMESSAGE_MESSAGETYPE +_SIGNEDMESSAGE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDMESSAGE_MESSAGETYPE.containing_type = _SIGNEDMESSAGE +_WIDEVINECENCHEADER.fields_by_name['algorithm'].enum_type = _WIDEVINECENCHEADER_ALGORITHM +_WIDEVINECENCHEADER_ALGORITHM.containing_type = _WIDEVINECENCHEADER +_SIGNEDLICENSEREQUEST.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUEST_MESSAGETYPE +_SIGNEDLICENSEREQUEST.fields_by_name['Msg'].message_type = _LICENSEREQUEST +_SIGNEDLICENSEREQUEST.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDLICENSEREQUEST_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUEST +_SIGNEDLICENSE.fields_by_name['Type'].enum_type = _SIGNEDLICENSE_MESSAGETYPE +_SIGNEDLICENSE.fields_by_name['Msg'].message_type = _LICENSE +_SIGNEDLICENSE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION +_SIGNEDLICENSE_MESSAGETYPE.containing_type = _SIGNEDLICENSE +DESCRIPTOR.message_types_by_name['ClientIdentification'] = _CLIENTIDENTIFICATION +DESCRIPTOR.message_types_by_name['DeviceCertificate'] = _DEVICECERTIFICATE +DESCRIPTOR.message_types_by_name['DeviceCertificateStatus'] = _DEVICECERTIFICATESTATUS +DESCRIPTOR.message_types_by_name['DeviceCertificateStatusList'] = _DEVICECERTIFICATESTATUSLIST +DESCRIPTOR.message_types_by_name['EncryptedClientIdentification'] = _ENCRYPTEDCLIENTIDENTIFICATION +DESCRIPTOR.message_types_by_name['LicenseIdentification'] = _LICENSEIDENTIFICATION +DESCRIPTOR.message_types_by_name['License'] = _LICENSE +DESCRIPTOR.message_types_by_name['LicenseError'] = _LICENSEERROR +DESCRIPTOR.message_types_by_name['LicenseRequest'] = _LICENSEREQUEST +DESCRIPTOR.message_types_by_name['ProvisionedDeviceInfo'] = _PROVISIONEDDEVICEINFO +DESCRIPTOR.message_types_by_name['ProvisioningOptions'] = _PROVISIONINGOPTIONS +DESCRIPTOR.message_types_by_name['ProvisioningRequest'] = _PROVISIONINGREQUEST +DESCRIPTOR.message_types_by_name['ProvisioningResponse'] = _PROVISIONINGRESPONSE +DESCRIPTOR.message_types_by_name['RemoteAttestation'] = _REMOTEATTESTATION +DESCRIPTOR.message_types_by_name['SessionInit'] = _SESSIONINIT +DESCRIPTOR.message_types_by_name['SessionState'] = _SESSIONSTATE +DESCRIPTOR.message_types_by_name['SignedCertificateStatusList'] = _SIGNEDCERTIFICATESTATUSLIST +DESCRIPTOR.message_types_by_name['SignedDeviceCertificate'] = _SIGNEDDEVICECERTIFICATE +DESCRIPTOR.message_types_by_name['SignedProvisioningMessage'] = _SIGNEDPROVISIONINGMESSAGE +DESCRIPTOR.message_types_by_name['SignedMessage'] = _SIGNEDMESSAGE +DESCRIPTOR.message_types_by_name['WidevineCencHeader'] = _WIDEVINECENCHEADER +DESCRIPTOR.message_types_by_name['SignedLicenseRequest'] = _SIGNEDLICENSEREQUEST +DESCRIPTOR.message_types_by_name['SignedLicense'] = _SIGNEDLICENSE +DESCRIPTOR.enum_types_by_name['LicenseType'] = _LICENSETYPE +DESCRIPTOR.enum_types_by_name['ProtocolVersion'] = _PROTOCOLVERSION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ClientIdentification = _reflection.GeneratedProtocolMessageType('ClientIdentification', (_message.Message,), dict( + + NameValue = _reflection.GeneratedProtocolMessageType('NameValue', (_message.Message,), dict( + DESCRIPTOR = _CLIENTIDENTIFICATION_NAMEVALUE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification.NameValue) + )) + , + + ClientCapabilities = _reflection.GeneratedProtocolMessageType('ClientCapabilities', (_message.Message,), dict( + DESCRIPTOR = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification.ClientCapabilities) + )) + , + DESCRIPTOR = _CLIENTIDENTIFICATION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ClientIdentification) + )) +_sym_db.RegisterMessage(ClientIdentification) +_sym_db.RegisterMessage(ClientIdentification.NameValue) +_sym_db.RegisterMessage(ClientIdentification.ClientCapabilities) + +DeviceCertificate = _reflection.GeneratedProtocolMessageType('DeviceCertificate', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificate) + )) +_sym_db.RegisterMessage(DeviceCertificate) + +DeviceCertificateStatus = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatus', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATESTATUS, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificateStatus) + )) +_sym_db.RegisterMessage(DeviceCertificateStatus) + +DeviceCertificateStatusList = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatusList', (_message.Message,), dict( + DESCRIPTOR = _DEVICECERTIFICATESTATUSLIST, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:DeviceCertificateStatusList) + )) +_sym_db.RegisterMessage(DeviceCertificateStatusList) + +EncryptedClientIdentification = _reflection.GeneratedProtocolMessageType('EncryptedClientIdentification', (_message.Message,), dict( + DESCRIPTOR = _ENCRYPTEDCLIENTIDENTIFICATION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:EncryptedClientIdentification) + )) +_sym_db.RegisterMessage(EncryptedClientIdentification) + +LicenseIdentification = _reflection.GeneratedProtocolMessageType('LicenseIdentification', (_message.Message,), dict( + DESCRIPTOR = _LICENSEIDENTIFICATION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseIdentification) + )) +_sym_db.RegisterMessage(LicenseIdentification) + +License = _reflection.GeneratedProtocolMessageType('License', (_message.Message,), dict( + + Policy = _reflection.GeneratedProtocolMessageType('Policy', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_POLICY, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.Policy) + )) + , + + KeyContainer = _reflection.GeneratedProtocolMessageType('KeyContainer', (_message.Message,), dict( + + OutputProtection = _reflection.GeneratedProtocolMessageType('OutputProtection', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.OutputProtection) + )) + , + + KeyControl = _reflection.GeneratedProtocolMessageType('KeyControl', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_KEYCONTROL, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.KeyControl) + )) + , + + OperatorSessionKeyPermissions = _reflection.GeneratedProtocolMessageType('OperatorSessionKeyPermissions', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.OperatorSessionKeyPermissions) + )) + , + + VideoResolutionConstraint = _reflection.GeneratedProtocolMessageType('VideoResolutionConstraint', (_message.Message,), dict( + DESCRIPTOR = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer.VideoResolutionConstraint) + )) + , + DESCRIPTOR = _LICENSE_KEYCONTAINER, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License.KeyContainer) + )) + , + DESCRIPTOR = _LICENSE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:License) + )) +_sym_db.RegisterMessage(License) +_sym_db.RegisterMessage(License.Policy) +_sym_db.RegisterMessage(License.KeyContainer) +_sym_db.RegisterMessage(License.KeyContainer.OutputProtection) +_sym_db.RegisterMessage(License.KeyContainer.KeyControl) +_sym_db.RegisterMessage(License.KeyContainer.OperatorSessionKeyPermissions) +_sym_db.RegisterMessage(License.KeyContainer.VideoResolutionConstraint) + +LicenseError = _reflection.GeneratedProtocolMessageType('LicenseError', (_message.Message,), dict( + DESCRIPTOR = _LICENSEERROR, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseError) + )) +_sym_db.RegisterMessage(LicenseError) + +LicenseRequest = _reflection.GeneratedProtocolMessageType('LicenseRequest', (_message.Message,), dict( + + ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict( + + CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.CENC) + )) + , + + WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.WebM) + )) + , + + ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict( + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.ExistingLicense) + )) + , + DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification) + )) + , + DESCRIPTOR = _LICENSEREQUEST, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:LicenseRequest) + )) +_sym_db.RegisterMessage(LicenseRequest) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.CENC) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.WebM) +_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.ExistingLicense) + +ProvisionedDeviceInfo = _reflection.GeneratedProtocolMessageType('ProvisionedDeviceInfo', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONEDDEVICEINFO, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ProvisionedDeviceInfo) + )) +_sym_db.RegisterMessage(ProvisionedDeviceInfo) + +ProvisioningOptions = _reflection.GeneratedProtocolMessageType('ProvisioningOptions', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGOPTIONS, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningOptions) + )) +_sym_db.RegisterMessage(ProvisioningOptions) + +ProvisioningRequest = _reflection.GeneratedProtocolMessageType('ProvisioningRequest', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGREQUEST, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningRequest) + )) +_sym_db.RegisterMessage(ProvisioningRequest) + +ProvisioningResponse = _reflection.GeneratedProtocolMessageType('ProvisioningResponse', (_message.Message,), dict( + DESCRIPTOR = _PROVISIONINGRESPONSE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:ProvisioningResponse) + )) +_sym_db.RegisterMessage(ProvisioningResponse) + +RemoteAttestation = _reflection.GeneratedProtocolMessageType('RemoteAttestation', (_message.Message,), dict( + DESCRIPTOR = _REMOTEATTESTATION, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:RemoteAttestation) + )) +_sym_db.RegisterMessage(RemoteAttestation) + +SessionInit = _reflection.GeneratedProtocolMessageType('SessionInit', (_message.Message,), dict( + DESCRIPTOR = _SESSIONINIT, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SessionInit) + )) +_sym_db.RegisterMessage(SessionInit) + +SessionState = _reflection.GeneratedProtocolMessageType('SessionState', (_message.Message,), dict( + DESCRIPTOR = _SESSIONSTATE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SessionState) + )) +_sym_db.RegisterMessage(SessionState) + +SignedCertificateStatusList = _reflection.GeneratedProtocolMessageType('SignedCertificateStatusList', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDCERTIFICATESTATUSLIST, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedCertificateStatusList) + )) +_sym_db.RegisterMessage(SignedCertificateStatusList) + +SignedDeviceCertificate = _reflection.GeneratedProtocolMessageType('SignedDeviceCertificate', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDDEVICECERTIFICATE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedDeviceCertificate) + )) +_sym_db.RegisterMessage(SignedDeviceCertificate) + +SignedProvisioningMessage = _reflection.GeneratedProtocolMessageType('SignedProvisioningMessage', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDPROVISIONINGMESSAGE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedProvisioningMessage) + )) +_sym_db.RegisterMessage(SignedProvisioningMessage) + +SignedMessage = _reflection.GeneratedProtocolMessageType('SignedMessage', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDMESSAGE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedMessage) + )) +_sym_db.RegisterMessage(SignedMessage) + +WidevineCencHeader = _reflection.GeneratedProtocolMessageType('WidevineCencHeader', (_message.Message,), dict( + DESCRIPTOR = _WIDEVINECENCHEADER, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:WidevineCencHeader) + )) +_sym_db.RegisterMessage(WidevineCencHeader) + +SignedLicenseRequest = _reflection.GeneratedProtocolMessageType('SignedLicenseRequest', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDLICENSEREQUEST, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedLicenseRequest) + )) +_sym_db.RegisterMessage(SignedLicenseRequest) + +SignedLicense = _reflection.GeneratedProtocolMessageType('SignedLicense', (_message.Message,), dict( + DESCRIPTOR = _SIGNEDLICENSE, + __module__ = 'wv_proto3_pb2' + # @@protoc_insertion_point(class_scope:SignedLicense) + )) +_sym_db.RegisterMessage(SignedLicense) + + +# @@protoc_insertion_point(module_scope) diff --git a/pywidevine/cdm/key.py b/pywidevine/cdm/key.py new file mode 100644 index 0000000..0f0b956 --- /dev/null +++ b/pywidevine/cdm/key.py @@ -0,0 +1,14 @@ +import binascii + +class Key: + def __init__(self, kid, type, key, permissions=[]): + self.kid = kid + self.type = type + self.key = key + self.permissions = permissions + + def __repr__(self): + if self.type == "OPERATOR_SESSION": + return "key(kid={}, type={}, key={}, permissions={})".format(self.kid, self.type, binascii.hexlify(self.key), self.permissions) + else: + return "key(kid={}, type={}, key={})".format(self.kid, self.type, binascii.hexlify(self.key)) diff --git a/pywidevine/cdm/session.py b/pywidevine/cdm/session.py new file mode 100644 index 0000000..0f7295c --- /dev/null +++ b/pywidevine/cdm/session.py @@ -0,0 +1,18 @@ +class Session: + def __init__(self, session_id, init_data, device_config, offline): + self.session_id = session_id + self.init_data = init_data + self.offline = offline + self.device_config = device_config + self.device_key = None + self.session_key = None + self.derived_keys = { + 'enc': None, + 'auth_1': None, + 'auth_2': None + } + self.license_request = None + self.license = None + self.service_certificate = None + self.privacy_mode = False + self.keys = [] diff --git a/pywidevine/cdm/vmp.py b/pywidevine/cdm/vmp.py new file mode 100644 index 0000000..42ab1bf --- /dev/null +++ b/pywidevine/cdm/vmp.py @@ -0,0 +1,102 @@ +try: + from google.protobuf.internal.decoder import _DecodeVarint as _di # this was tested to work with protobuf 3, but it's an internal API (any varint decoder might work) +except ImportError: + # this is generic and does not depend on pb internals, however it will decode "larger" possible numbers than pb decoder which has them fixed + def LEB128_decode(buffer, pos, limit = 64): + result = 0 + shift = 0 + while True: + b = buffer[pos] + pos += 1 + result |= ((b & 0x7F) << shift) + if not (b & 0x80): + return (result, pos) + shift += 7 + if shift > limit: + raise Exception("integer too large, shift: {}".format(shift)) + _di = LEB128_decode + + +class FromFileMixin: + @classmethod + def from_file(cls, filename): + """Load given a filename""" + with open(filename,"rb") as f: + return cls(f.read()) + +# the signatures use a format internally similar to +# protobuf's encoding, but without wire types +class VariableReader(FromFileMixin): + """Protobuf-like encoding reader""" + + def __init__(self, buf): + self.buf = buf + self.pos = 0 + self.size = len(buf) + + def read_int(self): + """Read a variable length integer""" + # _DecodeVarint will take care of out of range errors + (val, nextpos) = _di(self.buf, self.pos) + self.pos = nextpos + return val + + def read_bytes_raw(self, size): + """Read size bytes""" + b = self.buf[self.pos:self.pos+size] + self.pos += size + return b + + def read_bytes(self): + """Read a bytes object""" + size = self.read_int() + return self.read_bytes_raw(size) + + def is_end(self): + return (self.size == self.pos) + + +class TaggedReader(VariableReader): + """Tagged reader, needed for implementing a WideVine signature reader""" + + def read_tag(self): + """Read a tagged buffer""" + return (self.read_int(), self.read_bytes()) + + def read_all_tags(self, max_tag=3): + tags = {} + while (not self.is_end()): + (tag, bytes) = self.read_tag() + if (tag > max_tag): + raise IndexError("tag out of bound: got {}, max {}".format(tag, max_tag)) + + tags[tag] = bytes + return tags + +class WideVineSignatureReader(FromFileMixin): + """Parses a widevine .sig signature file.""" + + SIGNER_TAG = 1 + SIGNATURE_TAG = 2 + ISMAINEXE_TAG = 3 + + def __init__(self, buf): + reader = TaggedReader(buf) + self.version = reader.read_int() + if (self.version != 0): + raise Exception("Unsupported signature format version {}".format(self.version)) + self.tags = reader.read_all_tags() + + self.signer = self.tags[self.SIGNER_TAG] + self.signature = self.tags[self.SIGNATURE_TAG] + + extra = self.tags[self.ISMAINEXE_TAG] + if (len(extra) != 1 or (extra[0] > 1)): + raise Exception("Unexpected 'ismainexe' field value (not '\\x00' or '\\x01'), please check: {0}".format(extra)) + + self.mainexe = bool(extra[0]) + + @classmethod + def get_tags(cls, filename): + """Return a dictionary of each tag in the signature file""" + return cls.from_file(filename).tags diff --git a/pywidevine/clients/__init__.py b/pywidevine/clients/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/clients/__pycache__/__init__.cpython-36.pyc b/pywidevine/clients/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..51f5787 Binary files /dev/null and b/pywidevine/clients/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/clients/__pycache__/__init__.cpython-37.pyc b/pywidevine/clients/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..725a903 Binary files /dev/null and b/pywidevine/clients/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/clients/__pycache__/__init__.cpython-39.pyc b/pywidevine/clients/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..594350d Binary files /dev/null and b/pywidevine/clients/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/__init__.py b/pywidevine/clients/netflix/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/clients/netflix/__pycache__/__init__.cpython-36.pyc b/pywidevine/clients/netflix/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..194de5d Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/__init__.cpython-37.pyc b/pywidevine/clients/netflix/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..0733c6b Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/__init__.cpython-39.pyc b/pywidevine/clients/netflix/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..65b4537 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/client.cpython-36.pyc b/pywidevine/clients/netflix/__pycache__/client.cpython-36.pyc new file mode 100644 index 0000000..e2fbb5d Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/client.cpython-36.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/client.cpython-37.pyc b/pywidevine/clients/netflix/__pycache__/client.cpython-37.pyc new file mode 100644 index 0000000..8a44230 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/client.cpython-37.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/client.cpython-39.pyc b/pywidevine/clients/netflix/__pycache__/client.cpython-39.pyc new file mode 100644 index 0000000..6d53f60 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/client.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/config.cpython-36.pyc b/pywidevine/clients/netflix/__pycache__/config.cpython-36.pyc new file mode 100644 index 0000000..b198e6b Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/config.cpython-36.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/config.cpython-37.pyc b/pywidevine/clients/netflix/__pycache__/config.cpython-37.pyc new file mode 100644 index 0000000..6889ff2 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/config.cpython-37.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/config.cpython-39.pyc b/pywidevine/clients/netflix/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000..8e3f9a4 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/config.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/profiles.cpython-36.pyc b/pywidevine/clients/netflix/__pycache__/profiles.cpython-36.pyc new file mode 100644 index 0000000..81d09c6 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/profiles.cpython-36.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/profiles.cpython-37.pyc b/pywidevine/clients/netflix/__pycache__/profiles.cpython-37.pyc new file mode 100644 index 0000000..a392af1 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/profiles.cpython-37.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/profiles.cpython-39.pyc b/pywidevine/clients/netflix/__pycache__/profiles.cpython-39.pyc new file mode 100644 index 0000000..1b5f7ad Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/profiles.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/subs.cpython-36.pyc b/pywidevine/clients/netflix/__pycache__/subs.cpython-36.pyc new file mode 100644 index 0000000..9e63664 Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/subs.cpython-36.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/subs.cpython-37.pyc b/pywidevine/clients/netflix/__pycache__/subs.cpython-37.pyc new file mode 100644 index 0000000..b5e9cca Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/subs.cpython-37.pyc differ diff --git a/pywidevine/clients/netflix/__pycache__/subs.cpython-39.pyc b/pywidevine/clients/netflix/__pycache__/subs.cpython-39.pyc new file mode 100644 index 0000000..4c820de Binary files /dev/null and b/pywidevine/clients/netflix/__pycache__/subs.cpython-39.pyc differ diff --git a/pywidevine/clients/netflix/client.py b/pywidevine/clients/netflix/client.py new file mode 100644 index 0000000..435239d --- /dev/null +++ b/pywidevine/clients/netflix/client.py @@ -0,0 +1,1420 @@ +import base64 +from datetime import datetime +import gzip +import zlib +import json +import logging +from io import BytesIO +import random +import time +import os +import re +from itertools import islice + + +import requests +from Cryptodome.Cipher import AES +from Cryptodome.Cipher import PKCS1_OAEP +from Cryptodome.Hash import HMAC, SHA256 +from Cryptodome.PublicKey import RSA +from Cryptodome.Random import get_random_bytes +from Cryptodome.Util import Padding + +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg +import pywidevine.clients.netflix.config as nf_cfg +import pywidevine.clients.netflix.subs as subs +from pywidevine.downloader.tracks import VideoTrack, AudioTrack, SubtitleTrack + +# for operator sessions +from pywidevine.cdm import cdm, deviceconfig + + +from urllib3.exceptions import InsecureRequestWarning +# Suppress only the single warning from urllib3 needed. +requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) + +import urllib3 + +currentFile = __file__ +realPath = os.path.realpath(currentFile) +realPath = realPath.replace('pywidevine\\clients\\netflix\\client.py', '') +dirPath = os.path.dirname(realPath) +dirName = os.path.basename(dirPath) +wvDecrypterexe = dirPath + '/binaries/wvDecrypter/wvDecrypter.exe' +challengeBIN = dirPath + '/binaries/wvDecrypter/challenge.bin' +licenceBIN = dirPath + '/binaries/wvDecrypter/licence.bin' +mp4dump = dirPath + "/binaries/mp4dump.exe" + + +# keys are not padded properly +def base64key_decode(payload): + l = len(payload) % 4 + if l == 2: + payload += '==' + elif l == 3: + payload += '=' + elif l != 0: + raise ValueError('Invalid base64 string') + return base64.urlsafe_b64decode(payload.encode('utf-8')) + + +def find_str(s, char): + index = 0 + if char in s: + c = char[0] + for ch in s: + if ch == c and s[index:index + len(char)] == char: + return index + index += 1 + + return -1 + + +class NetflixClient(object): + def __init__(self, client_config): + self.logger = logging.getLogger(__name__) + self.logger.debug("creating NetflixClient object") + self.client_config = client_config + self.session = requests.Session() + self.current_message_id = 0 + self.rsa_key = None + self.encryption_key = None + self.sign_key = None + self.sequence_number = None + self.mastertoken = None + self.useridtoken = None + self.playbackContextId = None + self.drmContextId = None + self.playbackContextId_hpl = None + self.drmContextId_hpl = None + self.tokens = [] + self.rndm = random.SystemRandom() + #self.cookies = self.cookie_login() + + # for operator sessions: + if self.client_config.config['wv_keyexchange']: + self.wv_keyexchange = True + self.cdm = cdm.Cdm() + self.cdm_session = None + else: + self.wv_keyexchange = False + self.cdm = None + self.cdm_session = None + + + def login(self): + self.logger.info("acquiring token & key for netflix api") + config_dict = self.client_config.config + + #if self.cookies is None: + # self.cookies = self.cookie_login() + + if self.file_exists(wvdl_cfg.COOKIES_FOLDER, config_dict['msl_storage']): + self.logger.info("old MSL data found, using") + self.__load_msl_data() + else: + # could add support for other key exchanges here + if not self.wv_keyexchange: + if self.file_exists(wvdl_cfg.COOKIES_FOLDER, 'rsa_key.bin'): + self.logger.info('old RSA key found, using') + self.__load_rsa_keys() + else: + self.logger.info('create new RSA Keys') + # Create new Key Pair and save + self.rsa_key = RSA.generate(2048) + self.__save_rsa_keys() + # both RSA and wv key exchanges can be performed now + self.__perform_key_handshake() + + if self.encryption_key: + self.logger.info("negotiation successful, token & key acquired") + return True + else: + self.logger.error("failed to perform key handshake") + return False + + '''def cookie_login(self): + """Logs into netflix""" + config_dict = self.client_config.config + post_data = { + 'email': config_dict['username'], + 'password': config_dict['password'], + 'rememberMe': 'true', + 'mode': 'login', + 'action': 'loginAction', + 'withFields': 'email,password,rememberMe,nextPage,showPassword', + 'nextPage': '', + 'showPassword': '', + } + req = self.session.post('https://www.netflix.com/login', post_data) + return req.cookies''' + + def get_track_and_init_info(self, quality, profile, all_subs=False,only_subs=False): + config_dict = self.client_config.config + self.logger.info("video information") + self.quality = quality.replace('p', '') + self.profiles = profile + print(self.profiles) + id = int(time.time() * 10000) + """ + manifest_request_data = { + + 'method': 'manifest', + 'lookupType': 'PREPARE', + 'viewableIds': [self.client_config.viewable_id], + 'profiles': config_dict['profiles'], + 'drmSystem': 'widevine', + 'appId': '14673889385265', + 'sessionParams': { + 'pinCapableClient': False, + 'uiplaycontext': 'null' + }, + 'sessionId': '14673889385265', + 'trackId': 0, + 'flavor': 'PRE_FETCH', + 'secureUrls': True, + 'supportPreviewContent': True, + 'forceClearStreams': False, + 'languages': ['en-US'], + 'clientVersion': '6.0011.474.011', + 'uiVersion': 'shakti-v25d2fa21', + 'showAllSubDubTracks': all_subs + + } + """ + #'profiles': config_dict['profiles'], + #profiles = ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'playready-h264hpl30-dash', 'playready-h264hpl31-dash', 'playready-h264hpl40-dash', 'heaac-2-dash', 'dfxp-ls-sdh', 'simplesdh',] + #profiles = ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'playready-h264hpl30-dash', 'playready-h264hpl31-dash', 'playready-h264hpl40-dash', 'heaac-2-dash', 'BIF240', 'BIF320'] + + + profiles_hpl = [ + #'playready-h264bpl30-dash', + #'playready-h264hpl30-dash', + #'playready-h264hpl31-dash', + #'playready-h264hpl40-dash', + "hevc-hdr-main10-L41-dash-cenc", + "hevc-hdr-main10-L50-dash-cenc", + "hevc-hdr-main10-L51-dash-cenc", + "hevc-hdr-main10-L41-dash-cenc-prk", + "hevc-hdr-main10-L50-dash-cenc-prk", + "hevc-hdr-main10-L51-dash-cenc-prk", + 'ddplus-2.0-dash', + 'ddplus-5.1hq-dash', + 'ddplus-atmos-dash', + 'dd-5.1-dash', + #'dfxp-ls-sdh', + 'simplesdh', + #'nflx-cmisc', + #'BIF240', + #'BIF320' + ] + + + + profiles_sd = [ + #'playready-h264mpl30-dash', + "hevc-hdr-main10-L41-dash-cenc", + "hevc-hdr-main10-L50-dash-cenc", + "hevc-hdr-main10-L51-dash-cenc", + "hevc-hdr-main10-L41-dash-cenc-prk", + "hevc-hdr-main10-L50-dash-cenc-prk", + "hevc-hdr-main10-L51-dash-cenc-prk", + 'ddplus-2.0-dash', + 'ddplus-5.1hq-dash', + 'ddplus-atmos-dash', + 'dd-5.1-dash', + #'dfxp-ls-sdh', + 'simplesdh', + #'nflx-cmisc', + #'BIF240', + #'BIF320' + ] + + + profiles_4k = [ + #'playready-h264bpl30-dash', + #'playready-h264hpl30-dash', + #'playready-h264hpl31-dash', + #'playready-h264hpl40-dash', + "hevc-hdr-main10-L41-dash-cenc", + "hevc-hdr-main10-L50-dash-cenc", + "hevc-hdr-main10-L51-dash-cenc", + "hevc-hdr-main10-L41-dash-cenc-prk", + "hevc-hdr-main10-L50-dash-cenc-prk", + "hevc-hdr-main10-L51-dash-cenc-prk", + 'ddplus-2.0-dash', + 'ddplus-5.1hq-dash', + 'ddplus-atmos-dash', + 'dd-5.1-dash', + #'dfxp-ls-sdh', + 'simplesdh', + #'nflx-cmisc', + #'BIF240', + #'BIF320' + ] + + #config_dict['profiles'], + + manifest_request_data = { + 'version': 2, + 'url': '/manifest', + 'id': id, + 'esn': self.client_config.config['esn'], + 'languages' : ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.474.011', + 'params': { + 'type': 'standard', + 'viewableId': [self.client_config.viewable_id], + 'profiles': profiles_4k, #config_dict['profiles'], + 'flavor': 'PRE_FETCH', + 'drmType': 'widevine', + 'drmVersion': 25, + 'usePsshBox': True, + 'isBranching': False, + 'useHttpsStreams': False, + 'imageSubtitleHeight': 2160, + 'uiVersion': 'shakti-vb45817f4', + 'clientVersion': '6.0011.511.011', + 'supportsPreReleasePin': True, + 'supportsWatermark': True, + 'showAllSubDubTracks': False, + 'titleSpecificData': {}, + 'videoOutputInfo': [{ + 'type': 'DigitalVideoOutputDescriptor', + 'outputType': 'unknown', + 'supportedHdcpVersions': ['2.2'], + 'isHdcpEngaged': True + }], + 'preferAssistiveAudio': False, + 'isNonMember': False + } + } + + + manifest_request_data_hpl = { + 'version': 2, + 'url': '/manifest', + 'id': id, + 'esn': self.client_config.config['esn'], + 'languages' : ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.474.011', + 'params': { + 'type': 'standard', + 'viewableId': [self.client_config.viewable_id], + 'profiles': profiles_hpl, + 'flavor': 'PRE_FETCH', + 'drmType': 'widevine', + 'drmVersion': 25, + 'usePsshBox': True, + 'isBranching': False, + 'useHttpsStreams': False, + 'imageSubtitleHeight': 2160, + 'uiVersion': 'shakti-vb45817f4', + 'clientVersion': '6.0011.511.011', + 'supportsPreReleasePin': True, + 'supportsWatermark': True, + 'showAllSubDubTracks': False, + 'titleSpecificData': {}, + 'videoOutputInfo': [{ + 'type': 'DigitalVideoOutputDescriptor', + 'outputType': 'unknown', + 'supportedHdcpVersions': ['2.2'], + 'isHdcpEngaged': True + }], + 'preferAssistiveAudio': False, + 'isNonMember': False + } + } + + + + + manifest_request_data_sd = { + 'version': 2, + 'url': '/manifest', + 'id': id, + 'esn': self.client_config.config['esn'], + 'languages' : ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.474.011', + 'params': { + 'type': 'standard', + 'viewableId': [self.client_config.viewable_id], + 'profiles': profiles_sd, + 'flavor': 'PRE_FETCH', + 'drmType': 'widevine', + 'drmVersion': 25, + 'usePsshBox': True, + 'isBranching': False, + 'useHttpsStreams': False, + 'imageSubtitleHeight': 2160, + 'uiVersion': 'shakti-vb45817f4', + 'clientVersion': '6.0011.511.011', + 'supportsPreReleasePin': True, + 'supportsWatermark': True, + 'showAllSubDubTracks': False, + 'titleSpecificData': {}, + 'videoOutputInfo': [{ + 'type': 'DigitalVideoOutputDescriptor', + 'outputType': 'unknown', + 'supportedHdcpVersions': ['2.2'], + 'isHdcpEngaged': True + }], + 'preferAssistiveAudio': False, + 'isNonMember': False + } + } + + + + + + self.logger.debug("requesting manifest") + request_data = self.__generate_msl_request_data(manifest_request_data) + request_data_hpl = self.__generate_msl_request_data(manifest_request_data_hpl) + request_data_sd = self.__generate_msl_request_data(manifest_request_data_sd) + + + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, request_data, headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, verify=False) + resp_hpl = self.session.post(nf_cfg.MANIFEST_ENDPOINT, request_data_hpl, headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, verify=False) + resp_sd = self.session.post(nf_cfg.MANIFEST_ENDPOINT, request_data_sd, headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, verify=False) + + + + #self.logger.debug(manifest_request_data) + data = {} + data_hpl = {} + data_sd = {} + + try: + # if the json() does not fail we have an error because the manifest response is a chuncked json response + resp.json() + resp_hpl.json() + resp_sd.json() + self.logger.debug('Error getting Manifest: '+resp.text) + self.logger.debug('Error getting Manifest: '+resp_hpl.text) + self.logger.debug('Error getting Manifest: '+resp_sd.text) + return False, None + except ValueError: + # json() failed so parse the chunked response + global data1 + self.logger.debug('Got chunked Manifest Response: ' + resp.text) + self.logger.debug('Got chunked Manifest Response: ' + resp_hpl.text) + resp = self.__parse_chunked_msl_response(resp.text) + resp_hpl = self.__parse_chunked_msl_response(resp_hpl.text) + resp_sd = self.__parse_chunked_msl_response(resp_sd.text) + #print(resp.text) + self.logger.debug('Parsed chunked Response: ' + json.dumps(resp)) + data = self.__decrypt_payload_chunk(resp['payloads']) + data_hpl = self.__decrypt_payload_chunk(resp_hpl['payloads']) + data_sd = self.__decrypt_payload_chunk(resp_sd['payloads']) + data1 = self.__decrypt_payload_chunk(resp['payloads']) + fobj = open("manifest.json", "w") + #fobj.write(str(data['result'])) + #data['result']['links']['license']['href'] + playlist = json.dumps(data) + fobj.write(playlist) + fobj.close() + + fobj = open("manifest_hpl.json", "w") + #fobj.write(str(data['result'])) + #data['result']['links']['license']['href'] + playlist_hpl = json.dumps(data_hpl) + fobj.write(playlist_hpl) + fobj.close() + + + fobj = open("manifest_sd.json", "w") + #fobj.write(str(data['result'])) + #data['result']['links']['license']['href'] + playlist_sd = json.dumps(data_sd) + fobj.write(playlist_sd) + fobj.close() + + + #self.logger.debug(data['result']) + #[0] + + try: + + #self.logger.debug("manifest json: %s" % data['result']['viewables'][0]) + #self.playbackContextId = data['result']['viewables'][0]['playbackContextId'] + #self.drmContextId = data['result']['viewables'][0]['drmContextId'] + self.logger.debug("manifest json: %s" % data['result']) + self.playbackContextId = data['result']['playbackContextId'] + self.drmContextId = data['result']['drmContextId'] + + self.playbackContextId_hpl = data_hpl['result']['playbackContextId'] + self.drmContextId_hpl = data_hpl['result']['drmContextId'] + + + + self.playbackContextId_sd = data_sd['result']['playbackContextId'] + self.drmContextId_sd = data_sd['result']['drmContextId'] + + + #print(self.playbackContextId) + #print(self.drmContextId) + #print(self.playbackContextId_hpl) + #print(self.drmContextId_hpl) + + #global data1 + #print(data['result']['links']['license']['href']) + #print(data_hpl['result']['links']['license']['href']) + + #print(data['result']['video_tracks'][0]['drmHeader']['bytes']) + #print(data_hpl['result']['video_tracks'][0]['drmHeader']['bytes']) + + + except (KeyError, IndexError): + self.logger.error('No viewables found') + if 'errorDisplayMessage' in data['result']: + self.logger.error('MSL Error Message: {}'.format(data['result']['errorDisplayMessage'])) + return False, None + + self.logger.debug(data) + self.logger.debug("netflix cannot get title name from manifest") + #subtitle_tracks_js = data['result']['viewables'][0]['textTracks'] + subtitle_tracks_js = data['result']['timedtexttracks'] + self.logger.debug(len(subtitle_tracks_js)) + subtitle_tracks_filtered = [x for x in subtitle_tracks_js if "language" in x] + subtitle_tracks_filtered = list(islice(subtitle_tracks_filtered, len(subtitle_tracks_js)-1)) + self.logger.debug(subtitle_tracks_filtered) + + self.logger.info("found {} subtitle tracks".format(len(subtitle_tracks_filtered))) + for subtitle_track in subtitle_tracks_filtered: + self.logger.info( + "Name: {} bcp47: {} type: {}".format(subtitle_track['language'], subtitle_track['language'], subtitle_track['trackType']) + ) + + if only_subs: + wvdl_sts = [] + for i, subtitle in enumerate(subtitle_tracks_filtered): + if not subtitle['isForcedNarrative']: + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], True, next(iter(list(subtitle['downloadables'][0]['urls'].values()))), + 'srt') + ) + print(wvdl_sts) + return True, wvdl_sts + + #video_tracks_js = data['result']['viewables'][0]['videoTracks'][0]['downloadables'] + video_tracks_js = data['result']['video_tracks'][0]['streams'] + video_tracks_js_hpl = data_hpl['result']['video_tracks'][0]['streams'] + + self.logger.info("found {} video tracks".format(len(video_tracks_js))) + self.logger.info("found {} video tracks".format(len(video_tracks_js_hpl))) + for vid_id, video in enumerate(sorted(video_tracks_js, key= lambda v: int(v['bitrate']))): + self.logger.info( + "{} - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(vid_id, video['bitrate'], + video['content_profile'], + video['size'], + video['res_w'], + video['res_h']) + ) + + for vid_id_hpl, video_hpl in enumerate(sorted(video_tracks_js_hpl, key= lambda v_hpl: int(v_hpl['bitrate']))): + self.logger.info( + "{} - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(vid_id_hpl, video_hpl['bitrate'], + video_hpl['content_profile'], + video_hpl['size'], + video_hpl['res_w'], + video_hpl['res_h']) + ) + + audio_tracks_js = data['result']['audio_tracks'] + audio_tracks_flattened = [] + + for audio_track in audio_tracks_js: + for downloadable in audio_track['streams']: + new_track = audio_track.copy() + new_track['downloadables'] = downloadable + audio_tracks_flattened.append(new_track) + + self.logger.info("found {} audio tracks".format(len(audio_tracks_flattened))) + for aud_id, audio_track in enumerate( + sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']))): + self.logger.info( + "{} = Bitrate: {} Profile: {} Channels: {} Language: {} Lang: {} Size: {}".format(aud_id, audio_track[ + 'downloadables']['bitrate'], + audio_track[ + 'downloadables'][ + 'content_profile'], + audio_track[ + 'channels'], + audio_track[ + 'language'], + audio_track['language'], + audio_track[ + 'downloadables'][ + 'size']) + ) + + + self.logger.info("selected tracks") + if config_dict['video_track'] is not None: + self.logger.debug("VIDEO_TRACK_ID ARGUMENT: {}".format(config_dict['video_track'])) + if config_dict['video_track'] >= len(video_tracks_js): + self.logger.error("selected video track does not exist") + return False, [] + video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']))[int(config_dict['video_track'])] + + #video_track = sorted([x for x in video_representations if x['@height'] == config_dict['resolution']], + # key=lambda r: int(r['@bandwidth']), reverse=True) + + else: + #pass + #for x in video_tracks_js: + #print(x['res_h']) + #video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']), reverse=True)[0] + video_track_mpl = sorted([x for x in video_tracks_js if x['res_h'] == int(self.quality)] , key= lambda v: int(v['bitrate']), reverse=True)[0] + + try: + video_track_hpl = sorted([x for x in video_tracks_js_hpl if x['res_h'] == int(self.quality)] , key= lambda v_hpl: int(v_hpl['bitrate']), reverse=True)[0] + except IndexError: + video_track_hpl = video_track_mpl + print(video_track_mpl['bitrate']) + print(video_track_hpl['bitrate']) + + global links_license + + if video_track_mpl['bitrate'] >= video_track_hpl['bitrate']: + print("mpl grosser") + video_track = video_track_mpl + + #1080p pssh + #init_data_b64 = data['result']['video_tracks'][0]['drmHeader']['bytes'] + #links_license = data['result']['links']['license']['href'] + + #sd pssh + init_data_b64 = data_sd['result']['video_tracks'][0]['drmHeader']['bytes'] + links_license = data_sd['result']['links']['license']['href'] + device = 'mpl' + + else: + print("hpl grosser") + input("hpl grosser") + video_track = video_track_hpl + init_data_b64 = data_hpl['result']['video_tracks'][0]['drmHeader']['bytes'] + links_license = data_hpl['result']['links']['license']['href'] + device = 'hpl' + print(init_data_b64) + print(links_license) + + + + self.logger.info("VIDEO - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(video_track['bitrate'], + video_track['content_profile'], + video_track['size'], + video_track['res_w'], + video_track['res_h'])) + #print(args.quality) + audio_tracks = [] + + if config_dict['audio_tracks'] != []: + self.logger.debug("AUDIO_TRACK_ID ARUGMENT: {}".format(config_dict['audio_tracks'])) + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate'])) + for t_id in config_dict['audio_tracks']: + audio_tracks.append(sorted_aud[int(t_id)]) + else: + selected_track = None + bitrate = 0 + channels = 0 + profile = None + #default_audio_lang = data['result']['viewables'][0]['orderedAudioTracks'][0] + audio_lang_selectors = { + 'English': 'en', + 'French': 'fr', + 'German': 'de', + 'Italian': 'it', + 'Spanish': 'es', + 'Flemish': 'nl-BE', + 'Finnish': 'fi', + 'No Dialogue': 'zxx', + 'Czech': 'cs', + 'European Spanish': 'es-ES', + 'Japanese': 'ja', + 'Brazilian Portuguese': 'pt-BR', + 'Polish': 'pl', + 'Turkish': 'tr', + 'Mandarin': 'zh', + 'Cantonese': 'yue', + 'Arabic': 'ar', + 'Korean': 'ko', + 'Hebrew': 'he', + 'Norwegian': 'nb', + 'Swedish': 'sv', + 'Arabic': 'ar' + } + aud_profile_table = { + 'heaac-2-dash': 0, + 'ddplus-2.0-dash': 1, + 'ddplus-5.1-dash': 2, + 'dd-5.1-dash': 3 + } + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']), reverse=True) + + if video_track['res_h'] == 480: + sorted_aud = [a_track for a_track in sorted_aud if a_track['channels'] == '2.0'] + + audio_selected = ['en'] + if config_dict['audio_language'] is not None: + audio_selected = config_dict['audio_language'] + print("aaaaaa") + print(audio_selected) + + for audio_select in audio_selected: + for aud_track_sorted in sorted_aud: + if aud_track_sorted['language'] == audio_select: + audio_tracks.append(aud_track_sorted) + break + + # if selected_track == None: + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + # if (bitrate < aud_track_sorted['downloadables']['bitrate']) and ( + # channels <= aud_track_sorted['channels']) and ( + # profile <= aud_profile_table[aud_track_sorted['downloadables']['contentProfile']]): + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + + # audio_tracks.append(selected_track) + # if selected_track == None: + # self.logger.error("netfix cannot auto select audio track, please specify at least one") + # return False, [] + for audio_track in audio_tracks: + self.logger.info("AUDIO - Bitrate: {} Profile: {} Channels: {} Language: {} Size: {}".format( + audio_track['downloadables']['bitrate'], + audio_track['downloadables']['content_profile'], + audio_track['channels'], + audio_track['languageDescription'], + audio_track['downloadables']['size'])) + + if audio_tracks[0]['language'] == 'de': + print('dedededede') + else: + input("KEIN DEDEDEDEDE") + + + if config_dict['subtitle_languages'] is not None: + self.logger.debug("SUBTITLE_LANGUAGE_ARGUMENT: {}".format(config_dict['subtitle_languages'])) + if 'all' in config_dict['subtitle_languages']: + subtitle_tracks = subtitle_tracks_filtered + else: + subtitle_tracks = [x for x in subtitle_tracks_filtered if + x['language'] in config_dict['subtitle_languages']] + else: + subtitle_tracks = None + if subtitle_tracks: + for subtitle in subtitle_tracks: + self.logger.info("SUBTITLE - Name: {} bcp47: {}".format(subtitle['language'], subtitle['language'])) + + #init_data_b64 = data['result']['viewables'][0]['psshb64'][0] + + #init_data_b64 = data['result']['video_tracks'][0]['drmHeader']['bytes'] + #init_data_b64_hpl = data_hpl['result']['video_tracks'][0]['drmHeader']['bytes'] + + #init_data_b64 = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQAAAAAAUrePMAAAAAAAAAAA==' + #init_data_b64 = "" + + #cert_data_b64 = data['result']['viewables'][0]['cert'] + cert_data_b64 = 'CAUSwwUKvQIIAxIQ5US6QAvBDzfTtjb4tU/7QxiH8c+TBSKOAjCCAQoCggEBAObzvlu2hZRsapAPx4Aa4GUZj4/GjxgXUtBH4THSkM40x63wQeyVxlEEo1D/T1FkVM/S+tiKbJiIGaT0Yb5LTAHcJEhODB40TXlwPfcxBjJLfOkF3jP6wIlqbb6OPVkDi6KMTZ3EYL6BEFGfD1ag/LDsPxG6EZIn3k4S3ODcej6YSzG4TnGD0szj5m6uj/2azPZsWAlSNBRUejmP6Tiota7g5u6AWZz0MsgCiEvnxRHmTRee+LO6U4dswzF3Odr2XBPD/hIAtp0RX8JlcGazBS0GABMMo2qNfCiSiGdyl2xZJq4fq99LoVfCLNChkn1N2NIYLrStQHa35pgObvhwi7ECAwEAAToQdGVzdC5uZXRmbGl4LmNvbRKAA4TTLzJbDZaKfozb9vDv5qpW5A/DNL9gbnJJi/AIZB3QOW2veGmKT3xaKNQ4NSvo/EyfVlhc4ujd4QPrFgYztGLNrxeyRF0J8XzGOPsvv9Mc9uLHKfiZQuy21KZYWF7HNedJ4qpAe6gqZ6uq7Se7f2JbelzENX8rsTpppKvkgPRIKLspFwv0EJQLPWD1zjew2PjoGEwJYlKbSbHVcUNygplaGmPkUCBThDh7p/5Lx5ff2d/oPpIlFvhqntmfOfumt4i+ZL3fFaObvkjpQFVAajqmfipY0KAtiUYYJAJSbm2DnrqP7+DmO9hmRMm9uJkXC2MxbmeNtJHAHdbgKsqjLHDiqwk1JplFMoC9KNMp2pUNdX9TkcrtJoEDqIn3zX9p+itdt3a9mVFc7/ZL4xpraYdQvOwP5LmXj9galK3s+eQJ7bkX6cCi+2X+iBmCMx4R0XJ3/1gxiM5LiStibCnfInub1nNgJDojxFA3jH/IuUcblEf/5Y0s1SzokBnR8V0KbA==' + #cert_data_b64 = cert_data_b64.decode("utf-8") + #cert_data_b64 = 'Cr0CCAMSEOVEukALwQ8307Y2+LVP+0MYh/HPkwUijgIwggEKAoIBAQDm875btoWUbGqQD8eAGuBlGY+Pxo8YF1LQR+Ex0pDONMet8EHslcZRBKNQ/09RZFTP0vrYimyYiBmk9GG+S0wB3CRITgweNE15cD33MQYyS3zpBd4z+sCJam2+jj1ZA4uijE2dxGC+gRBRnw9WoPyw7D8RuhGSJ95OEtzg3Ho+mEsxuE5xg9LM4+Zuro/9msz2bFgJUjQUVHo5j+k4qLWu4ObugFmc9DLIAohL58UR5k0XnvizulOHbMMxdzna9lwTw/4SALadEV/CZXBmswUtBgATDKNqjXwokohncpdsWSauH6vfS6FXwizQoZJ9TdjSGC60rUB2t+aYDm74cIuxAgMBAAE6EHRlc3QubmV0ZmxpeC5jb20SgAOE0y8yWw2Win6M2/bw7+aqVuQPwzS/YG5ySYvwCGQd0Dltr3hpik98WijUODUr6PxMn1ZYXOLo3eED6xYGM7Riza8XskRdCfF8xjj7L7/THPbixyn4mULsttSmWFhexzXnSeKqQHuoKmerqu0nu39iW3pcxDV/K7E6aaSr5ID0SCi7KRcL9BCUCz1g9c43sNj46BhMCWJSm0mx1XFDcoKZWhpj5FAgU4Q4e6f+S8eX39nf6D6SJRb4ap7Znzn7preIvmS93xWjm75I6UBVQGo6pn4qWNCgLYlGGCQCUm5tg566j+/g5jvYZkTJvbiZFwtjMW5njbSRwB3W4CrKoyxw4qsJNSaZRTKAvSjTKdqVDXV/U5HK7SaBA6iJ981/aforXbd2vZlRXO/2S+Maa2mHULzsD+S5l4/YGpSt7PnkCe25F+nAovtl/ogZgjMeEdFyd/9YMYjOS4krYmwp3yJ7m9ZzYCQ6I8RQN4x/yLlHG5RH/+WNLNUs6JAZ0fFdCmw=' + #cert_data_b64 = '' + + """ + self.logger.debug(video_track['urls'][0]['url']) + self.logger.debug(audio_track['downloadables']['urls'][0]['url']) + self.logger.debug(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values())[0]) + """ + + #iter(video_track['urls'].values()) + #next(iter(video_track['urls'][0]['url'])), + + wvdl_vt = VideoTrack(True, video_track['size'], 0, video_track['urls'][0]['url'], + video_track['content_profile'], video_track['bitrate'], + video_track['res_w'], video_track['res_h']) + print(wvdl_vt) + + wvdl_ats = [] + audio_languages = [] + + + #iter(audio_track['downloadables']['urls'].values())), + #next(iter(audio_track['downloadables']['urls'][0]['url'])), + + + + for id, audio_track in enumerate(audio_tracks): + audio_languages.append(audio_track['languageDescription'].replace("English [Original]", "English").replace("German [Original]", "German").replace(" [Original]", "")) + #print(audio_track) + wvdl_ats.append( + AudioTrack(False, audio_track['downloadables']['size'], id, audio_track['downloadables']['urls'][0]['url'], + audio_track['downloadables']['content_profile'], audio_track['downloadables']['bitrate'], audio_track['languageDescription'].replace("English [Original]", "English").replace("German [Original]", "German").replace(" [Original]", "")) + ) + + + print(wvdl_ats) + + wvdl_sts = [] + use_captions = { 'de': True } + if subtitle_tracks: + for track in subtitle_tracks: + use_captions.update({track['language']: True}) + for track in subtitle_tracks: + if track['language'] == 'de' and track['trackType'] == "SUBTITLES" and not track['isForcedNarrative']: + use_captions.update({track['language']:False}) + + for i, subtitle in enumerate(subtitle_tracks): + + #print('xxxxxxx\n') + #if config_dict['audio_language'][0] == 'de': + #print(len(config_dict['audio_language'])) + + #if 'de' or 'German [Original]' or 'en' or 'English [Original]' in audio_languages: + if len(config_dict['audio_language']) == 1: + + if subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.insert(0, + SubtitleTrack(i, 'Forced', subtitle['language'], True, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + + if not subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + + + + if len(config_dict['audio_language']) > 1: + + if subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.insert(0, + SubtitleTrack(i, 'Forced', subtitle['language'], True, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + if not subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + + if subtitle['isForcedNarrative'] and subtitle['language'] == audio_selected[1] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, 'Forced', subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + if not subtitle['isForcedNarrative'] and subtitle['language'] == audio_selected[1] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + 'srt') + ) + + + + + + #~ elif not subtitle['isForcedNarrative'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + #~ wvdl_sts.append( + #~ SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + #~ 'srt') + #~ ) + + #~ if subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + #~ wvdl_sts.append( + #~ SubtitleTrack(i, 'Forced', subtitle['language'], True, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + #~ 'srt') + #~ ) + #~ elif not subtitle['isForcedNarrative'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + #~ wvdl_sts.append( + #~ SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + #~ 'srt') + #~ ) + #~ else: + + #~ if not subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + #~ wvdl_sts.append( + #~ SubtitleTrack(i, subtitle['language'], subtitle['language'], True, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + #~ 'srt') + #~ ) + #~ elif not subtitle['isForcedNarrative'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + #~ wvdl_sts.append( + #~ SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))), + #~ 'srt') + #~ ) + + + #SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(subtitle['downloadables'][0]['urls'].values())), + #(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()[0]) + + #if 'German [Original]' in audio_languages: + # if subtitle['isForcedNarrative'] and subtitle['language'] == 'de' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + # wvdl_sts.append(SubtitleTrack(i, 'Forced', subtitle['language'], True, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()))),'srt')) + + + print(wvdl_sts) + + return True, [wvdl_vt, wvdl_ats, wvdl_sts, init_data_b64, cert_data_b64, device] + #, cert_data_b64 + + + def get_license(self, challenge, session_id): + + + + #print(data) + + id = int(time.time() * 10000) + self.logger.info("doing license request") + #self.logger.debug(challenge) + #.decode('latin-1'), + #'challengeBase64': base64.b64encode(challenge).decode('utf-8'), + #challenge1 = "CAESwQsKhgsIARLrCQquAggCEhAZj62gkJOXXXaMFkjqJD0tGNqb5MsFIo4CMIIBCgKCAQEA5ErxleIO2jsTG/3iGdvRLuL/EU73oLS+dGCvrSXynYRgOCo8uXkrIgoPZ0kCWK3JIcoUezix7w8yC2W5AmbyJ/af9Nq1Tyj8lMAIj14RWioXCAOxo+nH0wcz3lXQ9xdnLDCyO32Q2ieSR6ztFfn7f3U0FqOMkXloUKQhGTeqskuIz1PS8oIPVdgLQuASseQfSF8joOo4el64pAu70nGq0mxQhPWqxbVmSmwK6ll1hERLwRqeWaeWvWl+BsmPBATzvvCzavyP/INLd0jk25tYwB8fdskUTGa4EsEy1/m1jbYHKYV0KyPJ4HhceITPeRc7yEfLurwfsZxB3mcjxP9PCQIDAQABKOI7EoACgLrYCAjdgUp4LCRVy8bDxl/UL2YW91D7VTCMOmCpfRYShnBSgNJ7Lyl/ZPWwmo0Um4kbt3/j0gHh6c0w8S2mFE/cE9J9O4L7ud4YgdDInh6LRzvlJ0XGt6c8uxY05Cp85C+VLp7HW9WIGL4S3MhT5jQkfPSOiKCNEC5gtaUmFdrNNMvXUH3OSyX68r+IXs3eBsyBV1mSdJYfFqHyB8zWAX4RWghgEhWVL8TQ2o4Ahji7vSvbrZydZsSA8mswIvfpL3AN+iD+Dc9090DObj5hNIyBA9vEIbCNENPpTLSvBb1eaH7XQG7Z2SvPofDBO8h8RD5ewQfRF/kgidgkhVT2Uhq0BQquAggBEhBTPD046AWb9VpLdNIONjAuGPyC5MsFIo4CMIIBCgKCAQEAwsB00VQL7FwCYFJ3VD7Ryj1sWtAIE4fd3B7SoLtxnZyquZUBqPNMSw3dBGACTXX56o/GO/7swFvgUlBcHuZmYxlR+fSgPZXsdqw9XsHQeQcWss+N3IwNDSKBD3hpFEEYNu4t1ZEAxoSsEr5WPFfeqgpfag6MqaRVmkD0bmGi3yCjvtg0tMwFQf2BOAAha/gTZ7N0KxFrIDcX8GUQiUUKI4l/4cvJwMOXDVNPXThvJk8GI2tpikMfApPwD+tCb6R6EfSeYt9rY0d5b2xRf5n6jx0TfzNsMz/MLxu5B9EGquvTkCWt6pJTi3uYrRG2ri7NqtGzhqPJ7VnFGW9CGJw54QIDAQABKOI7EoADcR7dmMcXcyCMLxGbm71P7EI4BmVShv3wUuLRTNDFFbSp8RhCLCXCxQnh+Gx4AnFewHTCGxqVzLfEukL5YG/sZCyNXxmjBjRqXIABumjUUZjTNjMHus6g8h1dMmQHc7e8Twi7TeYk7XLdmzB9OZZ0VC+sSmoWyh5M+psdzOTiGmHtjFVwiKpPbX6ceaqgi/XMDk3wz/V6TgfjbLJgn4aCRFXA7/5ow9Cez/pFygkK9+/DkIgC2fo4uQ9uLWnuhs8cm46yb87+y8wcrEETXuvsIS90pnjpvc094UzuY6T4e0ACql+zf/P0Cqdu+ZEZTjQpXuVgSZpdDfNoG6Z9EMlP6yz5D1uTEyCyvsYzIA1cFwE69rcUCH6EJ4+LYf2pl+9cmXUKbiBeUrCAfdK82ih+xaEYsTNBI1biUd1WPy0kzOVCA/4HeN7XfmDsAa/4XGod2IxDXXjWcLKPNllv6RGYIlvMKcDSquElyS9kVKr12Zz7+dvh0zjq9R2Y5xsSN7VUGhsKEWFyY2hpdGVjdHVyZV9uYW1lEgZ4ODYtNjQaFgoMY29tcGFueV9uYW1lEgZHb29nbGUaFwoKbW9kZWxfbmFtZRIJQ2hyb21lQ0RNGhgKDXBsYXRmb3JtX25hbWUSB1dpbmRvd3MaIgoUd2lkZXZpbmVfY2RtX3ZlcnNpb24SCjEuNC45LjEwODgyCAgAEAAYASABEiwKKgoUCAESEAAAAAAFJh6iAAAAAAAAAAAQARoQ79lOuHmSjMeIDZTu48RFRhgBIOnf8uYFMBUagAJsriOJoOjvff7tOCzEnTIgzwO0nmyDwzaWFnwQqW8e1W8m3UQG1YpRsq5Py3rzKD8VbzktMaFUZbZe0vn8Acp4so+NKC39hGvOIQXbSUz4g6bO5lntmqJnRoTMur9eDL0T48eFrTGymnbZ7Vf0I27Baizj3hv2KSP/LdPRbyOLPdobh3R9CfeS3IPzu/YHfny4L8w10XErzPh0dq6CkVxCEwTk6ikb6V2gxlpgyNyJozLHDunfbaqKyvsS7K0z63jOz1LzPmo0Gf0H01kA6JDBt1cDJPQ4V2uN5PfHhVIRY39d6irLREl3u9V4L0v72vWHV+ffaIF6V6//BFGd3QAs" + + #self.logger.debug("challenge - {}".format(base64.b64encode(challenge))) + + license_request_data = { + #'method': 'license', + #'licenseType': 'STANDARD', + #'clientVersion': '4.0004.899.011', + #'uiVersion': 'akira', + #'languages': ['en-US'], + #'playbackContextId': self.playbackContextId, + #'drmContextIds': [self.drmContextId], + #'challenges': [{ + # 'dataBase64': base64.b64encode(challenge).decode('utf-8'), + # 'sessionId': "14673889385265" + 'version': 2, + 'url': links_license, #data1['result']['links']['license']['href'], + 'id': id, + 'esn': self.client_config.config['esn'], + 'languages': ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.511.011', + 'params': [{ + 'sessionId': session_id, + 'clientTime': int(id / 10000), + 'challengeBase64': base64.b64encode(challenge).decode('utf-8'), + 'xid': int(id + 1610) + }], + #base64.b64encode(challenge).decode('utf-8') + #self.client_config.config['esn'] + #'clientTime': int(time.time()), + #'clientTime': int(id / 10000), + #'sessionId': '14673889385265', + #'clientTime': int(id / 10000), + #'xid': int((int(time.time()) + 0.1612) * 1000) + 'echo': 'sessionId' + } + #license_request_data = str(license_request_data) + request_data = self.__generate_msl_request_data_lic(license_request_data) + + + resp = self.session.post(nf_cfg.LICENSE_ENDPOINT, request_data, headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, verify=False) + + """ + try: + # If is valid json the request for the licnese failed + resp.json() + self.logger.debug('Error getting license: '+resp.text) + exit(1) + except ValueError: + # json() failed so we have a chunked json response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads']) + self.logger.debug(data) + #if data['success'] is True: + if 'licenseResponseBase64' in data[0]: + #return data['result']['licenses'][0]['data'] + #return response['result'][0]['licenseResponseBase64'] + return data[0]['licenseResponseBase64'] + else: + self.logger.debug('Error getting license: ' + json.dumps(data)) + exit(1) + """ + # json() failed so we have a chunked json response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads']) + self.logger.debug(data) + + fobj = open("license.json", "w") + playlist = str(data) + fobj.write(playlist) + fobj.close() + + #print(data['result'][0]['licenseResponseBase64']) + + + return data['result'][0]['licenseResponseBase64'] + + #if data['success'] is True: + #data[0] + #if 'licenseResponseBase64' in data: + #return data['result']['licenses'][0]['data'] + #return response['result'][0]['licenseResponseBase64'] + #return data['links']['releaseLicense']['href'] + # return data['licenseResponseBase64'] + + + def __get_base_url(self, urls): + for key in urls: + return urls[key] + + def __decrypt_payload_chunk(self, payloadchunks): + decrypted_payload = '' + for chunk in payloadchunks: + payloadchunk = json.loads(chunk) + try: + encryption_envelope = str(bytes(payloadchunk['payload'], encoding="utf-8").decode('utf8')) + except TypeError: + encryption_envelope = payloadchunk['payload'] + # Decrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['iv'])) + plaintext = cipher.decrypt(base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['ciphertext'])) + # unpad the plaintext + plaintext = json.loads((Padding.unpad(plaintext, 16))) + data = plaintext['data'] + + # uncompress data if compressed + data = base64.standard_b64decode(data) + #if plaintext['compressionalgo'] == 'GZIP': + # data = zlib.decompress(base64.standard_b64decode(data), 16 + zlib.MAX_WBITS) + #else: + # data = base64.standard_b64decode(data) + + decrypted_payload += data.decode('utf-8') + #decrypted_payload = json.loads(decrypted_payload)[1]['payload']['data'] + #decrypted_payload = base64.standard_b64decode(decrypted_payload) + #return json.loads(decrypted_payload) + decrypted_payload = json.loads(decrypted_payload) + return decrypted_payload + + def __parse_chunked_msl_response(self, message): + header = message.split('}}')[0] + '}}' + payloads = re.split(',\"signature\":\"[0-9A-Za-z=/+]+\"}', message.split('}}')[1]) + payloads = [x + '}' for x in payloads][:-1] + + return { + 'header': header, + 'payloads': payloads + } + + def __generate_msl_request_data(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(header_encryption_envelope).decode('utf-8'), + 'mastertoken': self.mastertoken, + } + # Serialize the given Data + #serialized_data = json.dumps(data) + #serialized_data = serialized_data.replace('"', '\\"') + #serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-13","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + #compressed_data = self.__compress_data(serialized_data) + + + data1 = json.dumps(data) + print(data1) + data1 = data1.encode('utf-8') + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + #"data": compressed_data.decode('utf-8'), + #"compressionalgo": "GZIP", + "data": (base64.standard_b64encode(data1)).decode('utf-8'), + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(first_payload_encryption_envelope).decode('utf-8'), + } + request_data = json.dumps(header) + json.dumps(first_payload_chunk) + return request_data + + + def __generate_msl_request_data_lic(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(header_encryption_envelope).decode('utf-8'), + 'mastertoken': self.mastertoken, + } + # Serialize the given Data + #serialized_data = json.dumps(data) + #serialized_data = serialized_data.replace('"', '\\"') + #serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-13","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + #compressed_data = self.__compress_data(serialized_data) + + + print(data) + #print('\n') + + #data1 = json.dumps(data) + #print(data1) + #data1 = data1.encode('utf-8') + + + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + #"data": compressed_data.decode('utf-8'), + #"compressionalgo": "GZIP", + #"data": (base64.standard_b64encode(data1)).decode('utf-8'), + "data": base64.standard_b64encode(json.dumps(data).encode('utf-8')).decode('utf-8'), + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(first_payload_encryption_envelope).decode('utf-8'), + } + request_data = json.dumps(header) + json.dumps(first_payload_chunk) + + return request_data + + def __compress_data(self, data): + # GZIP THE DATA + out = BytesIO() + with gzip.GzipFile(fileobj=out, mode="w") as f: + f.write(data.encode('utf-8')) + return base64.standard_b64encode(out.getvalue()) + + def parseCookieFile(self, cookiefile): + """Parse a cookies.txt file and return a dictionary of key value pairs compatible with requests.""" + cookies = {} + with open (cookiefile, 'r') as fp: + for line in fp: + if not re.match(r'^\#', line): + lineFields = line.strip().split('\t') + cookies[lineFields[5]] = lineFields[6] + return cookies + + def __generate_msl_header(self, is_handshake=False, is_key_request=False, compressionalgo="GZIP", encrypt=True): + """ + Function that generates a MSL header dict + :return: The base64 encoded JSON String of the header + """ + self.current_message_id = self.rndm.randint(0, pow(2, 52)) + + header_data = { + 'sender': self.client_config.config['esn'], + 'handshake': is_handshake, + 'nonreplayable': False, + 'capabilities': { + 'languages': ["en-US"] + #'languages': ["en-US"], + #'compressionalgos': [], + #'encoderformats' : ['JSON'], + }, + 'recipient': 'Netflix', + 'renewable': True, + 'messageid': self.current_message_id, + 'timestamp': time.time() + } + + # Add compression algo if not empty + #if compressionalgo is not "": + # header_data['capabilities']['compressionalgos'].append(compressionalgo) + + # If this is a keyrequest act diffrent then other requests + # If this is a keyrequest act diffrent then other requests + if is_key_request: + if not self.wv_keyexchange: + public_key = base64.standard_b64encode(self.rsa_key.publickey().exportKey(format='DER')).decode('utf-8') + header_data['keyrequestdata'] = [{ + 'scheme': 'ASYMMETRIC_WRAPPED', + 'keydata': { + 'publickey': public_key, + 'mechanism': 'JWK_RSA', + 'keypairid': 'superKeyPair' + } + }] + else: + self.cdm_session = self.cdm.open_session(None, + deviceconfig.DeviceConfig(self.client_config.config['wv_device']), + b'\x0A\x7A\x00\x6C\x38\x2B', # raw + True) # persist + # should a client cert be set? most likely nonreplayable + wv_request = base64.b64encode(self.cdm.get_license_request(self.cdm_session)).decode("utf-8") + + header_data['keyrequestdata'] = [{ + 'scheme': 'WIDEVINE', + 'keydata': {'keyrequest': wv_request} + }] + else: + if 'usertoken' in self.tokens: + pass + else: + # Auth via email and password + header_data['userauthdata'] = { + 'scheme': 'EMAIL_PASSWORD', + 'authdata': { + 'email': self.client_config.config['username'], + 'password': self.client_config.config['password'] + } + } + return json.dumps(header_data) + + def __encrypt(self, plaintext): + """ + Encrypt the given Plaintext with the encryption key + :param plaintext: + :return: Serialized JSON String of the encryption Envelope + """ + iv = get_random_bytes(16) + encryption_envelope = { + 'ciphertext': '', + 'keyid': self.client_config.config['esn'] + '_' + str(self.sequence_number), + 'sha256': 'AA==', + 'iv': base64.standard_b64encode(iv).decode('utf-8') + } + # Padd the plaintext + plaintext = Padding.pad(plaintext.encode('utf-8'), 16) + # Encrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv) + ciphertext = cipher.encrypt(plaintext) + encryption_envelope['ciphertext'] = base64.standard_b64encode(ciphertext).decode('utf-8') + return json.dumps(encryption_envelope) + + def __sign(self, text): + """ + Calculates the HMAC signature for the given text with the current sign key and SHA256 + :param text: + :return: Base64 encoded signature + """ + signature = HMAC.new(self.sign_key, text.encode('utf-8'), SHA256).digest() + return base64.standard_b64encode(signature) + + def __perform_key_handshake(self): + header = self.__generate_msl_header(is_key_request=True, is_handshake=True, compressionalgo="", encrypt=False) + request = { + 'entityauthdata': { + 'scheme': 'NONE', + 'authdata': { + 'identity': self.client_config.config['esn'] + } + }, + 'headerdata': base64.standard_b64encode(header.encode('utf-8')).decode('utf-8'), + 'signature': '', + } + self.logger.debug('Key Handshake Request:') + self.logger.debug(json.dumps(request)) + + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, json.dumps(request, sort_keys=True), headers={'User-Agent': 'Gibbon/2018.1.6.3/2018.1.6.3: Netflix/2018.1.6.3 (DEVTYPE=NFANDROID2-PRV-FIRETVSTICK2016; CERTVER=0)'}, proxies=self.client_config.get_proxies()) + if resp.status_code == 200: + resp = resp.json() + if 'errordata' in resp: + self.logger.debug('Key Exchange failed') + self.logger.debug(base64.standard_b64decode(resp['errordata'])) + return False + self.logger.debug(resp) + self.logger.debug('Key Exchange Sucessful') + self.__parse_crypto_keys(json.JSONDecoder().decode(base64.standard_b64decode(resp['headerdata']).decode('utf-8'))) + else: + self.logger.debug('Key Exchange failed') + self.logger.debug(resp.text) + + def __parse_crypto_keys(self, headerdata): + keyresponsedata = headerdata['keyresponsedata'] + self.__set_master_token(keyresponsedata['mastertoken']) + self.logger.debug("response headerdata: %s" % headerdata) + #self.__set_userid_token(headerdata['useridtoken']) + if self.wv_keyexchange: + expected_scheme = 'WIDEVINE' + else: + expected_scheme = 'ASYMMETRIC_WRAPPED' + + scheme = keyresponsedata['scheme'] + + if scheme != expected_scheme: + self.logger.debug('Key Exchange failed:') + self.logger.debug('Unexpected scheme in response, expected %s, got %s' % (expected_scheme, scheme)) + return False + + keydata = keyresponsedata['keydata'] + + if self.wv_keyexchange: + self.__process_wv_keydata(keydata) + else: + self.__parse_rsa_wrapped_crypto_keys(keydata) + + self.__save_msl_data() + self.handshake_performed = True + + def __process_wv_keydata(self, keydata): + wv_response_b64 = keydata['cdmkeyresponse'] # pass as b64 + encryptionkeyid = base64.standard_b64decode(keydata['encryptionkeyid']) + hmackeyid = base64.standard_b64decode(keydata['hmackeyid']) + self.cdm.provide_license(self.cdm_session, wv_response_b64) + keys = self.cdm.get_keys(self.cdm_session) + self.logger.info('wv key exchange: obtained wv key exchange keys %s' % keys) + # might be better not to hardcode wv proto field names + self.encryption_key = self.__find_wv_key(encryptionkeyid, keys, ["AllowEncrypt", "AllowDecrypt"]) + self.sign_key = self.__find_wv_key(hmackeyid, keys, ["AllowSign", "AllowSignatureVerify"]) + + + # will fail if wrong permission or type + def __find_wv_key(self, kid, keys, permissions): + for key in keys: + if key.kid != kid: + continue + if key.type != "OPERATOR_SESSION": + self.logger.debug("wv key exchange: Wrong key type (not operator session) key %s" % key) + continue + + if not set(permissions) <= set(key.permissions): + self.logger.debug("wv key exchange: Incorrect permissions, key %s, needed perms %s" % (key, permissions)) + continue + return key.key + + return None + + def __parse_rsa_wrapped_crypto_keys(self, keydata): + # Init Decryption + encrypted_encryption_key = base64.standard_b64decode(keydata['encryptionkey']) + encrypted_sign_key = base64.standard_b64decode(keydata['hmackey']) + cipher_rsa = PKCS1_OAEP.new(self.rsa_key) + + # Decrypt encryption key + encryption_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_encryption_key).decode('utf-8')) + self.encryption_key = base64key_decode(encryption_key_data['k']) + + # Decrypt sign key + sign_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_sign_key).decode('utf-8')) + self.sign_key = base64key_decode(sign_key_data['k']) + + def __load_msl_data(self): + msl_data = json.JSONDecoder().decode( + self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage']).decode('utf-8')) + # Check expire date of the token + master_token = json.JSONDecoder().decode( + base64.standard_b64decode(msl_data['tokens']['mastertoken']['tokendata']).decode('utf-8')) + valid_until = datetime.utcfromtimestamp(int(master_token['expiration'])) + present = datetime.now() + difference = valid_until - present + difference = difference.total_seconds() / 60 / 60 + # If token expires in less then 10 hours or is expires renew it + if difference < 10: + self.__load_rsa_keys() + self.__perform_key_handshake() + return + + self.__set_master_token(msl_data['tokens']['mastertoken']) + #self.__set_userid_token(msl_data['tokens']['useridtoken']) + self.encryption_key = base64.standard_b64decode(msl_data['encryption_key']) + self.sign_key = base64.standard_b64decode(msl_data['sign_key']) + + def __save_msl_data(self): + """ + Saves the keys and tokens in json file + :return: + """ + data = { + "encryption_key": base64.standard_b64encode(self.encryption_key).decode('utf-8'), + 'sign_key': base64.standard_b64encode(self.sign_key).decode('utf-8'), + 'tokens': { + 'mastertoken': self.mastertoken, + #'useridtoken': self.useridtoken, + } + } + serialized_data = json.JSONEncoder().encode(data) + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage'], serialized_data.encode('utf-8')) + + def __set_master_token(self, master_token): + self.mastertoken = master_token + self.sequence_number = json.JSONDecoder().decode(base64.standard_b64decode(master_token['tokendata']).decode('utf-8'))[ + 'sequencenumber'] + + def __set_userid_token(self, userid_token): + self.useridtoken = userid_token + + def __load_rsa_keys(self): + loaded_key = self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key']) + self.rsa_key = RSA.importKey(loaded_key) + + def __save_rsa_keys(self): + self.logger.debug('Save RSA Keys') + # Get the DER Base64 of the keys + encrypted_key = self.rsa_key.exportKey() + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key'], encrypted_key) + + @staticmethod + def file_exists(msl_data_path, filename): + """ + Checks if a given file exists + :param filename: The filename + :return: True if so + """ + return os.path.isfile(os.path.join(msl_data_path, filename)) + + @staticmethod + def save_file(msl_data_path, filename, content): + """ + Saves the given content under given filename + :param filename: The filename + :param content: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'wb') as file_: + file_.write(content) + file_.flush() + file_.close() + + @staticmethod + def load_file(msl_data_path, filename): + """ + Loads the content of a given filename + :param filename: The file to load + :return: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'rb') as file_: + file_content = file_.read() + file_.close() + return file_content + + + def get_track_download(self, track): + return self.session.get(track.url, stream=True, proxies=self.client_config.get_proxies()) + + def get_subtitle_download(self, track): + + + + try: + req = requests.get(track.url) + req.encoding = 'utf-8' + except: + while True: + try: + req = requests.get(track.url) + req.encoding = 'utf-8' + return req + except: + continue + return req + + + + + def get_wvconfig_options(self): + return {'server_cert_required': True, 'pssh_header': True} + + def needs_ffmpeg(self): + return True + + def finagle_subs(self, subtitles): + return subs.to_srt(subtitles) + diff --git a/pywidevine/clients/netflix/client1.py b/pywidevine/clients/netflix/client1.py new file mode 100644 index 0000000..93bc27e --- /dev/null +++ b/pywidevine/clients/netflix/client1.py @@ -0,0 +1,749 @@ +import base64 +from datetime import datetime +import gzip +import zlib +import json +import logging +from io import BytesIO +import random +import time +import os +import re + +import requests +from Cryptodome.Cipher import AES +from Cryptodome.Cipher import PKCS1_OAEP +from Cryptodome.Hash import HMAC, SHA256 +from Cryptodome.PublicKey import RSA +from Cryptodome.Random import get_random_bytes +from Cryptodome.Util import Padding + +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg +import pywidevine.clients.netflix.config as nf_cfg +import pywidevine.clients.netflix.subs as subs +from pywidevine.downloader.tracks import VideoTrack, AudioTrack, SubtitleTrack + + +# keys are not padded properly +def base64key_decode(payload): + l = len(payload) % 4 + if l == 2: + payload += '==' + elif l == 3: + payload += '=' + elif l != 0: + raise ValueError('Invalid base64 string') + return base64.urlsafe_b64decode(payload.encode('utf-8')) + + +class NetflixClient(object): + def __init__(self, client_config): + self.logger = logging.getLogger(__name__) + self.logger.debug("creating NetflixClient object") + self.client_config = client_config + self.session = requests.Session() + self.current_message_id = 0 + self.rsa_key = None + self.encryption_key = None + self.sign_key = None + self.sequence_number = None + self.mastertoken = None + self.useridtoken = None + self.playbackContextId = None + self.drmContextId = None + self.tokens = [] + self.rndm = random.SystemRandom() + #self.cookies = self.cookie_login() + + def login(self): + self.logger.info("acquiring token & key for netflix api") + config_dict = self.client_config.config + + #if self.cookies is None: + # self.cookies = self.cookie_login() + + if self.file_exists(wvdl_cfg.COOKIES_FOLDER, config_dict['msl_storage']): + self.logger.info("old MSL data found, using") + self.__load_msl_data() + elif self.file_exists(wvdl_cfg.COOKIES_FOLDER, 'rsa_key.bin'): + self.logger.info('old RSA key found, using') + self.__load_rsa_keys() + self.__perform_key_handshake() + else: + self.logger.info('create new RSA Keys') + # Create new Key Pair and save + self.rsa_key = RSA.generate(2048) + self.__save_rsa_keys() + self.__perform_key_handshake() + + if self.encryption_key: + self.logger.info("negotiation successful, token & key acquired") + return True + else: + self.logger.error("failed to perform key handshake") + return False + + '''def cookie_login(self): + """Logs into netflix""" + config_dict = self.client_config.config + post_data = { + 'email': config_dict['username'], + 'password': config_dict['password'], + 'rememberMe': 'true', + 'mode': 'login', + 'action': 'loginAction', + 'withFields': 'email,password,rememberMe,nextPage,showPassword', + 'nextPage': '', + 'showPassword': '', + } + req = self.session.post('https://www.netflix.com/login', post_data) + return req.cookies''' + + def get_track_and_init_info(self,all_subs=False,only_subs=False): + config_dict = self.client_config.config + self.logger.info("video information") + manifest_request_data = { + 'method': 'manifest', + 'lookupType': 'PREPARE', + 'viewableIds': [self.client_config.viewable_id], + 'profiles': config_dict['profiles'], + 'drmSystem': 'widevine', + 'appId': '14673889385265', + 'sessionParams': { + 'pinCapableClient': False, + 'uiplaycontext': 'null' + }, + 'sessionId': '14673889385265', + 'trackId': 0, + 'flavor': 'PRE_FETCH', + 'secureUrls': True, + 'supportPreviewContent': True, + 'forceClearStreams': False, + 'languages': ['en-US'], + 'clientVersion': '4.0004.899.011', + 'uiVersion': 'akira', + 'showAllSubDubTracks': all_subs + } + self.logger.debug("requesting manifest") + request_data = self.__generate_msl_request_data(manifest_request_data) + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, request_data, proxies=self.client_config.get_proxies()) + + data = {} + + + try: + # if the json() does not fail we have an error because the manifest response is a chuncked json response + resp.json() + self.logger.debug('Error getting Manifest: '+resp.text) + return False, None + except ValueError: + # json() failed so parse the chunked response + self.logger.debug('Got chunked Manifest Response: ' + resp.text) + resp = self.__parse_chunked_msl_response(resp.text) + #print(resp.text) + self.logger.debug('Parsed chunked Response: ' + json.dumps(resp)) + data = self.__decrypt_payload_chunk(resp['payloads']) + + try: + self.logger.debug("manifest json: %s" % data['result']['viewables'][0]) + self.playbackContextId = data['result']['viewables'][0]['playbackContextId'] + self.drmContextId = data['result']['viewables'][0]['drmContextId'] + except (KeyError, IndexError): + self.logger.error('No viewables found') + if 'errorDisplayMessage' in data['result']: + self.logger.error('MSL Error Message: {}'.format(data['result']['errorDisplayMessage'])) + return False, None + + self.logger.debug(data) + self.logger.debug("netflix cannot get title name from manifest") + subtitle_tracks_js = data['result']['viewables'][0]['textTracks'] + subtitle_tracks_filtered = [x for x in subtitle_tracks_js if "bcp47" in x] + + self.logger.info("found {} subtitle tracks".format(len(subtitle_tracks_filtered))) + for subtitle_track in subtitle_tracks_filtered: + self.logger.info( + "Name: {} bcp47: {} type: {}".format(subtitle_track['language'], subtitle_track['bcp47'], subtitle_track['trackType']) + ) + + if only_subs: + wvdl_sts = [] + for i, subtitle in enumerate(subtitle_tracks_filtered): + if not subtitle['isForced']: + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['bcp47'], True, next(iter(subtitle['downloadables'][0]['urls'].values())), + 'srt') + ) + return True, wvdl_sts + + video_tracks_js = data['result']['viewables'][0]['videoTracks'][0]['downloadables'] + + self.logger.info("found {} video tracks".format(len(video_tracks_js))) + for vid_id, video in enumerate(sorted(video_tracks_js, key= lambda v: int(v['bitrate']))): + self.logger.info( + "{} - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(vid_id, video['bitrate'], + video['contentProfile'], + video['size'], + video['width'], + video['height']) + ) + + audio_tracks_js = data['result']['viewables'][0]['audioTracks'] + audio_tracks_flattened = [] + + for audio_track in audio_tracks_js: + for downloadable in audio_track['downloadables']: + new_track = audio_track.copy() + new_track['downloadables'] = downloadable + audio_tracks_flattened.append(new_track) + + self.logger.info("found {} audio tracks".format(len(audio_tracks_flattened))) + for aud_id, audio_track in enumerate( + sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']))): + self.logger.info( + "{} = Bitrate: {} Profile: {} Channels: {} Language: {} Lang: {} Size: {}".format(aud_id, audio_track[ + 'downloadables']['bitrate'], + audio_track[ + 'downloadables'][ + 'contentProfile'], + audio_track[ + 'channels'], + audio_track[ + 'language'], + audio_track['bcp47'], + audio_track[ + 'downloadables'][ + 'size']) + ) + + + self.logger.info("selected tracks") + if config_dict['video_track'] is not None: + self.logger.debug("VIDEO_TRACK_ID ARGUMENT: {}".format(config_dict['video_track'])) + if config_dict['video_track'] >= len(video_tracks_js): + self.logger.error("selected video track does not exist") + return False, [] + video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']))[int(config_dict['video_track'])] + else: + video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']), reverse=True)[0] + self.logger.info("VIDEO - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(video_track['bitrate'], + video_track['contentProfile'], + video_track['size'], + video_track['width'], + video_track['height'])) + audio_tracks = [] + + if config_dict['audio_tracks'] != []: + self.logger.debug("AUDIO_TRACK_ID ARUGMENT: {}".format(config_dict['audio_tracks'])) + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate'])) + for t_id in config_dict['audio_tracks']: + audio_tracks.append(sorted_aud[int(t_id)]) + else: + selected_track = None + bitrate = 0 + channels = 0 + profile = None + default_audio_lang = data['result']['viewables'][0]['orderedAudioTracks'][0] + audio_lang_selectors = { + 'English': 'en', + 'French': 'fr', + 'German': 'de', + 'Italian': 'it', + 'Spanish': 'es', + 'Flemish': 'nl-BE', + 'Finnish': 'fi', + 'No Dialogue': 'zxx', + 'Czech': 'cs', + 'European Spanish': 'es-ES', + 'Japanese': 'ja', + 'Brazilian Portuguese': 'pt-BR', + 'Polish': 'pl', + 'Turkish': 'tr', + 'Mandarin': 'zh', + 'Cantonese': 'yue', + 'Arabic': 'ar', + 'Korean': 'ko', + 'Hebrew': 'he', + 'Norwegian': 'nb' + } + aud_profile_table = { + 'heaac-2-dash': 0, + 'ddplus-2.0-dash': 1, + 'ddplus-5.1-dash': 2, + 'dd-5.1-dash': 3 + } + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']), reverse=True) + + audio_selected = ['en'] + if config_dict['audio_language'] is not None: + audio_selected = config_dict['audio_language'] + + for audio_select in audio_selected: + for aud_track_sorted in sorted_aud: + if aud_track_sorted['bcp47'] == audio_select: + audio_tracks.append(aud_track_sorted) + break + + # if selected_track == None: + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + # if (bitrate < aud_track_sorted['downloadables']['bitrate']) and ( + # channels <= aud_track_sorted['channels']) and ( + # profile <= aud_profile_table[aud_track_sorted['downloadables']['contentProfile']]): + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + + # audio_tracks.append(selected_track) + # if selected_track == None: + # self.logger.error("netfix cannot auto select audio track, please specify at least one") + # return False, [] + for audio_track in audio_tracks: + self.logger.info("AUDIO - Bitrate: {} Profile: {} Channels: {} Language: {} Size: {}".format( + audio_track['downloadables']['bitrate'], + audio_track['downloadables']['contentProfile'], + audio_track['channels'], + audio_track['language'], + audio_track['downloadables']['size'])) + + if config_dict['subtitle_languages'] is not None: + self.logger.debug("SUBTITLE_LANGUAGE_ARGUMENT: {}".format(config_dict['subtitle_languages'])) + if 'all' in config_dict['subtitle_languages']: + subtitle_tracks = subtitle_tracks_filtered + else: + subtitle_tracks = [x for x in subtitle_tracks_filtered if + x['bcp47'] in config_dict['subtitle_languages']] + else: + subtitle_tracks = None + if subtitle_tracks: + for subtitle in subtitle_tracks: + self.logger.info("SUBTITLE - Name: {} bcp47: {}".format(subtitle['language'], subtitle['bcp47'])) + + init_data_b64 = data['result']['viewables'][0]['psshb64'][0] + + cert_data_b64 = data['result']['viewables'][0]['cert'] + + wvdl_vt = VideoTrack(True, video_track['size'], 0, next(iter(video_track['urls'].values())), + video_track['contentProfile'], video_track['bitrate'], + video_track['width'], video_track['height']) + + wvdl_ats = [] + audio_languages = [] + + + for id, audio_track in enumerate(audio_tracks): + audio_languages.append(audio_track['bcp47']) + wvdl_ats.append( + AudioTrack(False, audio_track['downloadables']['size'], id, next(iter(audio_track['downloadables']['urls'].values())), + audio_track['downloadables']['contentProfile'], audio_track['downloadables']['bitrate'], audio_track['language']) + ) + + wvdl_sts = [] + use_captions = { 'en': True } + if subtitle_tracks: + for track in subtitle_tracks: + use_captions.update({track['bcp47']: True}) + for track in subtitle_tracks: + if track['bcp47'] == 'en' and track['trackType'] == "SUBTITLES" and not track['isForced']: + use_captions.update({track['bcp47']:False}) + for i, subtitle in enumerate(subtitle_tracks): + if 'en' in audio_languages: + if subtitle['isForced'] and subtitle['bcp47'] == 'en' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['bcp47']] == True): + wvdl_sts.append( + SubtitleTrack(i, 'Forced', subtitle['bcp47'], True, next(iter(subtitle['downloadables'][0]['urls'].values())), + 'srt') + ) + elif not subtitle['isForced'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['bcp47']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['bcp47'], False, next(iter(subtitle['downloadables'][0]['urls'].values())), + 'srt') + ) + else: + if not subtitle['isForced'] and subtitle['bcp47'] == 'en' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['bcp47']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['bcp47'], True, next(iter(subtitle['downloadables'][0]['urls'].values())), + 'srt') + ) + elif not subtitle['isForced'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['bcp47']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['bcp47'], False, next(iter(subtitle['downloadables'][0]['urls'].values())), + 'srt') + ) + + return True, [wvdl_vt, wvdl_ats, wvdl_sts, init_data_b64, cert_data_b64] + + + def get_license(self, challenge): + # + self.logger.info("doing license request") + self.logger.debug("challenge - {}".format(base64.b64encode(challenge))) + license_request_data = { + 'method': 'license', + 'licenseType': 'STANDARD', + 'clientVersion': '4.0004.899.011', + 'uiVersion': 'akira', + 'languages': ['en-US'], + 'playbackContextId': self.playbackContextId, + 'drmContextIds': [self.drmContextId], + 'challenges': [{ + 'dataBase64': base64.b64encode(challenge).decode('utf-8'), + 'sessionId': "14673889385265" + }], + 'clientTime': int(time.time()), + 'xid': int((int(time.time()) + 0.1612) * 1000) + + } + request_data = self.__generate_msl_request_data(license_request_data) + + resp = self.session.post(nf_cfg.LICENSE_ENDPOINT, request_data, proxies=self.client_config.get_proxies()) + + try: + # If is valid json the request for the licnese failed + resp.json() + self.logger.debug('Error getting license: '+resp.text) + exit(1) + except ValueError: + # json() failed so we have a chunked json response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads']) + if data['success'] is True: + return data['result']['licenses'][0]['data'] + else: + self.logger.debug('Error getting license: ' + json.dumps(data)) + exit(1) + + + def __get_base_url(self, urls): + for key in urls: + return urls[key] + + def __decrypt_payload_chunk(self, payloadchunks): + decrypted_payload = '' + for chunk in payloadchunks: + payloadchunk = json.loads(chunk) + try: + encryption_envelope = str(bytes(payloadchunk['payload'], encoding="utf-8").decode('utf8')) + except TypeError: + encryption_envelope = payloadchunk['payload'] + # Decrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['iv'])) + plaintext = cipher.decrypt(base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['ciphertext'])) + # unpad the plaintext + plaintext = json.loads((Padding.unpad(plaintext, 16))) + data = plaintext['data'] + + # uncompress data if compressed + if plaintext['compressionalgo'] == 'GZIP': + data = zlib.decompress(base64.standard_b64decode(data), 16 + zlib.MAX_WBITS) + else: + data = base64.standard_b64decode(data) + + decrypted_payload += data.decode('utf-8') + decrypted_payload = json.loads(decrypted_payload)[1]['payload']['data'] + decrypted_payload = base64.standard_b64decode(decrypted_payload) + return json.loads(decrypted_payload) + + def __parse_chunked_msl_response(self, message): + header = message.split('}}')[0] + '}}' + payloads = re.split(',\"signature\":\"[0-9A-Za-z=/+]+\"}', message.split('}}')[1]) + payloads = [x + '}' for x in payloads][:-1] + + return { + 'header': header, + 'payloads': payloads + } + + def __generate_msl_request_data(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(header_encryption_envelope).decode('utf-8'), + 'mastertoken': self.mastertoken, + } + # Serialize the given Data + serialized_data = json.dumps(data) + serialized_data = serialized_data.replace('"', '\\"') + serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-13","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + compressed_data = self.__compress_data(serialized_data) + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + "data": compressed_data.decode('utf-8'), + "compressionalgo": "GZIP", + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(first_payload_encryption_envelope).decode('utf-8'), + } + request_data = json.dumps(header) + json.dumps(first_payload_chunk) + return request_data + + def __compress_data(self, data): + # GZIP THE DATA + out = BytesIO() + with gzip.GzipFile(fileobj=out, mode="w") as f: + f.write(data.encode('utf-8')) + return base64.standard_b64encode(out.getvalue()) + + def __generate_msl_header(self, is_handshake=False, is_key_request=False, compressionalgo="GZIP", encrypt=True): + """ + Function that generates a MSL header dict + :return: The base64 encoded JSON String of the header + """ + self.current_message_id = self.rndm.randint(0, pow(2, 52)) + + header_data = { + 'sender': self.client_config.config['esn'], + 'handshake': is_handshake, + 'nonreplayable': False, + 'capabilities': { + 'languages': ["en-US"], + 'compressionalgos': [], + 'encoderformats' : ['JSON'], + }, + 'recipient': 'Netflix', + 'renewable': True, + 'messageid': self.current_message_id, + 'timestamp': 1467733923, + } + + # Add compression algo if not empty + if compressionalgo is not "": + header_data['capabilities']['compressionalgos'].append(compressionalgo) + + # If this is a keyrequest act diffrent then other requests + if is_key_request: + public_key = base64.standard_b64encode(self.rsa_key.publickey().exportKey(format='DER')).decode('utf-8') + header_data['keyrequestdata'] = [{ + 'scheme': 'ASYMMETRIC_WRAPPED', + 'keydata': { + 'publickey': public_key, + 'mechanism': 'JWK_RSA', + 'keypairid': 'superKeyPair' + } + }] + #header_data['userauthdata'] = { + # 'scheme' : 'NETFLIXID', + # 'authdata' : { + # 'netflixid' : self.cookies['NetflixId'], + # 'securenetflixid' : self.cookies['SecureNetflixId'], + # } + #} + #header_data['keyrequestdata'] = [{ + # 'scheme': 'WIDEVINE', + # 'keydata': { + # 'keyrequest':'CAESiQ0KxgwIARLrCQquAggCEhAlHgXTeVZWV5AbCt3IDiHsGIazwckFIo4CMIIBCgKCAQEAz2Cz+sq6JqPv1N6TwdFYyTjEvmAdUZjMNFTAX4vbMBe8adURCnePeAl8K67h7iWOQO5xxN4rfv49H3bX7lyo+kU/v34iTabu+wLSTj9Pl+hBpx5X+kX0arO+Mvy+bh32obug09Tjfg000SiA09+kyKf9q8Yitllfgzj0uUscotoSKIGIZPjHiI9Voboxi0ApSKh4lWfIvE7YuhDVJJt3pfuRHwQeXHOUSJj32pOLkinU3yVfmSf7ozd10NuqRrUQ7t/8ZmE6AeAc+XACAQku0W5iNwW4raqwG6oRGV5WXfr28NsM1j89kOgbHEf7Nr4tRc0Pbu+/7gp5ySP26snIPQIDAQABKMA0EoACWoSItadpIcGOtgWpC6VLOTliaVjBpHg2LnfQnag2XqmXbcZ457O4DfyRBX1YxQRVpwCSh5EM0kOrnI9AUUfZQplMVa0f+Qp04UKH5FIoUGeRND0I1Qn3/5uF2PXIG/xRjf8BoH+WqKhpWT+143wDml2ERW7otsXZdqHeZQNabwlFEjvttcrL3qKj+IDa4cXKRflbmt7SVjVo5cmSPRaVqgk7Mck+6haI4pgkkBMfdwpPBlvroM41zQO7qz3P8HkZjTI2OEBwnNFGZ4Di+mQsQExE3UkUUxwmUBH84ftRgnsdhRoaQ8roeZGO73u5KVRVUyDvpWjnKCCCcvx90H0Z5hq0BQquAggBEhASqgK+FxGhlxP70rVZ8RnzGMjgnbgFIo4CMIIBCgKCAQEAslO3gaTon+lSqGB33pfvFpVFUb2WITRegpbjA7u8iv+44xv53N0ZggOdJME14i460kOaYZ+PEDlaU10HlBqv5yn8Nk2tnwHs+1rY+AufTBuBWhKWaCg35YdGiCFm3/QHnBbtYqE1GqoCyHLmS7FUbj0iBJF6tOr7/qR4NW2/eRsfe89K/qNi73lP97JUQrZn8pKVZ8pijET+aTFFE+iZi7IQnuqFibGIAmzcrQLDbYLlgrrTdp/AxPsjUHgAE9GF3PnsVZfmbChaK+wV1fG5p/Ke0LLXvQRS5XpefD+3aH/tNWGfr+RDFeAwht/oFX0pOVHEZLTiXpxq/iE/SE3k9wIDAQABKMA0EoADsmVh9iHXpzmob8Wxy+GUAyfUHBOQG8TvlD/n6BiBz4F3lY1HiHQSJVNGTvboZZNkg0oI6o7mhh616Y/4RlfSiVGqHzRaGol4SFow82DZnyF4ozsUrJpi/FFMc5KpwSEE4N0GIMq4asbsbK5RXUrtaRpG8rH80tu50Ft4veei6bzwACvS9QrkFcL7zvby3DT9mHZtn46ytrGqmogftrT6FfvOUCdoyfizLBfQM0LY3zRUp5h03W7GhwueR0Jg/4g5XZKvA2LzQov9120qczOxP9RtE0PP1h/EnsXidfdYsbOP+IgYcBHHaqtVaFWPWKxt9+cPy/0gYYzfnpT5axotlo96aJm96arZnt5QxZUAASq/OwSzqgRojZqmB91tTwP7LOrFaNfwq4Icb29gSAN2nofl4WFZx/VSvXBB/alBlc8tOJxM0wzzKw5c2EFC2qRjuPsIDF6MJWaicUERdcDoO24JaRItXCeW0rv+PQSuwbU+oJOI9HWGmtcKU/1fYLABGhYKDGNvbXBhbnlfbmFtZRIGR29vZ2xlGhMKCm1vZGVsX25hbWUSBVBpeGVsGh4KEWFyY2hpdGVjdHVyZV9uYW1lEglhcm02NC12OGEaFwoLZGV2aWNlX25hbWUSCHNhaWxmaXNoGhgKDHByb2R1Y3RfbmFtZRIIc2FpbGZpc2gaTQoKYnVpbGRfaW5mbxI/Z29vZ2xlL3NhaWxmaXNoL3NhaWxmaXNoOjcuMS4xL05PRjI3Qy8zNjg3ODEwOnVzZXIvcmVsZWFzZS1rZXlzGi0KCWRldmljZV9pZBIgQUMzNzQzNDkyOTRCAAAAAAAAAAAAAAAAAAAAAAAAAAAaJgoUd2lkZXZpbmVfY2RtX3ZlcnNpb24SDnY0LjEuMC1hbmRyb2lkGiQKH29lbV9jcnlwdG9fc2VjdXJpdHlfcGF0Y2hfbGV2ZWwSATAyCBABIAQoCzABEi4KLAoGCnoAbDgrEAIaIEEzRTJEQUY3MjAxMkJBN0Q2QjAwMDAwMDAwMDAwMDAwGAEgisGQygUwFTjrqfChCRqAAjPrDb21SMpfIZsNZzpE97e4QU5R72I6KMCugWsKQmvbZqVWCSTmqMlqEKU48NyDLYaiqJ8VNaIfZgP+rsC4K8BYmGIgIx1TTYtai0yEnL89m07zZEH/QnOgM9BL+f6/wJ84cH1zS/rP1r6//dkrb80PnsLJowbdQ9N9DH3h/6g0vzh2RSzIP2eLGTxILbb06WJ1G/lgeXhy21JxIFFGUdgemTMfKZaSjgQO6f4SWhKv7t5jvIoD0BsqO3IT8afCapopMurW/YLSz3BkErgy4+0Lt22+t+gTkmtxiEgrq4cV7nCdRIiaNthuaxIkS2KSZkd3YKrkc/N3lifKnQEn9+o=', + # }, + #}] + else: + if 'usertoken' in self.tokens: + pass + else: + # Auth via email and password + header_data['userauthdata'] = { + 'scheme': 'EMAIL_PASSWORD', + 'authdata': { + 'email': self.client_config.config['username'], + 'password': self.client_config.config['password'] + } + } + return json.dumps(header_data) + + def __encrypt(self, plaintext): + """ + Encrypt the given Plaintext with the encryption key + :param plaintext: + :return: Serialized JSON String of the encryption Envelope + """ + iv = get_random_bytes(16) + encryption_envelope = { + 'ciphertext': '', + 'keyid': self.client_config.config['esn'] + '_' + str(self.sequence_number), + 'sha256': 'AA==', + 'iv': base64.standard_b64encode(iv).decode('utf-8') + } + # Padd the plaintext + plaintext = Padding.pad(plaintext.encode('utf-8'), 16) + # Encrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv) + ciphertext = cipher.encrypt(plaintext) + encryption_envelope['ciphertext'] = base64.standard_b64encode(ciphertext).decode('utf-8') + return json.dumps(encryption_envelope) + + def __sign(self, text): + """ + Calculates the HMAC signature for the given text with the current sign key and SHA256 + :param text: + :return: Base64 encoded signature + """ + signature = HMAC.new(self.sign_key, text.encode('utf-8'), SHA256).digest() + return base64.standard_b64encode(signature) + + def __perform_key_handshake(self): + header = self.__generate_msl_header(is_key_request=True, is_handshake=True, compressionalgo="", encrypt=False) + request = { + 'entityauthdata': { + 'scheme': 'NONE', + 'authdata': { + 'identity': self.client_config.config['esn'] + } + }, + 'headerdata': base64.standard_b64encode(header.encode('utf-8')).decode('utf-8'), + 'signature': '', + } + self.logger.debug('Key Handshake Request:') + self.logger.debug(json.dumps(request)) + + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, json.dumps(request, sort_keys=True), proxies=self.client_config.get_proxies()) + if resp.status_code == 200: + resp = resp.json() + if 'errordata' in resp: + self.logger.debug('Key Exchange failed') + self.logger.debug(base64.standard_b64decode(resp['errordata'])) + return False + self.logger.debug(resp) + self.logger.debug('Key Exchange Sucessful') + self.__parse_crypto_keys(json.JSONDecoder().decode(base64.standard_b64decode(resp['headerdata']).decode('utf-8'))) + else: + self.logger.debug('Key Exchange failed') + self.logger.debug(resp.text) + + def __parse_crypto_keys(self, headerdata): + self.__set_master_token(headerdata['keyresponsedata']['mastertoken']) + #self.__set_userid_token(headerdata['useridtoken']) + # Init Decryption + encrypted_encryption_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['encryptionkey']) + encrypted_sign_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['hmackey']) + cipher_rsa = PKCS1_OAEP.new(self.rsa_key) + + # Decrypt encryption key + encryption_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_encryption_key).decode('utf-8')) + self.encryption_key = base64key_decode(encryption_key_data['k']) + + # Decrypt sign key + sign_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_sign_key).decode('utf-8')) + self.sign_key = base64key_decode(sign_key_data['k']) + + self.__save_msl_data() + self.handshake_performed = True + + def __load_msl_data(self): + msl_data = json.JSONDecoder().decode( + self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage']).decode('utf-8')) + # Check expire date of the token + master_token = json.JSONDecoder().decode( + base64.standard_b64decode(msl_data['tokens']['mastertoken']['tokendata']).decode('utf-8')) + valid_until = datetime.utcfromtimestamp(int(master_token['expiration'])) + present = datetime.now() + difference = valid_until - present + difference = difference.total_seconds() / 60 / 60 + # If token expires in less then 10 hours or is expires renew it + if difference < 10: + self.__load_rsa_keys() + self.__perform_key_handshake() + return + + self.__set_master_token(msl_data['tokens']['mastertoken']) + #self.__set_userid_token(msl_data['tokens']['useridtoken']) + self.encryption_key = base64.standard_b64decode(msl_data['encryption_key']) + self.sign_key = base64.standard_b64decode(msl_data['sign_key']) + + def __save_msl_data(self): + """ + Saves the keys and tokens in json file + :return: + """ + data = { + "encryption_key": base64.standard_b64encode(self.encryption_key).decode('utf-8'), + 'sign_key': base64.standard_b64encode(self.sign_key).decode('utf-8'), + 'tokens': { + 'mastertoken': self.mastertoken, + #'useridtoken': self.useridtoken, + } + } + serialized_data = json.JSONEncoder().encode(data) + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage'], serialized_data.encode('utf-8')) + + def __set_master_token(self, master_token): + self.mastertoken = master_token + self.sequence_number = json.JSONDecoder().decode(base64.standard_b64decode(master_token['tokendata']).decode('utf-8'))[ + 'sequencenumber'] + + def __set_userid_token(self, userid_token): + self.useridtoken = userid_token + + def __load_rsa_keys(self): + loaded_key = self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key']) + self.rsa_key = RSA.importKey(loaded_key) + + def __save_rsa_keys(self): + self.logger.debug('Save RSA Keys') + # Get the DER Base64 of the keys + encrypted_key = self.rsa_key.exportKey() + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key'], encrypted_key) + + @staticmethod + def file_exists(msl_data_path, filename): + """ + Checks if a given file exists + :param filename: The filename + :return: True if so + """ + return os.path.isfile(os.path.join(msl_data_path, filename)) + + @staticmethod + def save_file(msl_data_path, filename, content): + """ + Saves the given content under given filename + :param filename: The filename + :param content: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'wb') as file_: + file_.write(content) + file_.flush() + file_.close() + + @staticmethod + def load_file(msl_data_path, filename): + """ + Loads the content of a given filename + :param filename: The file to load + :return: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'rb') as file_: + file_content = file_.read() + file_.close() + return file_content + + + def get_track_download(self, track): + return self.session.get(track.url, stream=True, proxies=self.client_config.get_proxies()) + + def get_subtitle_download(self, track): + try: + req = self.session.get(track.url, proxies=self.client_config.get_proxies()) + except: + while True: + try: + req = self.session.get(track.url, proxies=self.client_config.get_proxies()) + return req + except: + continue + return req + + + def get_wvconfig_options(self): + return {'server_cert_required': True, 'pssh_header': True} + + def needs_ffmpeg(self): + return True + + def finagle_subs(self, subtitles): + return subs.to_srt(subtitles) + diff --git a/pywidevine/clients/netflix/client3.py b/pywidevine/clients/netflix/client3.py new file mode 100644 index 0000000..9840a0a --- /dev/null +++ b/pywidevine/clients/netflix/client3.py @@ -0,0 +1,943 @@ +import base64 +from datetime import datetime +import gzip +import zlib +import json +import logging +from io import BytesIO +import random +import time +import os +import re +from itertools import islice + + +import requests +from Cryptodome.Cipher import AES +from Cryptodome.Cipher import PKCS1_OAEP +from Cryptodome.Hash import HMAC, SHA256 +from Cryptodome.PublicKey import RSA +from Cryptodome.Random import get_random_bytes +from Cryptodome.Util import Padding + +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg +import pywidevine.clients.netflix.config as nf_cfg +import pywidevine.clients.netflix.subs as subs +from pywidevine.downloader.tracks import VideoTrack, AudioTrack, SubtitleTrack + + +# keys are not padded properly +def base64key_decode(payload): + l = len(payload) % 4 + if l == 2: + payload += '==' + elif l == 3: + payload += '=' + elif l != 0: + raise ValueError('Invalid base64 string') + return base64.urlsafe_b64decode(payload.encode('utf-8')) + + +class NetflixClient(object): + def __init__(self, client_config): + self.logger = logging.getLogger(__name__) + self.logger.debug("creating NetflixClient object") + self.client_config = client_config + self.session = requests.Session() + self.current_message_id = 0 + self.rsa_key = None + self.encryption_key = None + self.sign_key = None + self.sequence_number = None + self.mastertoken = None + self.useridtoken = None + self.playbackContextId = None + self.drmContextId = None + self.tokens = [] + self.rndm = random.SystemRandom() + #self.cookies = self.cookie_login() + + def login(self): + self.logger.info("acquiring token & key for netflix api") + config_dict = self.client_config.config + + #if self.cookies is None: + # self.cookies = self.cookie_login() + + if self.file_exists(wvdl_cfg.COOKIES_FOLDER, config_dict['msl_storage']): + self.logger.info("old MSL data found, using") + self.__load_msl_data() + elif self.file_exists(wvdl_cfg.COOKIES_FOLDER, 'rsa_key.bin'): + self.logger.info('old RSA key found, using') + self.__load_rsa_keys() + self.__perform_key_handshake() + else: + self.logger.info('create new RSA Keys') + # Create new Key Pair and save + self.rsa_key = RSA.generate(2048) + self.__save_rsa_keys() + self.__perform_key_handshake() + + if self.encryption_key: + self.logger.info("negotiation successful, token & key acquired") + return True + else: + self.logger.error("failed to perform key handshake") + return False + + '''def cookie_login(self): + """Logs into netflix""" + config_dict = self.client_config.config + post_data = { + 'email': config_dict['username'], + 'password': config_dict['password'], + 'rememberMe': 'true', + 'mode': 'login', + 'action': 'loginAction', + 'withFields': 'email,password,rememberMe,nextPage,showPassword', + 'nextPage': '', + 'showPassword': '', + } + req = self.session.post('https://www.netflix.com/login', post_data) + return req.cookies''' + + def get_track_and_init_info(self,all_subs=False,only_subs=False): + config_dict = self.client_config.config + self.logger.info("video information") + id = int(time.time() * 10000) + """ + manifest_request_data = { + + 'method': 'manifest', + 'lookupType': 'PREPARE', + 'viewableIds': [self.client_config.viewable_id], + 'profiles': config_dict['profiles'], + 'drmSystem': 'widevine', + 'appId': '14673889385265', + 'sessionParams': { + 'pinCapableClient': False, + 'uiplaycontext': 'null' + }, + 'sessionId': '14673889385265', + 'trackId': 0, + 'flavor': 'PRE_FETCH', + 'secureUrls': True, + 'supportPreviewContent': True, + 'forceClearStreams': False, + 'languages': ['en-US'], + 'clientVersion': '6.0011.474.011', + 'uiVersion': 'shakti-v25d2fa21', + 'showAllSubDubTracks': all_subs + + } + """ + #'profiles': config_dict['profiles'], + #profiles = ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'playready-h264hpl30-dash', 'playready-h264hpl31-dash', 'playready-h264hpl40-dash', 'heaac-2-dash', 'dfxp-ls-sdh', 'simplesdh',] + #profiles = ['playready-h264mpl30-dash', 'playready-h264mpl31-dash', 'playready-h264mpl40-dash', 'playready-h264hpl30-dash', 'playready-h264hpl31-dash', 'playready-h264hpl40-dash', 'heaac-2-dash', 'BIF240', 'BIF320'] + + manifest_request_data = { + 'version': 2, + 'url': '/manifest', + 'id': id, + 'esn': self.client_config.config['esn'], + 'languages' : ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.474.011', + 'params': { + 'type': 'standard', + 'viewableId': [self.client_config.viewable_id], + 'profiles': config_dict['profiles'], + 'flavor': 'PRE_FETCH', + 'drmType': 'widevine', + 'drmVersion': 25, + 'usePsshBox': True, + 'isBranching': False, + 'useHttpsStreams': False, + 'imageSubtitleHeight': 1080, + 'uiVersion': 'shakti-vb45817f4', + 'clientVersion': '6.0011.511.011', + 'supportsPreReleasePin': True, + 'supportsWatermark': True, + 'showAllSubDubTracks': False, + 'titleSpecificData': {}, + 'videoOutputInfo': [{ + 'type': 'DigitalVideoOutputDescriptor', + 'outputType': 'unknown', + 'supportedHdcpVersions': [], + 'isHdcpEngaged': False + }], + 'preferAssistiveAudio': False, + 'isNonMember': False + } + } + self.logger.debug("requesting manifest") + request_data = self.__generate_msl_request_data(manifest_request_data) + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, request_data, proxies=self.client_config.get_proxies()) + self.logger.debug(manifest_request_data) + data = {} + + + try: + # if the json() does not fail we have an error because the manifest response is a chuncked json response + resp.json() + self.logger.debug('Error getting Manifest: '+resp.text) + return False, None + except ValueError: + # json() failed so parse the chunked response + global data1 + self.logger.debug('Got chunked Manifest Response: ' + resp.text) + resp = self.__parse_chunked_msl_response(resp.text) + #print(resp.text) + self.logger.debug('Parsed chunked Response: ' + json.dumps(resp)) + data = self.__decrypt_payload_chunk(resp['payloads']) + data1 = self.__decrypt_payload_chunk(resp['payloads']) + fobj = open("manifest.json", "w") + #fobj.write(str(data['result'])) + #data['result']['links']['license']['href'] + playlist = json.dumps(data) + fobj.write(playlist) + fobj.close() + self.logger.debug(data['result']) + #[0] + + try: + + #self.logger.debug("manifest json: %s" % data['result']['viewables'][0]) + #self.playbackContextId = data['result']['viewables'][0]['playbackContextId'] + #self.drmContextId = data['result']['viewables'][0]['drmContextId'] + self.logger.debug("manifest json: %s" % data['result']) + self.playbackContextId = data['result']['playbackContextId'] + self.drmContextId = data['result']['drmContextId'] + except (KeyError, IndexError): + self.logger.error('No viewables found') + if 'errorDisplayMessage' in data['result']: + self.logger.error('MSL Error Message: {}'.format(data['result']['errorDisplayMessage'])) + return False, None + + self.logger.debug(data) + self.logger.debug("netflix cannot get title name from manifest") + #subtitle_tracks_js = data['result']['viewables'][0]['textTracks'] + subtitle_tracks_js = data['result']['timedtexttracks'] + self.logger.debug(len(subtitle_tracks_js)) + subtitle_tracks_filtered = [x for x in subtitle_tracks_js if "language" in x] + subtitle_tracks_filtered = list(islice(subtitle_tracks_filtered, len(subtitle_tracks_js)-1)) + self.logger.debug(subtitle_tracks_filtered) + + self.logger.info("found {} subtitle tracks".format(len(subtitle_tracks_filtered))) + for subtitle_track in subtitle_tracks_filtered: + self.logger.info( + "Name: {} bcp47: {} type: {}".format(subtitle_track['language'], subtitle_track['language'], subtitle_track['trackType']) + ) + + if only_subs: + wvdl_sts = [] + for i, subtitle in enumerate(subtitle_tracks_filtered): + if not subtitle['isForcedNarrative']: + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], True, next(iter(list(subtitle['downloadables'][0]['urls'].values()))), + 'srt') + ) + return True, wvdl_sts + + #video_tracks_js = data['result']['viewables'][0]['videoTracks'][0]['downloadables'] + video_tracks_js = data['result']['video_tracks'][0]['streams'] + + self.logger.info("found {} video tracks".format(len(video_tracks_js))) + for vid_id, video in enumerate(sorted(video_tracks_js, key= lambda v: int(v['bitrate']))): + self.logger.info( + "{} - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(vid_id, video['bitrate'], + video['content_profile'], + video['size'], + video['res_w'], + video['res_h']) + ) + + audio_tracks_js = data['result']['audio_tracks'] + audio_tracks_flattened = [] + + for audio_track in audio_tracks_js: + for downloadable in audio_track['streams']: + new_track = audio_track.copy() + new_track['downloadables'] = downloadable + audio_tracks_flattened.append(new_track) + + self.logger.info("found {} audio tracks".format(len(audio_tracks_flattened))) + for aud_id, audio_track in enumerate( + sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']))): + self.logger.info( + "{} = Bitrate: {} Profile: {} Channels: {} Language: {} Lang: {} Size: {}".format(aud_id, audio_track[ + 'downloadables']['bitrate'], + audio_track[ + 'downloadables'][ + 'content_profile'], + audio_track[ + 'channels'], + audio_track[ + 'language'], + audio_track['language'], + audio_track[ + 'downloadables'][ + 'size']) + ) + + + self.logger.info("selected tracks") + if config_dict['video_track'] is not None: + self.logger.debug("VIDEO_TRACK_ID ARGUMENT: {}".format(config_dict['video_track'])) + if config_dict['video_track'] >= len(video_tracks_js): + self.logger.error("selected video track does not exist") + return False, [] + video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']))[int(config_dict['video_track'])] + else: + video_track = sorted(video_tracks_js, key= lambda v: int(v['bitrate']), reverse=True)[0] + self.logger.info("VIDEO - Bitrate: {} Profile: {} Size: {} Width: {} Height: {}".format(video_track['bitrate'], + video_track['content_profile'], + video_track['size'], + video_track['res_w'], + video_track['res_h'])) + audio_tracks = [] + + if config_dict['audio_tracks'] != []: + self.logger.debug("AUDIO_TRACK_ID ARUGMENT: {}".format(config_dict['audio_tracks'])) + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate'])) + for t_id in config_dict['audio_tracks']: + audio_tracks.append(sorted_aud[int(t_id)]) + else: + selected_track = None + bitrate = 0 + channels = 0 + profile = None + #default_audio_lang = data['result']['viewables'][0]['orderedAudioTracks'][0] + audio_lang_selectors = { + 'English': 'en', + 'French': 'fr', + 'German': 'de', + 'Italian': 'it', + 'Spanish': 'es', + 'Flemish': 'nl-BE', + 'Finnish': 'fi', + 'No Dialogue': 'zxx', + 'Czech': 'cs', + 'European Spanish': 'es-ES', + 'Japanese': 'ja', + 'Brazilian Portuguese': 'pt-BR', + 'Polish': 'pl', + 'Turkish': 'tr', + 'Mandarin': 'zh', + 'Cantonese': 'yue', + 'Arabic': 'ar', + 'Korean': 'ko', + 'Hebrew': 'he', + 'Norwegian': 'nb' + } + aud_profile_table = { + 'heaac-2-dash': 0, + 'ddplus-2.0-dash': 1, + 'ddplus-5.1-dash': 2, + 'dd-5.1-dash': 3 + } + sorted_aud = sorted(audio_tracks_flattened, key=lambda v: int(v['downloadables']['bitrate']), reverse=True) + + if video_track['res_h'] == 480: + sorted_aud = [a_track for a_track in sorted_aud if a_track['channels'] == '2.0'] + + audio_selected = ['en'] + if config_dict['audio_language'] is not None: + audio_selected = config_dict['audio_language'] + + for audio_select in audio_selected: + for aud_track_sorted in sorted_aud: + if aud_track_sorted['language'] == audio_select: + audio_tracks.append(aud_track_sorted) + break + + # if selected_track == None: + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + # if (bitrate < aud_track_sorted['downloadables']['bitrate']) and ( + # channels <= aud_track_sorted['channels']) and ( + # profile <= aud_profile_table[aud_track_sorted['downloadables']['contentProfile']]): + # selected_track = aud_track_sorted + # bitrate = aud_track_sorted['downloadables']['bitrate'] + # channels = aud_track_sorted['channels'] + # profile = aud_profile_table[aud_track_sorted['downloadables']['contentProfile']] + + # audio_tracks.append(selected_track) + # if selected_track == None: + # self.logger.error("netfix cannot auto select audio track, please specify at least one") + # return False, [] + for audio_track in audio_tracks: + self.logger.info("AUDIO - Bitrate: {} Profile: {} Channels: {} Language: {} Size: {}".format( + audio_track['downloadables']['bitrate'], + audio_track['downloadables']['content_profile'], + audio_track['channels'], + audio_track['language'], + audio_track['downloadables']['size'])) + + if config_dict['subtitle_languages'] is not None: + self.logger.debug("SUBTITLE_LANGUAGE_ARGUMENT: {}".format(config_dict['subtitle_languages'])) + if 'all' in config_dict['subtitle_languages']: + subtitle_tracks = subtitle_tracks_filtered + else: + subtitle_tracks = [x for x in subtitle_tracks_filtered if + x['language'] in config_dict['subtitle_languages']] + else: + subtitle_tracks = None + if subtitle_tracks: + for subtitle in subtitle_tracks: + self.logger.info("SUBTITLE - Name: {} bcp47: {}".format(subtitle['language'], subtitle['language'])) + + #init_data_b64 = data['result']['viewables'][0]['psshb64'][0] + init_data_b64 = data['result']['video_tracks'][0]['drmHeader']['bytes'] + + #init_data_b64 = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQAAAAAAUrePMAAAAAAAAAAA==' + #init_data_b64 = "" + + #cert_data_b64 = data['result']['viewables'][0]['cert'] + cert_data_b64 = 'CAUSwwUKvQIIAxIQ5US6QAvBDzfTtjb4tU/7QxiH8c+TBSKOAjCCAQoCggEBAObzvlu2hZRsapAPx4Aa4GUZj4/GjxgXUtBH4THSkM40x63wQeyVxlEEo1D/T1FkVM/S+tiKbJiIGaT0Yb5LTAHcJEhODB40TXlwPfcxBjJLfOkF3jP6wIlqbb6OPVkDi6KMTZ3EYL6BEFGfD1ag/LDsPxG6EZIn3k4S3ODcej6YSzG4TnGD0szj5m6uj/2azPZsWAlSNBRUejmP6Tiota7g5u6AWZz0MsgCiEvnxRHmTRee+LO6U4dswzF3Odr2XBPD/hIAtp0RX8JlcGazBS0GABMMo2qNfCiSiGdyl2xZJq4fq99LoVfCLNChkn1N2NIYLrStQHa35pgObvhwi7ECAwEAAToQdGVzdC5uZXRmbGl4LmNvbRKAA4TTLzJbDZaKfozb9vDv5qpW5A/DNL9gbnJJi/AIZB3QOW2veGmKT3xaKNQ4NSvo/EyfVlhc4ujd4QPrFgYztGLNrxeyRF0J8XzGOPsvv9Mc9uLHKfiZQuy21KZYWF7HNedJ4qpAe6gqZ6uq7Se7f2JbelzENX8rsTpppKvkgPRIKLspFwv0EJQLPWD1zjew2PjoGEwJYlKbSbHVcUNygplaGmPkUCBThDh7p/5Lx5ff2d/oPpIlFvhqntmfOfumt4i+ZL3fFaObvkjpQFVAajqmfipY0KAtiUYYJAJSbm2DnrqP7+DmO9hmRMm9uJkXC2MxbmeNtJHAHdbgKsqjLHDiqwk1JplFMoC9KNMp2pUNdX9TkcrtJoEDqIn3zX9p+itdt3a9mVFc7/ZL4xpraYdQvOwP5LmXj9galK3s+eQJ7bkX6cCi+2X+iBmCMx4R0XJ3/1gxiM5LiStibCnfInub1nNgJDojxFA3jH/IuUcblEf/5Y0s1SzokBnR8V0KbA==' + #cert_data_b64 = cert_data_b64.decode("utf-8") + #cert_data_b64 = 'Cr0CCAMSEOVEukALwQ8307Y2+LVP+0MYh/HPkwUijgIwggEKAoIBAQDm875btoWUbGqQD8eAGuBlGY+Pxo8YF1LQR+Ex0pDONMet8EHslcZRBKNQ/09RZFTP0vrYimyYiBmk9GG+S0wB3CRITgweNE15cD33MQYyS3zpBd4z+sCJam2+jj1ZA4uijE2dxGC+gRBRnw9WoPyw7D8RuhGSJ95OEtzg3Ho+mEsxuE5xg9LM4+Zuro/9msz2bFgJUjQUVHo5j+k4qLWu4ObugFmc9DLIAohL58UR5k0XnvizulOHbMMxdzna9lwTw/4SALadEV/CZXBmswUtBgATDKNqjXwokohncpdsWSauH6vfS6FXwizQoZJ9TdjSGC60rUB2t+aYDm74cIuxAgMBAAE6EHRlc3QubmV0ZmxpeC5jb20SgAOE0y8yWw2Win6M2/bw7+aqVuQPwzS/YG5ySYvwCGQd0Dltr3hpik98WijUODUr6PxMn1ZYXOLo3eED6xYGM7Riza8XskRdCfF8xjj7L7/THPbixyn4mULsttSmWFhexzXnSeKqQHuoKmerqu0nu39iW3pcxDV/K7E6aaSr5ID0SCi7KRcL9BCUCz1g9c43sNj46BhMCWJSm0mx1XFDcoKZWhpj5FAgU4Q4e6f+S8eX39nf6D6SJRb4ap7Znzn7preIvmS93xWjm75I6UBVQGo6pn4qWNCgLYlGGCQCUm5tg566j+/g5jvYZkTJvbiZFwtjMW5njbSRwB3W4CrKoyxw4qsJNSaZRTKAvSjTKdqVDXV/U5HK7SaBA6iJ981/aforXbd2vZlRXO/2S+Maa2mHULzsD+S5l4/YGpSt7PnkCe25F+nAovtl/ogZgjMeEdFyd/9YMYjOS4krYmwp3yJ7m9ZzYCQ6I8RQN4x/yLlHG5RH/+WNLNUs6JAZ0fFdCmw=' + #cert_data_b64 = '' + + """ + self.logger.debug(video_track['urls'][0]['url']) + self.logger.debug(audio_track['downloadables']['urls'][0]['url']) + self.logger.debug(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values())[0]) + """ + + #iter(video_track['urls'].values()) + #next(iter(video_track['urls'][0]['url'])), + + wvdl_vt = VideoTrack(True, video_track['size'], 0, video_track['urls'][0]['url'], + video_track['content_profile'], video_track['bitrate'], + video_track['res_w'], video_track['res_h']) + + wvdl_ats = [] + audio_languages = [] + + + #iter(audio_track['downloadables']['urls'].values())), + #next(iter(audio_track['downloadables']['urls'][0]['url'])), + + + + for id, audio_track in enumerate(audio_tracks): + audio_languages.append(audio_track['language']) + wvdl_ats.append( + AudioTrack(False, audio_track['downloadables']['size'], id, audio_track['downloadables']['urls'][0]['url'], + audio_track['downloadables']['content_profile'], audio_track['downloadables']['bitrate'], audio_track['language']) + ) + + wvdl_sts = [] + use_captions = { 'it': True } + if subtitle_tracks: + for track in subtitle_tracks: + use_captions.update({track['language']: True}) + for track in subtitle_tracks: + if track['language'] == 'it' and track['trackType'] == "SUBTITLES" and not track['isForcedNarrative']: + use_captions.update({track['language']:False}) + for i, subtitle in enumerate(subtitle_tracks): + if 'it' in audio_languages: + if subtitle['isForcedNarrative'] and subtitle['language'] == 'it' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, 'Forced', subtitle['language'], True, next(iter(list(subtitle['downloadables'][0]['urls'].values()))), + 'srt') + ) + elif not subtitle['isForcedNarrative'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['labguage']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['downloadables'][0]['urls'].values()))), + 'srt') + ) + else: + if not subtitle['isForcedNarrative'] and subtitle['language'] == 'it' and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], True, next(iter(list(subtitle['downloadables'][0]['urls'].values()))), + 'srt') + ) + elif not subtitle['isForcedNarrative'] and (subtitle['trackType'] == "SUBTITLES" or use_captions[subtitle['language']] == True): + wvdl_sts.append( + SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(list(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values())[0])), + 'srt') + ) + + #SubtitleTrack(i, subtitle['language'], subtitle['language'], False, next(iter(subtitle['downloadables'][0]['urls'].values())), + #(subtitle['ttDownloadables']['simplesdh']['downloadUrls'].values()[0]) + + return True, [wvdl_vt, wvdl_ats, wvdl_sts, init_data_b64, cert_data_b64] + #, cert_data_b64 + + + def get_license(self, challenge, session_id): + id = int(time.time() * 10000) + self.logger.info("doing license request") + #self.logger.debug(challenge) + #.decode('latin-1'), + #'challengeBase64': base64.b64encode(challenge).decode('utf-8'), + #challenge = "CAESvwsKhAsIARLrCQquAggCEhBhljiz6gRtg2OViA9+Lz9YGK6Z5MsFIo4CMIIBCgKCAQEAqZctmMlrOdLTGaGIG8zGjKsTRmkkslu7F3aTgNckkuK7/95JUUkCIpJAeksnlWCcORO9EZlQpr10PQwMUTLQ5VO4S5QbBeXrwdJ+4N3FH3L5nqGpQZ8Ie6aNTeofkle1Kz6iBI+c2NJ82D2EyHclC17XrjXrhfFTXmcuZQ9voo9zcQaLSA7Q/hoGIRA+DrRh3ssVDNWK0EfcXbhCwF0wpvv8nY4sLTXn8VbGkhEt6DUQ4Io5GB0fRNQiOYDGeZ0/0Vv9MjN7V9ouAYGWyqTDbtDCCCLlKs4mUYu9jk/NA0fk9ASqkYNE8v7l/Vvi/CP9Cs8SscDeIo+tNKCjinQTHwIDAQABKN47EoACwm4d+Nnsw8ztw7ZUVXeyZpqVAwf8rKcZjsf2GmtT26out8yLhLq0Jm4NqKaPy3Gmc7g0Snm7RG1V5SnoROS2AU+5t65zjSKDFnPx9iaHnoMMDfVfT4dXh2pHXFiFJiio7rbNvjJm/tFN5htxX8R/DMYll6J+ZDrCSkEwrOwc2mmdgmsbCD0N54x2xPv9Z5QNKYToxBO9pAFK97zKQ5TulpRHaR5EOAx4S844j6M3nB0KuxZVQIiMHYeCusCDNR3bjNshkLSq+vDf+GubRRWPzdVsW/QdiC+TPNA6k29Is/M+XAvdaBTK/NXVbq4meetgpDIOnw1IOXJc5kChQe/GmRq0BQquAggBEhB2LPhY5TOiYdn5bHg8oGKXGOOA5MsFIo4CMIIBCgKCAQEAzh8d+Id0W9gKHFeRdXqbSQU+zXHITcSrv/xenEQiyXK1Abgnn4zcKTDVXxqAGPGpUcza8zuLpz29Cthv3f1RmKDdgMgzukLYK0s+oA/FPJlEQIw9wCybtcNGR3BfCZYBwDKap1kdfUbIh1hDHavRjirKjoUyzN207iEPFC0B64KBg4EZCX+qYFrZ19BkWkoCbGz80t0cTQzkEzhjuyrZMLN8qgG3mOcoemMfCP8VoNxrE0tBoQ+/cBGTbHc9zriaGWrUfy/NPfL8T73Qwc7At+S/dfeUNLc1VBm0tITKLhDvmFVmFNBiem68TUzi/Da7hfbSWkFWerF/Ja57OwAodwIDAQABKN47EoADLrTvfLaNu253c3qo7vPiTI0Fcnpk2kJ+UREun27c5Bls6vTL1YMveW5J7tlF1SKjbN7ivxFtnIxAoy/e971mrnzz+Wms9MWsm+JzmuJSvBhICSfBQf8ZSMUfA7ezWz9HG3FrJY/mgmNUxui5pZrxGQ3Ik+SgTSt0Nxj4RvXi6MNEuK1+p4uZNAsO7mn9uDVc7WHQvHYGRPIgCI5GuhcEb+kQVowYfNclImjQH/Lge35cSgXaPsj7AarnEl5cwRbMY6RKAmU5cQCPqYSTEiRkOEJgBvzZ+T5wUPcNw77kQssi9P0xZpgi1iOv7wtLcXi+NlLur9WB1t7aZG4YJiOaIMf7W28+hbNh/Ea8IJrX/ZM4HTp/OmI56cRC1IHheF/CEd+tRf5fOqHvsqVtByOUe0YLRCSTrbCGpcH1C9OsIZUcKO+Kn7EcET5xxg/zRqgF82MICzNX9hYgH2rYcPRcRSjRXU5Zk7M/3LEcr4ojzzRcNqVNQpMPOKH/Loq+k7/EGhgKEWFyY2hpdGVjdHVyZV9uYW1lEgNhcm0aFgoMY29tcGFueV9uYW1lEgZHb29nbGUaFwoKbW9kZWxfbmFtZRIJQ2hyb21lQ0RNGhkKDXBsYXRmb3JtX25hbWUSCENocm9tZU9TGiIKFHdpZGV2aW5lX2NkbV92ZXJzaW9uEgoxLjQuOS4xMDg4MggIABAAGAAgARIsCioKFAgBEhAAAAAABMaLogAAAAAAAAAAEAEaEEIKIik8QeHuBvBnJrVi2QcYASDP2/7fBTAVGoACQaYQfNJWZWIRUHJ1Z2GB20DCS+YUEtUun+375X5244Z+GfSzluYjKLw0NMF6r1Vbcauycy0+tloWHyb2cCIdYPNiGhPbOJNJ5XeLqVTZLQz+xJpdP/c6mTcKRVosJZcrjWz7X+5rzEBQf5rWzflb6vQF5oRh4LZz+4BjwAWcNmfvDMgzuJ37eLucAE/J/B6eNKeUt0l4BtCwmRESU15TD4AjtnkN4VIlE5ADdgso22rbuFE5RMqGydaHCT5d00N/aREjcvW1EDlOgiEe25PNvvtbiOTTFMxMoGuAVTo8cIHAIEeEZ8TsrUGoi8ELzHofIo7JvKPmLBlu2IbjfRsJhA==" + self.logger.debug("challenge - {}".format(base64.b64encode(challenge))) + license_request_data = { + #'method': 'license', + #'licenseType': 'STANDARD', + #'clientVersion': '4.0004.899.011', + #'uiVersion': 'akira', + #'languages': ['en-US'], + #'playbackContextId': self.playbackContextId, + #'drmContextIds': [self.drmContextId], + #'challenges': [{ + # 'dataBase64': base64.b64encode(challenge).decode('utf-8'), + # 'sessionId': "14673889385265" + 'version': 2, + 'url': data1['result']['links']['license']['href'], + 'id': id, + 'esn': 'NFCDIE-02-DMT4C1VHTF81YTJY8LXRA4GF9J07H1', + 'languages': ['en-US'], + 'uiVersion': 'shakti-v25d2fa21', + 'clientVersion': '6.0011.511.011', + 'params': [{ + 'sessionId': session_id, + 'clientTime': int(id / 10000), + 'challengeBase64': base64.b64encode(challenge).decode('utf-8'), + 'xid': int(id + 1610) + }], + #self.client_config.config['esn'] + #'clientTime': int(time.time()), + #'clientTime': int(id / 10000), + #'sessionId': '14673889385265', + #'clientTime': int(id / 10000), + #'xid': int((int(time.time()) + 0.1612) * 1000) + 'echo': 'sessionId' + } + #license_request_data = str(license_request_data) + request_data = self.__generate_msl_request_data_lic(license_request_data) + + + resp = self.session.post(nf_cfg.LICENSE_ENDPOINT, request_data, proxies=self.client_config.get_proxies()) + + """ + try: + # If is valid json the request for the licnese failed + resp.json() + self.logger.debug('Error getting license: '+resp.text) + exit(1) + except ValueError: + # json() failed so we have a chunked json response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads']) + self.logger.debug(data) + #if data['success'] is True: + if 'licenseResponseBase64' in data[0]: + #return data['result']['licenses'][0]['data'] + #return response['result'][0]['licenseResponseBase64'] + return data[0]['licenseResponseBase64'] + else: + self.logger.debug('Error getting license: ' + json.dumps(data)) + exit(1) + """ + # json() failed so we have a chunked json response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads']) + self.logger.debug(data) + + fobj = open("license.json", "w") + playlist = str(data) + fobj.write(playlist) + fobj.close() + + return data['result'][0]['licenseResponseBase64'] + + #if data['success'] is True: + #data[0] + #if 'licenseResponseBase64' in data: + #return data['result']['licenses'][0]['data'] + #return response['result'][0]['licenseResponseBase64'] + #return data['links']['releaseLicense']['href'] + # return data['licenseResponseBase64'] + + + def __get_base_url(self, urls): + for key in urls: + return urls[key] + + def __decrypt_payload_chunk(self, payloadchunks): + decrypted_payload = '' + for chunk in payloadchunks: + payloadchunk = json.loads(chunk) + try: + encryption_envelope = str(bytes(payloadchunk['payload'], encoding="utf-8").decode('utf8')) + except TypeError: + encryption_envelope = payloadchunk['payload'] + # Decrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['iv'])) + plaintext = cipher.decrypt(base64.standard_b64decode(json.loads(base64.standard_b64decode(encryption_envelope))['ciphertext'])) + # unpad the plaintext + plaintext = json.loads((Padding.unpad(plaintext, 16))) + data = plaintext['data'] + + # uncompress data if compressed + data = base64.standard_b64decode(data) + #if plaintext['compressionalgo'] == 'GZIP': + # data = zlib.decompress(base64.standard_b64decode(data), 16 + zlib.MAX_WBITS) + #else: + # data = base64.standard_b64decode(data) + + decrypted_payload += data.decode('utf-8') + #decrypted_payload = json.loads(decrypted_payload)[1]['payload']['data'] + #decrypted_payload = base64.standard_b64decode(decrypted_payload) + #return json.loads(decrypted_payload) + decrypted_payload = json.loads(decrypted_payload) + return decrypted_payload + + def __parse_chunked_msl_response(self, message): + header = message.split('}}')[0] + '}}' + payloads = re.split(',\"signature\":\"[0-9A-Za-z=/+]+\"}', message.split('}}')[1]) + payloads = [x + '}' for x in payloads][:-1] + + return { + 'header': header, + 'payloads': payloads + } + + def __generate_msl_request_data(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(header_encryption_envelope).decode('utf-8'), + 'mastertoken': self.mastertoken, + } + # Serialize the given Data + #serialized_data = json.dumps(data) + #serialized_data = serialized_data.replace('"', '\\"') + #serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-13","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + #compressed_data = self.__compress_data(serialized_data) + + + data1 = json.dumps(data) + print(data1) + data1 = data1.encode('utf-8') + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + #"data": compressed_data.decode('utf-8'), + #"compressionalgo": "GZIP", + "data": (base64.standard_b64encode(data1)).decode('utf-8'), + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(first_payload_encryption_envelope).decode('utf-8'), + } + request_data = json.dumps(header) + json.dumps(first_payload_chunk) + return request_data + + + def __generate_msl_request_data_lic(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(header_encryption_envelope).decode('utf-8'), + 'mastertoken': self.mastertoken, + } + # Serialize the given Data + #serialized_data = json.dumps(data) + #serialized_data = serialized_data.replace('"', '\\"') + #serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-13","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + #compressed_data = self.__compress_data(serialized_data) + + + print(data) + #print('\n') + + #data1 = json.dumps(data) + #print(data1) + #data1 = data1.encode('utf-8') + + + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + #"data": compressed_data.decode('utf-8'), + #"compressionalgo": "GZIP", + #"data": (base64.standard_b64encode(data1)).decode('utf-8'), + "data": base64.standard_b64encode(json.dumps(data).encode('utf-8')).decode('utf-8'), + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope.encode('utf-8')).decode('utf-8'), + 'signature': self.__sign(first_payload_encryption_envelope).decode('utf-8'), + } + request_data = json.dumps(header) + json.dumps(first_payload_chunk) + + return request_data + + def __compress_data(self, data): + # GZIP THE DATA + out = BytesIO() + with gzip.GzipFile(fileobj=out, mode="w") as f: + f.write(data.encode('utf-8')) + return base64.standard_b64encode(out.getvalue()) + + def __generate_msl_header(self, is_handshake=False, is_key_request=False, compressionalgo="GZIP", encrypt=True): + """ + Function that generates a MSL header dict + :return: The base64 encoded JSON String of the header + """ + self.current_message_id = self.rndm.randint(0, pow(2, 52)) + + header_data = { + 'sender': self.client_config.config['esn'], + 'handshake': is_handshake, + 'nonreplayable': False, + 'capabilities': { + 'languages': ["en-US"] + #'languages': ["en-US"], + #'compressionalgos': [], + #'encoderformats' : ['JSON'], + }, + 'recipient': 'Netflix', + 'renewable': True, + 'messageid': self.current_message_id, + 'timestamp': time.time() + } + + # Add compression algo if not empty + #if compressionalgo is not "": + # header_data['capabilities']['compressionalgos'].append(compressionalgo) + + # If this is a keyrequest act diffrent then other requests + if is_key_request: + public_key = base64.standard_b64encode(self.rsa_key.publickey().exportKey(format='DER')).decode('utf-8') + header_data['keyrequestdata'] = [{ + 'scheme': 'ASYMMETRIC_WRAPPED', + 'keydata': { + 'publickey': public_key, + 'mechanism': 'JWK_RSA', + 'keypairid': 'superKeyPair' + } + }] + #header_data['userauthdata'] = { + # 'scheme' : 'NETFLIXID', + # 'authdata' : { + # 'netflixid' : self.cookies['NetflixId'], + # 'securenetflixid' : self.cookies['SecureNetflixId'], + # } + #} + #header_data['keyrequestdata'] = [{ + # 'scheme': 'WIDEVINE', + # 'keydata': { + # 'keyrequest':'CAESiQ0KxgwIARLrCQquAggCEhAlHgXTeVZWV5AbCt3IDiHsGIazwckFIo4CMIIBCgKCAQEAz2Cz+sq6JqPv1N6TwdFYyTjEvmAdUZjMNFTAX4vbMBe8adURCnePeAl8K67h7iWOQO5xxN4rfv49H3bX7lyo+kU/v34iTabu+wLSTj9Pl+hBpx5X+kX0arO+Mvy+bh32obug09Tjfg000SiA09+kyKf9q8Yitllfgzj0uUscotoSKIGIZPjHiI9Voboxi0ApSKh4lWfIvE7YuhDVJJt3pfuRHwQeXHOUSJj32pOLkinU3yVfmSf7ozd10NuqRrUQ7t/8ZmE6AeAc+XACAQku0W5iNwW4raqwG6oRGV5WXfr28NsM1j89kOgbHEf7Nr4tRc0Pbu+/7gp5ySP26snIPQIDAQABKMA0EoACWoSItadpIcGOtgWpC6VLOTliaVjBpHg2LnfQnag2XqmXbcZ457O4DfyRBX1YxQRVpwCSh5EM0kOrnI9AUUfZQplMVa0f+Qp04UKH5FIoUGeRND0I1Qn3/5uF2PXIG/xRjf8BoH+WqKhpWT+143wDml2ERW7otsXZdqHeZQNabwlFEjvttcrL3qKj+IDa4cXKRflbmt7SVjVo5cmSPRaVqgk7Mck+6haI4pgkkBMfdwpPBlvroM41zQO7qz3P8HkZjTI2OEBwnNFGZ4Di+mQsQExE3UkUUxwmUBH84ftRgnsdhRoaQ8roeZGO73u5KVRVUyDvpWjnKCCCcvx90H0Z5hq0BQquAggBEhASqgK+FxGhlxP70rVZ8RnzGMjgnbgFIo4CMIIBCgKCAQEAslO3gaTon+lSqGB33pfvFpVFUb2WITRegpbjA7u8iv+44xv53N0ZggOdJME14i460kOaYZ+PEDlaU10HlBqv5yn8Nk2tnwHs+1rY+AufTBuBWhKWaCg35YdGiCFm3/QHnBbtYqE1GqoCyHLmS7FUbj0iBJF6tOr7/qR4NW2/eRsfe89K/qNi73lP97JUQrZn8pKVZ8pijET+aTFFE+iZi7IQnuqFibGIAmzcrQLDbYLlgrrTdp/AxPsjUHgAE9GF3PnsVZfmbChaK+wV1fG5p/Ke0LLXvQRS5XpefD+3aH/tNWGfr+RDFeAwht/oFX0pOVHEZLTiXpxq/iE/SE3k9wIDAQABKMA0EoADsmVh9iHXpzmob8Wxy+GUAyfUHBOQG8TvlD/n6BiBz4F3lY1HiHQSJVNGTvboZZNkg0oI6o7mhh616Y/4RlfSiVGqHzRaGol4SFow82DZnyF4ozsUrJpi/FFMc5KpwSEE4N0GIMq4asbsbK5RXUrtaRpG8rH80tu50Ft4veei6bzwACvS9QrkFcL7zvby3DT9mHZtn46ytrGqmogftrT6FfvOUCdoyfizLBfQM0LY3zRUp5h03W7GhwueR0Jg/4g5XZKvA2LzQov9120qczOxP9RtE0PP1h/EnsXidfdYsbOP+IgYcBHHaqtVaFWPWKxt9+cPy/0gYYzfnpT5axotlo96aJm96arZnt5QxZUAASq/OwSzqgRojZqmB91tTwP7LOrFaNfwq4Icb29gSAN2nofl4WFZx/VSvXBB/alBlc8tOJxM0wzzKw5c2EFC2qRjuPsIDF6MJWaicUERdcDoO24JaRItXCeW0rv+PQSuwbU+oJOI9HWGmtcKU/1fYLABGhYKDGNvbXBhbnlfbmFtZRIGR29vZ2xlGhMKCm1vZGVsX25hbWUSBVBpeGVsGh4KEWFyY2hpdGVjdHVyZV9uYW1lEglhcm02NC12OGEaFwoLZGV2aWNlX25hbWUSCHNhaWxmaXNoGhgKDHByb2R1Y3RfbmFtZRIIc2FpbGZpc2gaTQoKYnVpbGRfaW5mbxI/Z29vZ2xlL3NhaWxmaXNoL3NhaWxmaXNoOjcuMS4xL05PRjI3Qy8zNjg3ODEwOnVzZXIvcmVsZWFzZS1rZXlzGi0KCWRldmljZV9pZBIgQUMzNzQzNDkyOTRCAAAAAAAAAAAAAAAAAAAAAAAAAAAaJgoUd2lkZXZpbmVfY2RtX3ZlcnNpb24SDnY0LjEuMC1hbmRyb2lkGiQKH29lbV9jcnlwdG9fc2VjdXJpdHlfcGF0Y2hfbGV2ZWwSATAyCBABIAQoCzABEi4KLAoGCnoAbDgrEAIaIEEzRTJEQUY3MjAxMkJBN0Q2QjAwMDAwMDAwMDAwMDAwGAEgisGQygUwFTjrqfChCRqAAjPrDb21SMpfIZsNZzpE97e4QU5R72I6KMCugWsKQmvbZqVWCSTmqMlqEKU48NyDLYaiqJ8VNaIfZgP+rsC4K8BYmGIgIx1TTYtai0yEnL89m07zZEH/QnOgM9BL+f6/wJ84cH1zS/rP1r6//dkrb80PnsLJowbdQ9N9DH3h/6g0vzh2RSzIP2eLGTxILbb06WJ1G/lgeXhy21JxIFFGUdgemTMfKZaSjgQO6f4SWhKv7t5jvIoD0BsqO3IT8afCapopMurW/YLSz3BkErgy4+0Lt22+t+gTkmtxiEgrq4cV7nCdRIiaNthuaxIkS2KSZkd3YKrkc/N3lifKnQEn9+o=', + # }, + #}] + else: + if 'usertoken' in self.tokens: + pass + else: + # Auth via email and password + header_data['userauthdata'] = { + 'scheme': 'EMAIL_PASSWORD', + 'authdata': { + 'email': self.client_config.config['username'], + 'password': self.client_config.config['password'] + } + } + return json.dumps(header_data) + + def __encrypt(self, plaintext): + """ + Encrypt the given Plaintext with the encryption key + :param plaintext: + :return: Serialized JSON String of the encryption Envelope + """ + iv = get_random_bytes(16) + encryption_envelope = { + 'ciphertext': '', + 'keyid': self.client_config.config['esn'] + '_' + str(self.sequence_number), + 'sha256': 'AA==', + 'iv': base64.standard_b64encode(iv).decode('utf-8') + } + # Padd the plaintext + plaintext = Padding.pad(plaintext.encode('utf-8'), 16) + # Encrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv) + ciphertext = cipher.encrypt(plaintext) + encryption_envelope['ciphertext'] = base64.standard_b64encode(ciphertext).decode('utf-8') + return json.dumps(encryption_envelope) + + def __sign(self, text): + """ + Calculates the HMAC signature for the given text with the current sign key and SHA256 + :param text: + :return: Base64 encoded signature + """ + signature = HMAC.new(self.sign_key, text.encode('utf-8'), SHA256).digest() + return base64.standard_b64encode(signature) + + def __perform_key_handshake(self): + header = self.__generate_msl_header(is_key_request=True, is_handshake=True, compressionalgo="", encrypt=False) + request = { + 'entityauthdata': { + 'scheme': 'NONE', + 'authdata': { + 'identity': self.client_config.config['esn'] + } + }, + 'headerdata': base64.standard_b64encode(header.encode('utf-8')).decode('utf-8'), + 'signature': '', + } + self.logger.debug('Key Handshake Request:') + self.logger.debug(json.dumps(request)) + + resp = self.session.post(nf_cfg.MANIFEST_ENDPOINT, json.dumps(request, sort_keys=True), proxies=self.client_config.get_proxies()) + if resp.status_code == 200: + resp = resp.json() + if 'errordata' in resp: + self.logger.debug('Key Exchange failed') + self.logger.debug(base64.standard_b64decode(resp['errordata'])) + return False + self.logger.debug(resp) + self.logger.debug('Key Exchange Sucessful') + self.__parse_crypto_keys(json.JSONDecoder().decode(base64.standard_b64decode(resp['headerdata']).decode('utf-8'))) + else: + self.logger.debug('Key Exchange failed') + self.logger.debug(resp.text) + + def __parse_crypto_keys(self, headerdata): + self.__set_master_token(headerdata['keyresponsedata']['mastertoken']) + #self.__set_userid_token(headerdata['useridtoken']) + # Init Decryption + encrypted_encryption_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['encryptionkey']) + encrypted_sign_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['hmackey']) + cipher_rsa = PKCS1_OAEP.new(self.rsa_key) + + # Decrypt encryption key + encryption_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_encryption_key).decode('utf-8')) + self.encryption_key = base64key_decode(encryption_key_data['k']) + + # Decrypt sign key + sign_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_sign_key).decode('utf-8')) + self.sign_key = base64key_decode(sign_key_data['k']) + + self.__save_msl_data() + self.handshake_performed = True + + def __load_msl_data(self): + msl_data = json.JSONDecoder().decode( + self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage']).decode('utf-8')) + # Check expire date of the token + master_token = json.JSONDecoder().decode( + base64.standard_b64decode(msl_data['tokens']['mastertoken']['tokendata']).decode('utf-8')) + valid_until = datetime.utcfromtimestamp(int(master_token['expiration'])) + present = datetime.now() + difference = valid_until - present + difference = difference.total_seconds() / 60 / 60 + # If token expires in less then 10 hours or is expires renew it + if difference < 10: + self.__load_rsa_keys() + self.__perform_key_handshake() + return + + self.__set_master_token(msl_data['tokens']['mastertoken']) + #self.__set_userid_token(msl_data['tokens']['useridtoken']) + self.encryption_key = base64.standard_b64decode(msl_data['encryption_key']) + self.sign_key = base64.standard_b64decode(msl_data['sign_key']) + + def __save_msl_data(self): + """ + Saves the keys and tokens in json file + :return: + """ + data = { + "encryption_key": base64.standard_b64encode(self.encryption_key).decode('utf-8'), + 'sign_key': base64.standard_b64encode(self.sign_key).decode('utf-8'), + 'tokens': { + 'mastertoken': self.mastertoken, + #'useridtoken': self.useridtoken, + } + } + serialized_data = json.JSONEncoder().encode(data) + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['msl_storage'], serialized_data.encode('utf-8')) + + def __set_master_token(self, master_token): + self.mastertoken = master_token + self.sequence_number = json.JSONDecoder().decode(base64.standard_b64decode(master_token['tokendata']).decode('utf-8'))[ + 'sequencenumber'] + + def __set_userid_token(self, userid_token): + self.useridtoken = userid_token + + def __load_rsa_keys(self): + loaded_key = self.load_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key']) + self.rsa_key = RSA.importKey(loaded_key) + + def __save_rsa_keys(self): + self.logger.debug('Save RSA Keys') + # Get the DER Base64 of the keys + encrypted_key = self.rsa_key.exportKey() + self.save_file(wvdl_cfg.COOKIES_FOLDER, self.client_config.config['rsa_key'], encrypted_key) + + @staticmethod + def file_exists(msl_data_path, filename): + """ + Checks if a given file exists + :param filename: The filename + :return: True if so + """ + return os.path.isfile(os.path.join(msl_data_path, filename)) + + @staticmethod + def save_file(msl_data_path, filename, content): + """ + Saves the given content under given filename + :param filename: The filename + :param content: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'wb') as file_: + file_.write(content) + file_.flush() + file_.close() + + @staticmethod + def load_file(msl_data_path, filename): + """ + Loads the content of a given filename + :param filename: The file to load + :return: The content of the file + """ + with open(os.path.join(msl_data_path,filename), 'rb') as file_: + file_content = file_.read() + file_.close() + return file_content + + + def get_track_download(self, track): + return self.session.get(track.url, stream=True, proxies=self.client_config.get_proxies()) + + def get_subtitle_download(self, track): + try: + req = self.session.get(track.url, proxies=self.client_config.get_proxies()) + except: + while True: + try: + req = self.session.get(track.url, proxies=self.client_config.get_proxies()) + return req + except: + continue + return req + + + def get_wvconfig_options(self): + return {'server_cert_required': True, 'pssh_header': True} + + def needs_ffmpeg(self): + return True + + def finagle_subs(self, subtitles): + return subs.to_srt(subtitles) + diff --git a/pywidevine/clients/netflix/config.py b/pywidevine/clients/netflix/config.py new file mode 100644 index 0000000..171b74e --- /dev/null +++ b/pywidevine/clients/netflix/config.py @@ -0,0 +1,86 @@ +from pywidevine.cdm import deviceconfig + + +config = { + #'username': 'georgecorbett683@gmail.com', + #'password': 'HjyHjyScq1Scq1', + + + #'username': 'rita889@mail.com', + #'password': 'qwertzui', + + 'username': 'trkoneplus@gmail.com', + 'password': '132546as', + + #'username': 'bonniegoz@outlook.com', + #'password': 'ffJ5yc4wvl', + 'msl_storage': 'msl.json', + 'rsa_key': 'rsa.bin', + #'esn': "NFCDCH-02-DMT46QNHH01MNAHJF9414XFCF9X5YJ", + #'esn': "NFCDIE-02-DMT4C1VHTF81YTJY8LXRA4GF9J07H1", + #'esn': "NFCDSF-01-EYVQ7NW9NEVJ43C5LCQM6HV2PLC2PP", + #'esn': "NFUWA-001-DMT46QNHH01MNAHJF9415XFCF9X5YJ", + #'esn': 'NFANDROID1-PRV-P-MOTORNEXUS=6-5730-DFA914FBB2E4815708C10A6E82FD67B9166F9528A11C7A0AE410ACF266DF621F', + #'esn': 'NFANDROID1-PRV-T-L3-XIAOMMIBOX3-4445-F74EE02DFE6739B1007B33F1E4290AA594839FEA6F8711DBFE837F57E1E8F7C8', + + #'esn': "NFCDIE-03-F33YQY3J8827C82NE148PK3XV01R2V", + #'esn_manifest': "NFCDIE-03-F33YQY3J8827C82NE148PK3XV01R2V", + + #'esn': 'NFANDROID1-PRV-P-GOOGLPIXEL-4464-6EA8A15D39427309D0A97686A1A315C6A0ABFE46BECD14BB740EC56C65168E72', + + #'esn': "NFANDROID1-PRV-P-GOOGLPIXEL-6720-6EA8A15D39427309D0A97686A1A315C6A0ABFE46BECD14BB740EC56C65168E72", + + + #'esn': 'NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV', + + #'esn': 'NFANDROID-PRV-P-ASUS=ASUS=X00TD-8195-0519ECDF76149E3600596BE929720A91BAB905487A702E5BEEOF727BAFA2AB74E', + + #'esn': 'NFANDROID2-PRV-SONYANDROIDTV2019VU-SONY=BRAVIA=VU1-12360-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C', + 'esn': 'NFANDROID2-PRV-SHIELDANDROIDTV-NVIDISHIELD=ANDROID=TV-15895-4AA5B5F40AB2A2AA17A38514CF4B2DBE1E9D4D84CD8658D5DCC0430D4E93A05C', + + #'esn': 'NFANDROID1-PRV-SONYANDROIDTV2017-SONY=BRAVIA=4K=GB', + #'esn_manifest': "NFANDROID1-PRV-SONYANDROIDTV2017-SONY=BRAVIA=4K=GB", + + #'esn': 'NFANDROID2-PRV-FIRETVSTICK2016-AMAZOFTT-6590-7A32FCE57BD8289B07AC2DBF75125D5A082F10F834C43D2D654A0BAC4', + #'esn_manifest': "NFANDROID2-PRV-FIRETVSTICK2016-AMAZOFTT-6590-7A32FCE57BD8289B07AC2DBF75125D5A082F10F834C43D2D654A0BAC4", + + 'wv_keyexchange': True, + 'wv_device': deviceconfig.device_android_generic_2, + #'wv_device': deviceconfig.device_chromecdm_903, + + #'esn': "NFCDCH-02-DMT46QNHH01MNAHJF9414XFCF9X5YJ", + 'esn_manifest': "NFCDCH-02-DMT46QNHH01MNAHJF9414XFCF9X5YJ", + + 'proxies': { + 'us': None + }, +} + +#MANIFEST_ENDPOINT = 'http://www.netflix.com/api/msl/NFCDCH-LX/cadmium/manifest' +#LICENSE_ENDPOINT = 'http://www.netflix.com/api/msl/NFCDCH-LX/cadmium/license' + +MANIFEST_ENDPOINT = 'https://www.netflix.com/nq/msl_v1/cadmium/pbo_manifests/%5E1.0.0/router' +LICENSE_ENDPOINT = 'https://www.netflix.com/nq/msl_v1/cadmium/pbo_licenses/%5E1.0.0/router' + +#manifest_url = https://www.netflix.com/nq/msl_v1/cadmium/pbo_manifests/%5E1.0.0/router +#license_url = https://www.netflix.com/nq/msl_v1/cadmium/pbo_licenses/%5E1.0.0/router + +class NetflixConfig(object): + + def __init__(self, viewable_id, profiles, video_track, audio_tracks, subtitle_languages, audio_language, region): + self.config = config + self.viewable_id = int(viewable_id) + self.config['region'] = region + self.config['profiles'] = profiles + self.config['video_track'] = video_track + self.config['audio_tracks'] = audio_tracks + self.config['subtitle_languages'] = subtitle_languages + self.config['audio_language'] = audio_language + + def get_login(self): + return self.config['username'], self.config['password'] + + def get_proxies(self): + if self.config['proxies'] is not None: + return self.config['proxies'][self.config['region']] + return None diff --git a/pywidevine/clients/netflix/profiles.py b/pywidevine/clients/netflix/profiles.py new file mode 100644 index 0000000..364c12f --- /dev/null +++ b/pywidevine/clients/netflix/profiles.py @@ -0,0 +1,112 @@ +PROFILES = { + 'h264_main': { + '480p': [ + 'playready-h264bpl30-dash', + 'playready-h264mpl30-dash', + ], + '720p': [ + #'playready-h264mpl30-dash', + 'playready-h264mpl31-dash', + #'playready-h264mpl40-dash', + #'playready-h264mpl41-dash', + ], + '1080p': [ + 'playready-h264mpl40-dash', + ] + }, + 'h264_high': { + '480p': [ + 'playready-h264bpl30-dash', + 'playready-h264hpl30-dash', + ], + '720p': [ + 'playready-h264hpl31-dash', + ], + '1080p': [ + 'playready-h264hpl40-dash', + ] + }, + 'hevc': { + '480p': [ + 'hevc-main10-L30-dash-cenc', + ], + '720p': [ + 'hevc-main10-L31-dash-cenc', + ], + '1080p': [ + 'hevc-main10-L40-dash-cenc', + 'hevc-main10-L41-dash-cenc', + ], + '4k': [ + 'hevc-main10-L50-dash-cenc-prk', + 'hevc-main10-L51-dash-cenc-prk', + 'hevc-main10-L50-dash-cenc', + 'hevc-main10-L51-dash-cenc', + ] + }, + 'hdr': { + '480p': [ + 'hevc-hdr-main10-L30-dash-cenc-prk', + + ], + '720p': [ + 'hevc-hdr-main10-L31-dash-cenc-prk', + + ], + '1080p': [ + 'hevc-hdr-main10-L40-dash-cenc-prk', + + ], + '4k': [ + 'hevc-hdr-main10-L50-dash-cenc-prk', + + ] + }, + 'audio': [ + # 'heaac-2-dash', + 'ddplus-2.0-dash', + 'ddplus-5.1hq-dash', + 'ddplus-atmos-dash', + 'dd-5.1-dash', + ], + 'subs': [ + #'dfxp-ls-sdh', + 'simplesdh', + #'nflx-cmisc', + #'webvtt-lssdh-ios8', + #'webvtt-lssdh-ios' + #'BIF240', + #'BIF320', + ] + +} + +class NetflixProfiles(object): + def __init__(self, profile, quality): + self.profile = profile + self.quality = quality + + def get(self): + return PROFILES[self.profile]['480p'] + \ + PROFILES[self.profile]['720p'] + \ + PROFILES[self.profile]['1080p'] + + def get_all(self): + if self.profile == 'h2614': + return PROFILES[self.profile]['480p'] + \ + PROFILES[self.profile]['720p'] + \ + PROFILES[self.profile]['1080p'] + \ + PROFILES['audio'] + \ + PROFILES['subs'] + else: + return PROFILES[self.profile]['480p'] + \ + PROFILES[self.profile]['720p'] + \ + PROFILES[self.profile]['1080p'] + \ + PROFILES['audio'] + \ + PROFILES['subs'] + + def set_quality(self, quality): + self.quality = quality + + def set_profile(self, profile): + self.profile = profile diff --git a/pywidevine/clients/netflix/subs.py b/pywidevine/clients/netflix/subs.py new file mode 100644 index 0000000..a51bbc1 --- /dev/null +++ b/pywidevine/clients/netflix/subs.py @@ -0,0 +1,79 @@ +import re +import math + + +def leading_zeros(value, digits=2): + value = "000000" + str(value) + return value[-digits:] + + +def convert_time(raw_time): + if int(raw_time) == 0: + return "{}:{}:{},{}".format(0, 0, 0, 0) + + ms = '000' + if len(raw_time) > 4: + ms = leading_zeros(int(raw_time[:-4]) % 1000, 3) + time_in_seconds = int(raw_time[:-7]) if len(raw_time) > 7 else 0 + second = leading_zeros(time_in_seconds % 60) + minute = leading_zeros(int(math.floor(time_in_seconds / 60)) % 60) + hour = leading_zeros(int(math.floor(time_in_seconds / 3600))) + return "{}:{}:{},{}".format(hour, minute, second, ms) + + +def to_srt(text): + def append_subs(start, end, prev_content, format_time): + subs.append({ + "start_time": convert_time(start) if format_time else start, + "end_time": convert_time(end) if format_time else end, + "content": u"\n".join(prev_content), + }) + + begin_re = re.compile(u"\s*

(.*)

') + content_re = re.compile(u'\">(.*)

') + alt_content_re = re.compile(u'(.*?)') + br_re = re.compile(u'()+') + fmt_t = True + for s in sub_lines: + content = [] + alt_content = re.search(alt_content_re, s) + while (alt_content): # background text may have additional styling. + # background may also contain several ` ` groups + s = s.replace(alt_content.group(0), alt_content.group(1)) + alt_content = re.search(alt_content_re, s) + content = re.search(content_re, s).group(1) + + br_tags = re.search(br_re, content) + if br_tags: + content = u"\n".join(content.split(br_tags.group())) + + prev_start = prev_time["start"] + start = re.search(start_re, s).group(1) + end = re.search(end_re, s).group(1) + if len(start.split(":")) > 1: + fmt_t = False + start = start.replace(".", ",") + end = end.replace(".", ",") + if (prev_start == start and prev_time["end"] == end) or not prev_start: + # Fix for multiple lines starting at the same time + prev_time = {"start": start, "end": end} + prev_content.append(content) + continue + append_subs(prev_time["start"], prev_time["end"], prev_content, fmt_t) + prev_time = {"start": start, "end": end} + prev_content = [content] + append_subs(start, end, prev_content, fmt_t) + + lines = (u"{}\n{} --> {}\n{}\n".format( + s + 1, subs[s]["start_time"], subs[s]["end_time"], subs[s]["content"]) + for s in range(len(subs))) + return u"\n".join(lines) \ No newline at end of file diff --git a/pywidevine/decrypt/__init__.py b/pywidevine/decrypt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/decrypt/__pycache__/__init__.cpython-36.pyc b/pywidevine/decrypt/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..07c83de Binary files /dev/null and b/pywidevine/decrypt/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/decrypt/__pycache__/__init__.cpython-37.pyc b/pywidevine/decrypt/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..783e8c2 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/decrypt/__pycache__/__init__.cpython-39.pyc b/pywidevine/decrypt/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..1852b00 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-36.pyc b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-36.pyc new file mode 100644 index 0000000..a6af5d6 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-36.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-37.pyc b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-37.pyc new file mode 100644 index 0000000..002a346 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-37.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-39.pyc b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-39.pyc new file mode 100644 index 0000000..4a33773 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecrypt.cpython-39.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-36.pyc b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-36.pyc new file mode 100644 index 0000000..5dfb873 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-36.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-37.pyc b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-37.pyc new file mode 100644 index 0000000..88132a9 Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-37.pyc differ diff --git a/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-39.pyc b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-39.pyc new file mode 100644 index 0000000..5691bdd Binary files /dev/null and b/pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-39.pyc differ diff --git a/pywidevine/decrypt/wvdecrypt.py b/pywidevine/decrypt/wvdecrypt.py new file mode 100644 index 0000000..a06b923 --- /dev/null +++ b/pywidevine/decrypt/wvdecrypt.py @@ -0,0 +1,127 @@ +import logging +import subprocess +import re +from tqdm import tqdm +import base64 +import progressbar +from time import sleep +import binascii + +from pywidevine.cdm import cdm, deviceconfig +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg + + +class WvDecrypt(object): + + WV_SYSTEM_ID = [237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237] + + def __init__(self, config): + self.config = config + self.logger = logging.getLogger(__name__) + self.wvdecrypt_process = None + self.logger.debug(self.log_message("wvdecrypt object created")) + + self.cdm = cdm.Cdm() + + def check_pssh(pssh_b64): + pssh = base64.b64decode(pssh_b64) + if not pssh[12:28] == bytes(self.WV_SYSTEM_ID): + new_pssh = bytearray([0,0,0]) + new_pssh.append(32+len(pssh)) + new_pssh[4:] = bytearray(b'pssh') + new_pssh[8:] = [0,0,0,0] + new_pssh[13:] = self.WV_SYSTEM_ID + new_pssh[29:] = [0,0,0,0] + new_pssh[31] = len(pssh) + new_pssh[32:] = pssh + return base64.b64encode(new_pssh) + else: + return pssh_b64 + + print("binitdata64 " + config.init_data_b64) + + if config.device == 'mpl': + self.session = self.cdm.open_session(check_pssh(config.init_data_b64),deviceconfig.DeviceConfig(deviceconfig.device_android_generic_2)) + else: + self.session = self.cdm.open_session(check_pssh(config.init_data_b64),deviceconfig.DeviceConfig(deviceconfig.device_android_generic_2)) + #print(self.session) device_nexus6_lvl1 + self.logger.debug(self.log_message("widevine session opened")) + if self.config.server_cert_required: + self.logger.debug(self.log_message("server cert set")) + self.cdm.set_service_certificate(self.session,config.cert_data_b64) + + + def log_message(self, msg): + return "{}_{} : {}".format(self.config.tracktype, self.config.trackno, msg) + """ + def start_process(self): + if self.config.license: + for key in self.cdm.get_keys(self.session): + if key.type == 'CONTENT': + #key.kid.hex() + self.logger.logkey(self.log_message('{}:{}'.format(key.kid.hex(),key.key.hex()))) + else: + + #bar = progressbar.ProgressBar(maxval=progressbar.UnknownLength)#, \ + + #widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()]) + + self.logger.debug(self.log_message("starting mp4decrypt process")) + self.logger.debug(self.config.build_commandline_list(self.cdm.get_keys(self.session))) + print(self.cdm.get_keys(self.session)) + print(self.config.build_commandline_list(self.cdm.get_keys(self.session))) + #exit(1) + self.wvdecrypt_process = subprocess.Popen( + self.config.build_commandline_list(self.cdm.get_keys(self.session)), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT + ) + + + #i = 0 + poll = self.wvdecrypt_process.poll() + print(poll) + #bar.start() + while poll is None: + #bar.update(i) + #sleep(0.1) + #i = i +1 + poll = self.wvdecrypt_process.poll() + + #bar.finish() + + self.wvdecrypt_process.wait() + self.logger.debug(self.log_message("mp4decrypt decrypted successfully")) + """ + + def start_process(self): + #self.key_file = open("key", "w") + if self.config.license: + for key in self.cdm.get_keys(self.session): + if key.type == 'CONTENT': + self.logger.logkey(self.log_message('{}:{}'.format(key.kid.hex(),key.key.hex()))) + #self.key_file.write(key.kid.hex() + ':' + key.key.hex() + '\n') + else: + self.logger.debug(self.log_message("starting mp4decrypt process")) + self.logger.debug(self.config.build_commandline_list(self.cdm.get_keys(self.session))) + print(self.cdm.get_keys(self.session)) + print(self.config.build_commandline_list(self.cdm.get_keys(self.session))) + self.wvdecrypt_process = subprocess.Popen( + self.config.build_commandline_list(self.cdm.get_keys(self.session)), + #stdout=subprocess.PIPE, + #stderr=subprocess.STDOUT + ) + self.wvdecrypt_process.wait() + self.logger.debug(self.log_message("mp4decrypt decrypted successfully")) + #self.key_file.close() + + def get_challenge(self): + return self.cdm.get_license_request(self.session) + + def get_sid(self): + return (binascii.hexlify(self.session)).decode('utf-8').upper() + + def update_license(self, license_b64): + self.cdm.provide_license(self.session, license_b64) + return True + diff --git a/pywidevine/decrypt/wvdecryptconfig.py b/pywidevine/decrypt/wvdecryptconfig.py new file mode 100644 index 0000000..74b77e6 --- /dev/null +++ b/pywidevine/decrypt/wvdecryptconfig.py @@ -0,0 +1,62 @@ +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg +import subprocess + +class WvDecryptConfig(object): + def __init__(self, filename, tracktype, trackno, license, init_data_b64, device, cert_data_b64=None): + self.filename = filename + self.tracktype = tracktype + self.trackno = trackno + self.init_data_b64 = init_data_b64 + self.device = device + self.license = license + if cert_data_b64 is not None: + self.server_cert_required = True + self.cert_data_b64 = cert_data_b64 + else: + self.server_cert_required = False + + def get_filename(self, unformatted_filename): + return unformatted_filename.format(filename=self.filename, track_type=self.tracktype, track_no=self.trackno) + + + def find_str(self, s, char): + index = 0 + if char in s: + c = char[0] + for ch in s: + if ch == c and s[index:index + len(char)] == char: + return index + index += 1 + return -1 + + def get_kid(self, filename): + mp4dump = subprocess.Popen([wvdl_cfg.MP4DUMP_BINARY_PATH, filename], stdout=subprocess.PIPE) + mp4dump = str(mp4dump.stdout.read()) + A = self.find_str(mp4dump, 'default_KID') + KID = mp4dump[A:A + 63].replace('default_KID = ', '').replace('[', '').replace(']', '').replace(' ', '') + KID = KID.upper() + KID_video = KID[0:8] + '-' + KID[8:12] + '-' + KID[12:16] + '-' + KID[16:20] + '-' + KID[20:32] + if KID == '': + KID = 'nothing' + return KID.lower() + + def build_commandline_list(self, keys): + + KID_file = self.get_kid(self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME)) + print(KID_file) + + commandline = [wvdl_cfg.MP4DECRYPT_BINARY_PATH] + for key in keys: + if key.type == 'CONTENT' and key.kid.hex() == KID_file: + print("OK") + commandline.append('--show-progress') + commandline.append('--key') + #key.kid.hex() + #2 main high 1 hdr dv hevc + if 'hdr' in self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME): + commandline.append('{}:{}'.format(key.kid.hex(), key.key.hex())) + else: + commandline.append('{}:{}'.format(key.kid.hex(), key.key.hex())) + commandline.append(self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME)) + commandline.append(self.get_filename(wvdl_cfg.DECRYPTED_FILENAME)) + return commandline diff --git a/pywidevine/downloader/__init__.py b/pywidevine/downloader/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pywidevine/downloader/__pycache__/__init__.cpython-36.pyc b/pywidevine/downloader/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..dc27781 Binary files /dev/null and b/pywidevine/downloader/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/downloader/__pycache__/__init__.cpython-37.pyc b/pywidevine/downloader/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..0b97b84 Binary files /dev/null and b/pywidevine/downloader/__pycache__/__init__.cpython-37.pyc differ diff --git a/pywidevine/downloader/__pycache__/__init__.cpython-39.pyc b/pywidevine/downloader/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..a45f068 Binary files /dev/null and b/pywidevine/downloader/__pycache__/__init__.cpython-39.pyc differ diff --git a/pywidevine/downloader/__pycache__/tracks.cpython-36.pyc b/pywidevine/downloader/__pycache__/tracks.cpython-36.pyc new file mode 100644 index 0000000..9d4bf0d Binary files /dev/null and b/pywidevine/downloader/__pycache__/tracks.cpython-36.pyc differ diff --git a/pywidevine/downloader/__pycache__/tracks.cpython-37.pyc b/pywidevine/downloader/__pycache__/tracks.cpython-37.pyc new file mode 100644 index 0000000..5a5ad0c Binary files /dev/null and b/pywidevine/downloader/__pycache__/tracks.cpython-37.pyc differ diff --git a/pywidevine/downloader/__pycache__/tracks.cpython-39.pyc b/pywidevine/downloader/__pycache__/tracks.cpython-39.pyc new file mode 100644 index 0000000..7acdf54 Binary files /dev/null and b/pywidevine/downloader/__pycache__/tracks.cpython-39.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloader.cpython-36.pyc b/pywidevine/downloader/__pycache__/wvdownloader.cpython-36.pyc new file mode 100644 index 0000000..9f53e50 Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloader.cpython-36.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloader.cpython-37.pyc b/pywidevine/downloader/__pycache__/wvdownloader.cpython-37.pyc new file mode 100644 index 0000000..f347753 Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloader.cpython-37.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloader.cpython-39.pyc b/pywidevine/downloader/__pycache__/wvdownloader.cpython-39.pyc new file mode 100644 index 0000000..b4fd13e Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloader.cpython-39.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-36.pyc b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-36.pyc new file mode 100644 index 0000000..dc8cace Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-36.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-37.pyc b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-37.pyc new file mode 100644 index 0000000..5b3c58f Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-37.pyc differ diff --git a/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-39.pyc b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-39.pyc new file mode 100644 index 0000000..68de6ce Binary files /dev/null and b/pywidevine/downloader/__pycache__/wvdownloaderconfig.cpython-39.pyc differ diff --git a/pywidevine/downloader/tracks.py b/pywidevine/downloader/tracks.py new file mode 100644 index 0000000..f86e7de --- /dev/null +++ b/pywidevine/downloader/tracks.py @@ -0,0 +1,74 @@ +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg + +class VideoTrack(object): + def __init__(self, encrypted, size, id, url, codec, bitrate, width, height): + self.encrypted = encrypted + self.size = size + self.id = id + self.url = url + self.codec = codec + self.bitrate = bitrate + self.width = width + self.height = height + + def get_type(self): + return "video" + + def __repr__(self): + return "(encrypted={}, size={}, id={}, url={}, codec={}, bitrate={}, width={}, height={})"\ + .format(self.encrypted, self.size, self.id, self.url, self.codec, self.bitrate, self.width, self.height) + + def get_filename(self, filename, decrypted=False, fixed=False): + if not self.encrypted or decrypted: + fn = wvdl_cfg.DECRYPTED_FILENAME + else: + fn = wvdl_cfg.ENCRYPTED_FILENAME + if fixed: + fn = fn + '_fixed.mp4' + return fn.format(filename=filename, track_type="video", track_no=self.id) + + + +class AudioTrack(object): + def __init__(self, encrypted, size, id, url, codec, bitrate, language): + self.encrypted = encrypted + self.size = size + self.id = id + self.url = url + self.codec = codec + self.bitrate = bitrate + self.language = language + + def get_type(self): + return "audio" + + def get_lang(self): + return "audio" + + def __repr__(self): + return "(encrypted={}, language={}, size={}, id={}, url={}, codec={}, bitrate={})"\ + .format(self.encrypted, self.language, self.size, self.id, self.url, self.codec, self.bitrate) + + def get_filename(self, filename, decrypted=False, fixed=False): + if not self.encrypted or decrypted: + fn = wvdl_cfg.DECRYPTED_FILENAME_AUDIO + else: + fn = wvdl_cfg.ENCRYPTED_FILENAME_AUDIO + if fixed: + fn = fn + '_fixed.mka' + return fn.format(filename=filename, language=self.language, track_type="audio", track_no=self.id) + +class SubtitleTrack(object): + def __init__(self, id, name, language_code, default, url, type): + self.id = id + self.name = name + self.language_code = language_code + self.url = url + self.type = type + self.default = default + + def __repr__(self): + return "(id={}, name={}, language_code={}, url={}, type={})".format(self.id, self.name, self.language_code, self.url, self.type) + + def get_filename(self, filename, subtitle_format): + return wvdl_cfg.SUBTITLES_FILENAME.format(filename=filename, language_code=self.language_code, id=self.id, subtitle_type=subtitle_format) \ No newline at end of file diff --git a/pywidevine/downloader/wvdownloader.py b/pywidevine/downloader/wvdownloader.py new file mode 100644 index 0000000..e4622c8 --- /dev/null +++ b/pywidevine/downloader/wvdownloader.py @@ -0,0 +1,854 @@ +import logging +import threading +import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg +from pywidevine.decrypt.wvdecryptconfig import WvDecryptConfig +from pywidevine.decrypt.wvdecrypt import WvDecrypt +from tqdm import tqdm +import requests +import pycaption +import pysubs2 +import subprocess +import os +import shutil +import base64 +import time +import binascii + + + + +class WvDownloader(object): + + def __init__(self, config): + self.client = config.client + self.filename = config.filename + self.config = config + self.logger = logging.getLogger(__name__) + self.threads = None + + def get_track_download_thread(self, track, bar_position): + self.logger.debug("creating thread for {}_{}".format(track.get_type(), track.id)) + + if track.encrypted: + output_file = wvdl_cfg.ENCRYPTED_FILENAME + else: + output_file = wvdl_cfg.DECRYPTED_FILENAME + output_file = output_file.format(filename=self.filename, track_type=track.get_type(), track_no=track.id) + + output_dir = output_file.split("\\")[0] + output_name = output_file.split("\\")[1] + + file_size = track.size + self.logger.debug("file size {}".format(file_size)) + + def do_download(): + """ + pbar = tqdm(desc='{}_{}'.format(track.get_type(), track.id), total=int(file_size), unit="bytes", unit_scale=True, position=bar_position) + downloaded_size = 0 + with open(output_file, 'wb') as fd: + try: + r = self.client.get_track_download(track) + for chunk in r.iter_content(1024): + fd.write(chunk) + downloaded_size += len(chunk) + pbar.update(len(chunk)) + except requests.RequestException as e: + self.logger.debug("requests download error for track {}_{}, exiting".format(track.get_type(), track.id)) + exit(1) + except: + exit(1) + pbar.close() + """ + aria2_p = subprocess.run(["binaries\\aria2c_nf", "-x16", "-s16", track.url, f"--dir={output_dir}", f"--out={output_name}"]) + return aria2_p.returncode + return threading.Thread(target=do_download) + + + + def get_track_download_thread_audio(self, track, bar_position): + + language = track.language + #.replace("English [Original]", "English") + + #if track.language == "English [Original]": + # track.language = "English" + self.logger.debug("creating thread for {}_{}".format(track.get_type(), track.id)) + + if track.encrypted: + output_file = wvdl_cfg.ENCRYPTED_FILENAME_AUDIO + else: + output_file = wvdl_cfg.DECRYPTED_FILENAME_AUDIO + output_file = output_file.format(filename=self.filename, language=language, track_type=track.get_type(), track_no=track.id) + + output_dir = output_file.split("\\")[0] + output_name = output_file.split("\\")[1] + + #output_file = fn.format(filename=self.filename, language=language, track_type="audio", track_no=track.id) + file_size = track.size + self.logger.debug("file size {}".format(file_size)) + + def do_download(): + """ + pbar = tqdm(desc='{}_{}'.format(track.get_type(), track.id), total=int(file_size), unit="bytes", unit_scale=True, position=bar_position) + downloaded_size = 0 + with open(output_file, 'wb') as fd: + try: + r = self.client.get_track_download(track) + for chunk in r.iter_content(1024): + fd.write(chunk) + downloaded_size += len(chunk) + pbar.update(len(chunk)) + except requests.RequestException as e: + self.logger.debug("requests download error for track {}_{}, exiting".format(track.get_type(), track.id)) + exit(1) + except: + exit(1) + pbar.close() + """ + aria2_p = subprocess.run(["binaries\\aria2c_nf", "-x16", "-s16", track.url, f"--dir={output_dir}", f"--out={output_name}"]) + return aria2_p.returncode + return threading.Thread(target=do_download) + + + def find_str(self, s, char): + index = 0 + if char in s: + c = char[0] + for ch in s: + if ch == c and s[index:index + len(char)] == char: + return index + index += 1 + + return -1 + + def Get_PSSH(self, mp4_file): + currentFile = __file__ + realPath = os.path.realpath(currentFile) + dirPath = os.path.dirname(realPath) + dirName = os.path.basename(dirPath) + mp4dump = dirPath + "/binaries/mp4dump.exe" + WV_SYSTEM_ID = '[ed ef 8b a9 79 d6 4a ce a3 c8 27 dc d5 1d 21 ed]' + pssh = None + data = subprocess.check_output([mp4dump, '--format', 'json', '--verbosity', '1', mp4_file]) + data = json.loads(data) + for atom in data: + if atom['name'] == 'moov': + for child in atom['children']: + if child['name'] == 'pssh' and child['system_id'] == WV_SYSTEM_ID: + pssh = child['data'][1:-1].replace(' ', '') + pssh = binascii.unhexlify(pssh) + #if pssh.startswith('\x08\x01'): + # pssh = pssh[0:] + pssh = pssh[0:] + pssh = base64.b64encode(pssh).decode('utf-8') + return pssh + + def do_decrypt(self, config): + wvdecrypt = WvDecrypt(config) + chal = wvdecrypt.get_challenge() + #sess_id = wvdecrypt.get_sid() + license_b64 = self.client.get_license(chal, '123456') + if not license_b64: + return False + wvdecrypt.update_license(license_b64) + wvdecrypt.start_process() + return True + + def download_and_convert_subtitle(self, subtitle): + language_code = subtitle.language_code + id = subtitle.id + self.logger.info("downloading {}_{} subtitles".format(language_code, id)) + output_filename = wvdl_cfg.SUBTITLES_FILENAME.format(filename=self.filename, language_code=language_code, id=id, subtitle_type=self.config.subtitle_format) + print(output_filename) + print(subtitle) + subtitle_text = self.client.get_subtitle_download(subtitle).text + subtitle_text = self.client.finagle_subs(subtitle_text) + if subtitle.type == "dfxp": + srt_subs = pycaption.SRTWriter().write(pycaption.DFXPReader().read(subtitle_text.replace('tt:', ''))) + elif subtitle.type == "srt": + srt_subs = subtitle_text + else: + self.logger.error("subtitle error") + exit(1) + if self.config.subtitle_format == 'srt': + srt_subs = srt_subs.replace('&', '&') + with open(output_filename, 'w', encoding='utf-8') as f: + f.write(srt_subs) + elif self.config.subtitle_format == 'ass': + ass_subs = pysubs2.SSAFile.from_string(srt_subs) + # you can modify ass_subs to change the output format/style here + # eg + # ass_subs.styles['Default'].fontname = 'That terrible font HS uses' + # see https://github.com/tkarabela/pysubs2/blob/master/pysubs2/ssastyle.py etc + ass_subs.styles['Default'].fontname = 'Open Sans Semibold' + ass_subs.styles['Default'].fontsize = 36 + ass_subs.styles['Default'].outlinecolor = pysubs2.Color(19,7,2,0) + ass_subs.styles['Default'].outline = 1.7 + ass_subs.styles['Default'].shadow = 0 + ass_subs.styles['Default'].marginl = 0 + ass_subs.styles['Default'].marginr = 0 + ass_subs.styles['Default'].marginv = 28 + ass_subs.info.update({'PlayResX': 848}) + ass_subs.info.update({'PlayResY': 480}) + ass_subs.save(output_filename) + else: + self.logger.error("unknown subtitle output format") + exit(1) + + def do_ffmpeg_fix(self, track): + ffmpeg_command = [wvdl_cfg.FFMPEG_BINARY_PATH, + "-i", + track.get_filename(self.filename, decrypted=True), + "-map_metadata", + "-1", + "-codec", + "copy", + track.get_filename(self.filename, decrypted=True, fixed=True)] + subprocess.run(ffmpeg_command) + + def do_merge(self, vt, ats, sts): + #exit(1) + if self.client.needs_ffmpeg(): + vfn = vt.get_filename(self.filename, decrypted=True, fixed=True) + else: + vfn = vt.get_filename(self.filename, decrypted=True) + + for audio_track in ats: + if 'ddplus-atmos-dash' in audio_track.codec: + audiocodec_file = 'DD+5.1.Atmos' + if 'heaac-2-dash' in audio_track.codec: + audiocodec_file = 'AAC2.0' + if 'ddplus-2.0-dash' in audio_track.codec: + audiocodec_file = 'DD+2.0' + if 'ddplus-2.0-dash' in audio_track.codec: + audiocodec_file = 'DD+2.0' + if 'ddplus-5.1-dash' in audio_track.codec: + audiocodec_file = 'DD+5.1' + if 'ddplus-5.1hq-dash' in audio_track.codec: + audiocodec_file = 'DD+5.1' + + filename_audiocodec = self.filename.replace('AUDIOCODEC', audiocodec_file) + filename_audiocodec_fixed = filename_audiocodec + '_fixed' + filename_audiocodec_fixed1 = filename_audiocodec + '_fixed1' + + #self.config1 = config + #filename = self.config1.filename + '_' + self.config1.tracktype + '_' + str(self.config1.trackno) + '_' + + currentFile = __file__ + realPath = os.path.realpath(currentFile) + realPath = realPath.replace('pywidevine\\downloader\\wvdownloader.py', '') + dirPath = os.path.dirname(realPath) + dirName = os.path.basename(dirPath) + wvDecrypterexe = dirPath + '/binaries/wvDecrypter/wvDecrypter.exe' + challengeBIN = dirPath + '/binaries/wvDecrypter/challenge.bin' + licenceBIN = dirPath + '/binaries/wvDecrypter/licence.bin' + mp4dump = dirPath + "/binaries/mp4dump.exe" + TEMP_FOLDER = dirPath + '/temp' + + + #if 'h264' in self.filename: + # print('x264x624x264x264') + # DECRYPTED_FILENAME = os.path.join(TEMP_FOLDER, self.filename + 'decrypted.264') + if 'h265' in self.filename: + print('x265x265x265x265') + vfn = vfn.replace('264', 'h265') + #print(self.filename) + #print(wvdl_cfg.MUXED_FILENAME.format(filename=DECRYPTED_FILENAME)) + mkvmerge_command = [wvdl_cfg.MKVMERGE_BINARY_PATH, + "--compression", + "-1:none", + "--no-global-tags", + "--output", + wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec), + "--language", + "0:und", + "(", + vfn, + ")"] + for audio_track in ats: + if self.client.needs_ffmpeg(): + fn = audio_track.get_filename(self.filename, decrypted=True, fixed=True) + else: + fn = audio_track.get_filename(self.filename, decrypted=True) + audio_lang_dict = { + 'English': 'eng', + 'Spanish': 'spa', + 'European Spanish': 'spa', + 'Brazilian Portuguese': 'por', + 'Polish': 'pol', + 'Turkish': 'tur', + 'French': 'fre', + 'German': 'ger', + 'Italian': 'ita', + 'Czech': 'cze', + 'Japanese': 'jpn', + 'Hebrew': 'heb', + 'Norwegian': 'nor', + 'Swedish': 'swe', + 'Arabic': 'ara', + 'Dutch': 'dut', + 'Flemish': 'dut' + } + if audio_track.language and audio_track.language in audio_lang_dict: + lang = '0:{}'.format(audio_lang_dict[audio_track.language]) + else: + lang = '0:und' + mkvmerge_command = mkvmerge_command + ["--compression", + "-1:none", + "--no-global-tags", + "--language", + lang, + "(", + fn, + ")"] + + #https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes + for subtitle_track in sts: + subtitle_lang_dict = { + 'en': 'eng', + 'es': 'spa', + 'es-ES': 'spa', + 'fr': 'fre', + 'de': 'ger', + 'it': 'ita', + 'pt-BR': 'por', + 'nl-BE': 'dut', + 'pl': 'pol', + 'fi': 'fin', + 'tl': 'tgl', + 'cs': 'cze', + 'zxx': 'zxx', + 'es-ES': 'spa', + 'nl': 'dut', + 'nb': 'nor', + 'da': 'dan', + 'pt': 'por', + 'pl': 'pol', + 'sv': 'swe', + 'fi': 'fin', + 'tr': 'tur', + 'he': 'heb', + 'ru': 'rus', + 'hu': 'hun', + 'id': 'ind', + 'el': 'ell', + 'ar': 'ara', + } + if subtitle_track.language_code and subtitle_track.language_code in subtitle_lang_dict: + lang = '0:{}'.format(subtitle_lang_dict[subtitle_track.language_code]) + else: + lang = '0:und' + + if subtitle_track.name == 'de': + track_name = 'German_Full' + if subtitle_track.name == 'en': + track_name = 'English_Full' + if subtitle_track.name == 'it': + track_name = 'Italian_Full' + if subtitle_track.name == 'es': + track_name = 'Spanish_Full' + if subtitle_track.name == 'es-ES': + track_name = 'Spanish_Full' + if subtitle_track.name == 'fr': + track_name = 'French_Full' + if subtitle_track.name == 'pl': + track_name = 'Polish_Full' + if subtitle_track.name == 'jp': + track_name = 'Japanese_Full' + if subtitle_track.name == 'tr': + track_name = 'Turkish_Full' + if subtitle_track.name == 'pt-BR': + track_name = 'Brazilian.Portuguese_Full' + if subtitle_track.name == 'da': + track_name = 'Danish_Full' + if subtitle_track.name == 'nb': + track_name = 'Norwegian_Full' + if subtitle_track.name == 'sv': + track_name = 'Swedish_Full' + if subtitle_track.name == 'ar': + track_name = 'Arabic_Full' + if subtitle_track.name == 'nl-BE': + track_name = 'Flemish_Full' + + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'de': + track_name = 'German_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'en': + track_name = 'English_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'it': + track_name = 'Italian_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'es': + track_name = 'Spanish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'es-ES': + track_name = 'Spanish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'fr': + track_name = 'French_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'pl': + track_name = 'Polish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'jp': + track_name = 'Japanese_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'tr': + track_name = 'Turkish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'pt-BR': + track_name = 'Brazilian.Portuguese_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'da': + track_name = 'Danish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'nb': + track_name = 'Norwegian_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'sv': + track_name = 'Swedish_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'ar': + track_name = 'Arabic_Forced' + if subtitle_track.name == 'Forced' and subtitle_track.language_code == 'nl-BE': + track_name = 'Flemish_Forced' + + + """ + if subtitle_track.default: + mkvmerge_command = mkvmerge_command + ["--compression", + "-1:none", + "--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:yes", + "--forced-track", + "0:yes", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + else: + mkvmerge_command = mkvmerge_command + ["--compression", + "-1:none", + "--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + """ + + + if subtitle_track.default: + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:yes", + "--forced-track", + "0:yes", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'en': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'it': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'es': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'es-ES': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'it': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'pl': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'jp': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'tr': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'pt-BR': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'da': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'nb': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'sv': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'ar': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + elif subtitle_track.name == 'Forced' and subtitle_track.language_code == 'nl-BE': + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + else: + mkvmerge_command = mkvmerge_command + ["--language", + lang, + "--sub-charset", + "0:UTF-8", + "--track-name", + #"0:{}".format(subtitle_track.name), + "0:{}".format( track_name), + "--default-track", + "0:no", + "--forced-track", + "0:no", + "(", + subtitle_track.get_filename(self.filename, self.config.subtitle_format), + ")"] + + + + if self.config.subtitle_format == 'ass': + mkvmerge_command = mkvmerge_command + ["--attachment-mime-type", + "application/x-truetype-font", + "--attachment-name", + "OpenSans-Semibold.ttf", + "--attach-file", + "./fonts/OpenSans-Semibold.ttf"] + + subprocess.run(mkvmerge_command) + + + """ + mkvmerge_command_fixed = [wvdl_cfg.MKVMERGE_BINARY_PATH, + "--compression", + "-1:none", + "--no-attachments", + "--no-track-tags", + "--no-global-tags", + "--disable-track-statistics-tags", + "--output", + wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec_fixed), + "(", + wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec), + ")"] + + subprocess.run(mkvmerge_command_fixed) + + os.remove(wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec)) + + mkvmerge_command_fixed1 = [wvdl_cfg.MKVMERGE_BINARY_PATH, + "--compression", + "-1:none", + "--output", + wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec_fixed1), + "(", + wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec_fixed), + ")"] + + subprocess.run(mkvmerge_command_fixed1) + + os.remove(wvdl_cfg.MUXED_FILENAME.format(filename=filename_audiocodec_fixed)) + """ + + def run(self): + self.logger.info("wvdownloader starting") + self.logger.info("logging client in") + if self.client.login(): + self.logger.info("login successful") + else: + self.logger.error("login failed, please check credentials") + exit(1) + self.logger.info("getting track and widevine init data") + print(self.config.quality) + success, data = self.client.get_track_and_init_info(self.config.quality, self.config.profile) + if not success: + self.logger.error("get_track_and_init_info failed") + exit(1) + self.logger.info("track info and init data retrieved") + if self.config.print_info: + self.logger.info("info mode done, quitting") + exit(0) + + vt, ats, sts, init_data_b64, cert_data_b64, device = data + if not self.config.license: + self.logger.info("downloading subtitles") + #subs + self.logger.debug("requested output format {}".format(self.config.subtitle_format)) + for subtitle in sts: + self.download_and_convert_subtitle(subtitle) + self.logger.info("all subtitles downloaded, merging") + if self.config.subs_only: + self.logger.info("subs downloaded, quitting") + exit(0) + self.logger.info("creating video & audio track download threads") + threads = [] + threads.append(self.get_track_download_thread(vt, 0)) + for i, track in enumerate(ats): + threads.append(self.get_track_download_thread_audio(track, i+1)) + self.logger.info("starting video&audio downloads") + self.threads = threads + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.logger.info("video and audio tracks downloaded successfully") + self.logger.info("decrypting encrypted tracks") + self.logger.info("note: does not do this in parallel since we're IO bound anyway") + enc_tracks = [x for x in [vt] + ats if x.encrypted] + for track in enc_tracks: + wvdecrypt_config = WvDecryptConfig(self.filename, track.get_type(), track.id, self.config.license, + init_data_b64, device, cert_data_b64=cert_data_b64) + if self.config.gf is not None and self.client.client_config.config['region'] != 'us': + curr_region = self.config.gf.region_get('prime') + if self.client.client_config.config['region'] == 'uk' and curr_region != 'GB': + self.config.gf.region_set('prime','GB') + elif self.client.client_config.config['region'].upper() != curr_region and self.client.client_config.config['region'] != 'uk': + self.config.gf.region_set('prime',self.client.client_config.config['region'].upper()) + try: + if not self.do_decrypt(wvdecrypt_config): + return False + except: + if self.config.gf is not None and self.client.client_config.config['region'] != 'us': + curr_region = self.config.gf.region_get('prime') + if self.client.client_config.config['region'] == 'uk' and curr_region != 'GB': + self.config.gf.region_set('prime','GB') + elif self.client.client_config.config['region'].upper() != curr_region and self.client.client_config.config['region'] != 'uk': + self.config.gf.region_set('prime',self.client.client_config.config['region'].upper()) + if not self.do_decrypt(wvdecrypt_config): + return False + + if self.config.license: + return True + else: + self.logger.info("all decrypting complete") + + if self.client.needs_ffmpeg(): + self.logger.info("processing mp4s with ffmpeg to fix the headers") + #hdr hevc dv no ffmpeg + + self.do_ffmpeg_fix(vt) + for track in ats: + self.do_ffmpeg_fix(track) + + #self.config.dont_mux = False + if self.config.dont_mux: + self.logger.info('moving tracks instead of muxing') + #hdr hevc dv no ffmpeg fix + if self.client.needs_ffmpeg(): + vfn = vt.get_filename(self.filename, decrypted=True, fixed=True) + else: + vfn = vt.get_filename(self.filename, decrypted=True) + shutil.move(vfn, vfn.replace(wvdl_cfg.TEMP_FOLDER, wvdl_cfg.OUTPUT_FOLDER)) + for audio_track in ats: + if self.client.needs_ffmpeg(): + fn = audio_track.get_filename(self.filename, decrypted=True, fixed=True) + else: + fn = audio_track.get_filename(self.filename, decrypted=True) + shutil.move(fn, fn.replace(wvdl_cfg.TEMP_FOLDER, wvdl_cfg.OUTPUT_FOLDER)) + for subtitle_track in sts: + fn = subtitle_track.get_filename(self.filename, self.config.subtitle_format) + shutil.move(fn, fn.replace(wvdl_cfg.TEMP_FOLDER, wvdl_cfg.OUTPUT_FOLDER)) + else: + self.do_merge(vt, ats, sts) + self.logger.info("file written, cleaning up temp") + if self.config.skip_cleanup: + self.logger.info('skipping clean') + return True + file_list = [f for f in os.listdir(wvdl_cfg.TEMP_FOLDER)] + for f in file_list: + if f.startswith("{}_".format(self.filename)): + os.remove(os.path.join(wvdl_cfg.TEMP_FOLDER,f)) + self.logger.info("cleaned up temp") + return True + + + diff --git a/pywidevine/downloader/wvdownloaderconfig.py b/pywidevine/downloader/wvdownloaderconfig.py new file mode 100644 index 0000000..d44fab5 --- /dev/null +++ b/pywidevine/downloader/wvdownloaderconfig.py @@ -0,0 +1,59 @@ +import re +import os +import platform + +# constants + +BINARIES_FOLDER = 'binaries' +COOKIES_FOLDER = 'cookies' +TEMP_FOLDER = 'temp' +OUTPUT_FOLDER = 'output' + +MP4DECRYPT_BINARY = 'mp4decrypt' +MKVMERGE_BINARY = 'mkvmerge' +MP4DUMP_BINARY = 'mp4dump' +FFMPEG_BINARY = 'avconv' + +if platform.system() == 'Windows': + MP4DECRYPT_BINARY = 'mp4decrypt.exe' + MKVMERGE_BINARY = 'mkvmerge.exe' + MP4DUMP_BINARY = 'mp4dump.exe' + #FFMPEG_BINARY = 'avconv.exe' + FFMPEG_BINARY = 'ffmpeg.exe' + +MP4DECRYPT_BINARY_PATH = os.path.join(BINARIES_FOLDER, MP4DECRYPT_BINARY) +MKVMERGE_BINARY_PATH = os.path.join(BINARIES_FOLDER, MKVMERGE_BINARY) +MP4DUMP_BINARY_PATH = os.path.join(BINARIES_FOLDER, MP4DUMP_BINARY) +FFMPEG_BINARY_PATH = os.path.join(BINARIES_FOLDER, FFMPEG_BINARY) + +MP4DUMP_REGEX = re.compile(b"sample info count = (\d+)") + +BASE_TRACK_FILENAME = '{filename}_{track_type}_{track_no}_' +BASE_TRACK_FILENAME_AUDIO = '{filename}_{track_type}_{track_no}_{language}_' + + +ENCRYPTED_FILENAME = os.path.join(TEMP_FOLDER, BASE_TRACK_FILENAME + 'encrypted.mp4') +#DECRYPTED_FILENAME = os.path.join(TEMP_FOLDER, BASE_TRACK_FILENAME + 'decrypted.mp4') + +DECRYPTED_FILENAME = os.path.join(TEMP_FOLDER, BASE_TRACK_FILENAME + 'decrypted.mp4') + +ENCRYPTED_FILENAME_AUDIO = os.path.join(TEMP_FOLDER, BASE_TRACK_FILENAME_AUDIO + 'encrypted.mp4') +DECRYPTED_FILENAME_AUDIO = os.path.join(TEMP_FOLDER, BASE_TRACK_FILENAME_AUDIO + 'decrypted.mp4') + +SUBTITLES_FILENAME = os.path.join(TEMP_FOLDER, '{filename}_subtitles_{language_code}_{id}.{subtitle_type}') +MUXED_FILENAME = os.path.join(OUTPUT_FOLDER, '{filename}.mkv') + + +class WvDownloaderConfig(object): + def __init__(self, client, filename, subtitle_format, print_info, skip_cleanup, dont_mux, subs_only, license, quality, profile, gf=None): + self.client = client + self.filename = filename + self.subtitle_format = subtitle_format + self.print_info = print_info + self.skip_cleanup = skip_cleanup + self.dont_mux = dont_mux + self.subs_only = subs_only + self.license = license + self.quality = quality + self.profile = profile + self.gf = gf diff --git a/pywidevine/getflix/__init__.py b/pywidevine/getflix/__init__.py new file mode 100644 index 0000000..3dfc78f --- /dev/null +++ b/pywidevine/getflix/__init__.py @@ -0,0 +1 @@ +"""placeholder""" \ No newline at end of file diff --git a/pywidevine/getflix/__pycache__/__init__.cpython-36.pyc b/pywidevine/getflix/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..d0ea6c3 Binary files /dev/null and b/pywidevine/getflix/__pycache__/__init__.cpython-36.pyc differ diff --git a/pywidevine/getflix/__pycache__/getflix.cpython-36.pyc b/pywidevine/getflix/__pycache__/getflix.cpython-36.pyc new file mode 100644 index 0000000..c201f7d Binary files /dev/null and b/pywidevine/getflix/__pycache__/getflix.cpython-36.pyc differ diff --git a/pywidevine/getflix/getflix.py b/pywidevine/getflix/getflix.py new file mode 100644 index 0000000..3fc03e1 --- /dev/null +++ b/pywidevine/getflix/getflix.py @@ -0,0 +1,142 @@ +"""Hijack urllib3's dns resolver and getflix.com.au api""" +from socket import error as SocketError, timeout as SocketTimeout +import json +import logging +import time + +from urllib3.connection import HTTPConnection +from urllib3.util import connection +from urllib3.exceptions import ConnectTimeoutError +from urllib3.exceptions import NewConnectionError +import requests +import dns.resolver + +GETFLIX_DNSSERV = ['54.164.176.2', '54.187.61.200'] + +def getflix_new_conn(self): + """ Establish a socket connection and set nodelay settings on it. + :return: New socket connection. + """ + extra_kw = {} + if self.source_address: + extra_kw['source_address'] = self.source_address + + if self.socket_options: + extra_kw['socket_options'] = self.socket_options + + hostname = getflix_lookup(self.host) + try: + conn = connection.create_connection( + (hostname, self.port), self.timeout, **extra_kw) + + except SocketTimeout as err: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + except SocketError as err: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % err) + + return conn + +def getflix_lookup(host): + """resolve a dns address""" + res = dns.resolver.Resolver() + res.nameservers = GETFLIX_DNSSERV + answers = res.query(host, 'A') + for rdata in answers: + return str(rdata) + +class Getflix(object): + """interface for getflix""" + + API_URL = 'https://www.getflix.com.au/api/' + ENDPOINTS = { + 'region': 'v1/regions.json', + 'region_list': 'v1/regions/list.json', + 'ip': 'v1/addresses.json', + 'profile': 'v1/profile.json', + 'subscription': 'v1/subscription.json', + 'system': 'v1/system.json', + } + + _old_conn = None + + def __init__(self, apikey): + """set auth information""" + self.logger = logging.getLogger(__name__) + self.auth = (apikey, 'x') + + def enable(self): + """enable getflix lookups""" + self.logger.info("hijacking dns lookups") + self.logger.debug("saving old HTTPConnection._new_conn: {}".format(HTTPConnection._new_conn)) + self._old_conn = HTTPConnection._new_conn + self.logger.debug("setting new HTTPConnection._new_conn: {}".format(getflix_new_conn)) + HTTPConnection._new_conn = getflix_new_conn + + def disable(self): + """disable getflix lookups""" + self.logger.debug("restoring HTTPConnection._new_conn") + HTTPConnection._new_conn = self._old_conn + + def lookup(self, host): + """perform a getflix lookup""" + self.logger.info("looking up address") + return getflix_lookup(host) + + def region_list(self): + """return getflix region list""" + req = requests.get(self.API_URL+self.ENDPOINTS['region_list'], + auth=self.auth) + return json.loads(req.text) + + def region_get(self, curr_service): + """get the current region""" + while True: + try: + req = requests.get(self.API_URL+self.ENDPOINTS['region'], + auth=self.auth) + break + except: + time.sleep(10) + continue + for service in json.loads(req.text): + if service['service'] == curr_service: + if service['region'] == 'GB': + return 'UK' + else: + return service['region'] + return None + + def region_set(self, service, region): + """set the region""" + self.logger.info("updating getflix region for service {} to {}".format(service, region)) + if service == 'prime' and region == 'UK': + region = 'GB' + data = {'service': service, 'region': region} + req = requests.post(self.API_URL+self.ENDPOINTS['region'], + data=json.dumps(data), + auth=self.auth) + resp = json.loads(req.text) + try: + if resp['region'] == region: + return True + else: + self.logger.error("updating getflix region failed") + return False + except: + self.logger.error("updating getflix region failed") + return False + + def update_ip(self): + """updates auth'd ip""" + self.logger.info("updating getflix ip") + req = requests.put(self.API_URL+self.ENDPOINTS['ip'], + auth=self.auth) + if req.status_code == 200: + return True + else: + self.logger.error("updating getflix ip failed") + return False diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..b8ed757 --- /dev/null +++ b/readme.txt @@ -0,0 +1,2 @@ +python3.x +pip install wxpython diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fd63c7e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,25 @@ +astroid==1.5.3 +beautifulsoup4==4.4.1 +certifi==2017.4.17 +chardet==3.0.3 +colorama==0.3.9 +cssutils==1.0.2 +dnspython==1.15.0 +enum34==1.1.6 +future==0.16.0 +idna==2.5 +isort==4.2.14 +lazy-object-proxy==1.3.1 +lxml==3.8.0 +mccabe==0.6.1 +protobuf==3.0.0b2 +pycaption==1.0.0 +pycryptodomex==3.4.6 +pylint==1.7.1 +pysubs2==0.2.1 +requests==2.17.3 +six==1.10.0 +tqdm==4.14.0 +urllib3==1.21.1 +wrapt==1.10.10 +xmltodict==0.11.0