class PluzzDLM3U8( object ): """ Telechargement des liens m3u8 """ def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ): self.m3u8URL = m3u8URL self.nomFichier = nomFichier self.navigateur = navigateur self.stopDownloadEvent = stopDownloadEvent self.progressFnct = progressFnct self.historique = Historique() self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] ) def ouvrirNouvelleVideo( self ): """ Creer une nouvelle video """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "wb" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) # Ajout de l'en-tête # Fait dans creerMKV def ouvrirVideoExistante( self ): """ Ouvre une video existante """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "a+b" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) def creerMKV( self ): """ Creer un mkv a partir de la video existante (cree l'en-tete de la video) """ logger.info( "Création du fichier MKV (vidéo finale) ; veuillez attendre quelques instants" ) try: if( os.name == "nt" ): commande = "ffmpeg.exe -i %s -vcodec copy -acodec copy %s 1>NUL 2>NUL" % ( self.nomFichier, self.nomFichierFinal ) else: commande = "ffmpeg -i %s -vcodec copy -acodec copy %s 1>/dev/null 2>/dev/null" % ( self.nomFichier, self.nomFichierFinal ) if( os.system( commande ) == 0 ): os.remove( self.nomFichier ) logger.info( "Fin !" ) else: logger.warning( "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % ( self.nomFichier ) ) except: raise PluzzDLException( "Impossible de créer la vidéo finale" ) def telecharger( self ): # Recupere le fichier master.m3u8 self.m3u8 = self.navigateur.getFichier( self.m3u8URL ) # Extrait l'URL de base pour tous les fragments self.urlBase = "/".join( self.m3u8URL.split( "/" )[ :-1 ] ) # Recupere le lien avec le plus gros bitrate try: self.listeFragmentsURL = re.findall( ".+?\.m3u8.*", self.m3u8 )[ -1 ] if "://" not in self.listeFragmentsURL: self.listeFragmentsURL = "%s/%s" % ( self.urlBase, self.listeFragmentsURL ) except: raise PluzzDLException( "Impossible de trouver le lien vers la liste des fragments" ) # Recupere la liste des fragments self.listeFragmentsPage = self.navigateur.getFichier( self.listeFragmentsURL ) # Extrait l'URL de tous les fragments self.listeFragments = re.findall( ".+?\.ts", self.listeFragmentsPage ) # # Creation de la video # self.premierFragment = 1 self.telechargementFini = False video = self.historique.getVideo( self.listeFragmentsURL ) # Si la video est dans l'historique if( video is not None ): # Si la video existe sur le disque if( os.path.exists( self.nomFichier ) or os.path.exists( self.nomFichierFinal ) ): if( video.finie ): logger.info( "La vidéo a déjà été entièrement téléchargée" ) if( not os.path.exists( self.nomFichierFinal ) ): self.creerMKV() return else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) ) else: self.ouvrirNouvelleVideo() logger.info( u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) ) else: # Si la video n'est pas dans l'historique self.ouvrirNouvelleVideo() # Nombre de fragments self.nbFragMax = float( len( self.listeFragments ) ) logger.debug( "Nombre de fragments : %d" % ( self.nbFragMax ) ) # Ajout des fragments logger.info( "Début du téléchargement des fragments" ) try : i = self.premierFragment while( i <= self.nbFragMax and not self.stopDownloadEvent.isSet() ): fragURL = self.listeFragments[ i - 1 ] if "://" not in fragURL: fragURL = "%s/%s" % ( self.urlBase, fragURL ) frag = self.navigateur.getFichier( fragURL ) self.fichierVideo.write( frag ) # Affichage de la progression self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) ) i += 1 if( i == self.nbFragMax + 1 ): self.progressFnct( 100 ) self.telechargementFini = True logger.info( "Fin du téléchargement" ) self.creerMKV() except KeyboardInterrupt: logger.info( "Interruption clavier" ) except: logger.critical( "Erreur inconnue" ) finally : # Ajout dans l'historique self.historique.ajouter( Video( lien = self.listeFragmentsURL, fragments = i, finie = self.telechargementFini ) ) # Fermeture du fichier self.fichierVideo.close()
class PluzzDLF4M( object ): """ Telechargement des liens f4m """ adobePlayer = "http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf" def __init__( self, manifestURL, nomFichier, navigateur, stopDownloadEvent, progressFnct ): self.manifestURL = manifestURL self.nomFichier = nomFichier self.navigateur = navigateur self.stopDownloadEvent = stopDownloadEvent self.progressFnct = progressFnct self.historique = Historique() self.configuration = Configuration() self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" ) self.playerHash = self.configuration[ "player_hash" ] def parseManifest( self ): """ Parse le manifest """ try : arbre = xml.etree.ElementTree.fromstring( self.manifest ) # Duree self.duree = float( arbre.find( "{http://ns.adobe.com/f4m/1.0}duration" ).text ) self.pv2 = arbre.find( "{http://ns.adobe.com/f4m/1.0}pv-2.0" ).text media = arbre.findall( "{http://ns.adobe.com/f4m/1.0}media" )[ -1 ] # Bitrate self.bitrate = int( media.attrib[ "bitrate" ] ) # URL des fragments urlbootstrap = media.attrib[ "url" ] self.urlFrag = "%s%sSeg1-Frag" % ( self.manifestURLToken[ : self.manifestURLToken.find( "manifest.f4m" ) ], urlbootstrap ) # Header du fichier final self.flvHeader = base64.b64decode( media.find( "{http://ns.adobe.com/f4m/1.0}metadata" ).text ) except : raise PluzzDLException( "Impossible de parser le manifest" ) def ouvrirNouvelleVideo( self ): """ Creer une nouvelle video """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "wb" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) # Ajout de l'en-tête FLV self.fichierVideo.write( binascii.a2b_hex( "464c56010500000009000000001200010c00000000000000" ) ) # Ajout de l'header du fichier self.fichierVideo.write( self.flvHeader ) self.fichierVideo.write( binascii.a2b_hex( "00000000" ) ) # Padding pour avoir des blocs de 8 def ouvrirVideoExistante( self ): """ Ouvre une video existante """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "a+b" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) def decompressSWF( self, swfData ): """ Decompresse un fichier swf """ # Adapted from : # Prozacgod # http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=14693 if( type( swfData ) is str ): swfData = StringIO.StringIO( swfData ) swfData.seek( 0, 0 ) magic = swfData.read( 3 ) if( magic == "CWS" ): return "FWS" + swfData.read( 5 ) + zlib.decompress( swfData.read() ) else: return None def getPlayerHash( self ): """ Recupere le sha256 du player flash """ # Get SWF player playerData = self.navigateur.getFichier( "http://static.francetv.fr/players/Flash.H264/player.swf" ) # Uncompress SWF player playerDataUncompress = self.decompressSWF( playerData ) # Perform sha256 of uncompressed SWF player hashPlayer = hashlib.sha256( playerDataUncompress ).hexdigest() # Perform base64 return base64.encodestring( hashPlayer.decode( 'hex' ) ) def debutVideo( self, fragID, fragData ): """ Trouve le debut de la video dans un fragment """ # Skip fragment header start = fragData.find( "mdat" ) + 4 # For all fragment (except frag1) if( fragID > 1 ): # Skip 2 FLV tags for dummy in range( 2 ): tagLen, = struct.unpack_from( ">L", fragData, start ) # Read 32 bits (big endian) tagLen &= 0x00ffffff # Take the last 24 bits start += tagLen + 11 + 4 # 11 = tag header len ; 4 = tag footer len return start def telecharger( self ): # Verifie si le lien du manifest contient la chaine "media-secure" if( self.manifestURL.find( "media-secure" ) != -1 ): raise PluzzDLException( "pluzzdl ne sait pas gérer ce type de vidéo (utilisation de DRMs)..." ) # Lien du manifest (apres le token) self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" % ( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) ) # Recupere le manifest self.manifest = self.navigateur.getFichier( self.manifestURLToken ) # Parse le manifest self.parseManifest() # Calcul les elements self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ] self.pv20, self.hdntl = self.pv2.split( ";" ) self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash self.pvtoken = "pvtoken=%s~hmac=%s" % ( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() ) # # Creation de la video # self.premierFragment = 1 self.telechargementFini = False video = self.historique.getVideo( self.urlFrag ) # Si la video est dans l'historique if( video is not None ): # Si la video existe sur le disque if( os.path.exists( self.nomFichier ) ): if( video.finie ): logger.info( "La vidéo a déjà été entièrement téléchargée" ) return else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) ) else: self.ouvrirNouvelleVideo() logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) ) else: # Si la video n'est pas dans l'historique self.ouvrirNouvelleVideo() # Calcul l'estimation du nombre de fragments self.nbFragMax = round( self.duree / 6 ) logger.debug( "Estimation du nombre de fragments : %d" % ( self.nbFragMax ) ) # Ajout des fragments logger.info( "Début du téléchargement des fragments" ) try : i = self.premierFragment self.navigateur.appendCookie( "hdntl", self.hdntl ) while( not self.stopDownloadEvent.isSet() ): # frag = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) ) frag = self.navigateur.getFichier( "%s%d" % ( self.urlFrag, i ), referer = self.adobePlayer ) debut = self.debutVideo( i, frag ) self.fichierVideo.write( frag[ debut : ] ) # Affichage de la progression self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) ) i += 1 except urllib2.URLError, e : if( hasattr( e, 'code' ) ): if( e.code == 403 ): if( e.reason == "Forbidden" ): logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" ) newPlayerHash = self.getPlayerHash() if( newPlayerHash != self.playerHash ): self.configuration[ "player_hash" ] = newPlayerHash self.configuration.writeConfig() logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" ) else: logger.critical( "Pas de nouveau hash disponible..." ) else: logger.critical( "Impossible de charger la vidéo" ) elif( e.code == 404 ): self.progressFnct( 100 ) self.telechargementFini = True logger.info( "Fin du téléchargement" ) except KeyboardInterrupt: logger.info( "Interruption clavier" )
class PluzzDLM3U8( object ): """ Telechargement des liens m3u8 """ def __init__( self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct ): self.m3u8URL = m3u8URL self.nomFichier = nomFichier self.navigateur = navigateur self.stopDownloadEvent = stopDownloadEvent self.progressFnct = progressFnct self.historique = Historique() self.nomFichierFinal = "%s.mkv" % ( self.nomFichier[ :-3 ] ) def ouvrirNouvelleVideo( self ): """ Creer une nouvelle video """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "wb" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) # Ajout de l'en-tête # Fait dans creerMKV def ouvrirVideoExistante( self ): """ Ouvre une video existante """ try : # Ouverture du fichier self.fichierVideo = open( self.nomFichier, "a+b" ) except : raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) ) def creerMKV( self ): """ Creer un mkv a partir de la video existante (cree l'en-tete de la video) """ logger.info( "Création du fichier MKV (vidéo finale) ; veuillez attendre quelques instants" ) try: if( os.name == "nt" ): commande = "ffmpeg.exe -i %s -vcodec copy -acodec copy %s 1>NUL 2>NUL" % ( self.nomFichier, self.nomFichierFinal ) else: commande = "ffmpeg -i %s -vcodec copy -acodec copy %s 1>/dev/null 2>/dev/null" % ( self.nomFichier, self.nomFichierFinal ) if( os.system( commande ) == 0 ): os.remove( self.nomFichier ) logger.info( "Fin !" ) else: logger.warning( "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % ( self.nomFichier ) ) except: raise PluzzDLException( "Impossible de créer la vidéo finale" ) def telecharger( self ): # Recupere le fichier master.m3u8 self.m3u8 = self.navigateur.getFichier( self.m3u8URL ) # Extrait l'URL de base pour tous les fragments self.urlBase = "/".join( self.m3u8URL.split( "/" )[ :-1 ] ) # Recupere le lien avec le plus gros bitrate try: self.listeFragmentsURL = "%s/%s" % ( self.urlBase, re.findall( ".+?\.m3u8.*", self.m3u8 )[ -1 ] ) except: raise PluzzDLException( "Impossible de trouver le lien vers la liste des fragments" ) # Recupere la liste des fragments self.listeFragmentsPage = self.navigateur.getFichier( self.listeFragmentsURL ) # Extrait l'URL de tous les fragments self.listeFragments = re.findall( ".+?\.ts", self.listeFragmentsPage ) # # Creation de la video # self.premierFragment = 1 self.telechargementFini = False video = self.historique.getVideo( self.listeFragmentsURL ) # Si la video est dans l'historique if( video is not None ): # Si la video existe sur le disque if( os.path.exists( self.nomFichier ) or os.path.exists( self.nomFichierFinal ) ): if( video.finie ): logger.info( "La vidéo a déjà été entièrement téléchargée" ) if( not os.path.exists( self.nomFichierFinal ) ): self.creerMKV() return else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info( "Reprise du téléchargement de la vidéo au fragment %d" % ( video.fragments ) ) else: self.ouvrirNouvelleVideo() logger.info( u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier ) ) else: # Si la video n'est pas dans l'historique self.ouvrirNouvelleVideo() # Nombre de fragments self.nbFragMax = float( len( self.listeFragments ) ) logger.debug( "Nombre de fragments : %d" % ( self.nbFragMax ) ) # Ajout des fragments logger.info( "Début du téléchargement des fragments" ) try : i = self.premierFragment while( i <= self.nbFragMax and not self.stopDownloadEvent.isSet() ): frag = self.navigateur.getFichier( "%s/%s" % ( self.urlBase, self.listeFragments[ i - 1 ] ) ) self.fichierVideo.write( frag ) # Affichage de la progression self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) ) i += 1 if( i == self.nbFragMax + 1 ): self.progressFnct( 100 ) self.telechargementFini = True logger.info( "Fin du téléchargement" ) self.creerMKV() except KeyboardInterrupt: logger.info( "Interruption clavier" ) except: logger.critical( "Erreur inconnue" ) finally : # Ajout dans l'historique self.historique.ajouter( Video( lien = self.listeFragmentsURL, fragments = i, finie = self.telechargementFini ) ) # Fermeture du fichier self.fichierVideo.close()
class DlM3u8(Downloader): """ Téléchargement des liens m3u8 """ def __init__(self, m3u8Url, outDir, codeProgramme, timeStamp, navigateur, stopDownloadEvent, progressFnct): self.m3u8Url = m3u8Url super(DlM3u8, self).__init__(outDir, codeProgramme, timeStamp, "ts", navigateur, stopDownloadEvent, progressFnct) self.historique = Historique() def telecharger(self): # Récupère le fichier master.m3u8 self.m3u8 = self.navigateur.getFichier(self.m3u8Url) # Extrait l'URL de tous les fragments self.listeFragments = re.findall(".+?\.ts", self.m3u8) # # Création de la vidéo # self.premierFragment = 1 self.telechargementFini = False video = self.historique.getVideo(self.m3u8Url) # Si la vidéo est dans l'historique if(video is not None): # Si la vidéo existe sur le disque if(os.path.exists(self.nomFichier)): if(video.finie): logger.info("La vidéo a déjà été entièrement téléchargée") return else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info("Reprise du téléchargement de la vidéo au fragment %d" % (video.fragments)) else: self.ouvrirNouvelleVideo() logger.info("Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % (self.nomFichier)) else: # Si la vidéo n'est pas dans l'historique self.ouvrirNouvelleVideo() # Nombre de fragments self.nbFragMax = float(len(self.listeFragments)) logger.debug("Nombre de fragments: %d" % (self.nbFragMax)) # Ajout des fragments logger.info("Début du téléchargement des fragments") try: i = self.premierFragment while(i <= self.nbFragMax and not self.stopDownloadEvent.isSet()): frag = self.navigateur.getFichier("%s" % ( self.listeFragments[i - 1])) self.fichierVideo.write(frag) # Affichage de la progression self.progressFnct(min(int((i / self.nbFragMax) * 100), 100)) i += 1 if(i == self.nbFragMax + 1): self.progressFnct(100) self.telechargementFini = True logger.info("Fin du téléchargement") except KeyboardInterrupt: logger.info("Interruption clavier") except Exception as inst: logger.critical("Erreur inconnue %s" % inst) finally: # Ajout dans l'historique self.historique.ajouter(Video(lien = self.m3u8Url, fragments = i, finie = self.telechargementFini)) # Fermeture du fichier self.fichierVideo.close()
class PluzzDL( object ): def __init__( self, url, useFragments = False, proxy = None, resume = False, progressFnct = lambda x : None, stopDownloadEvent = threading.Event(), outDir = ".", manifest = False, playlist = False ): self.url = url self.useFragments = useFragments self.proxy = proxy self.resume = resume self.progressFnct = progressFnct self.stopDownloadEvent = stopDownloadEvent self.outDir = outDir self.navigateur = Navigateur( self.proxy ) self.historique = Historique() self.configuration = Configuration() self.lienMMS = None self.lienRTMP = None self.manifestURL = None self.drm = None if playlist: self.mode = "playlist" self.ext = "ts" else: self.mode = "manifest" self.ext = "flv" self.hmacKey = self.configuration[ "hmac_key" ].decode( "hex" ) self.playerHash = self.configuration[ "player_hash" ] if( re.match( "http://www.pluzz.fr/[^\.]+?\.html", self.url ) ): # Recupere l'ID de l'emission self.getID() # Recupere la page d'infos de l'emission self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) ) # Parse la page d'infos self.parseInfos() # Petit message en cas de DRM if( self.drm == "oui" ): logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" ) # Lien MMS trouve if( self.lienMMS is not None ): logger.info( "Lien MMS : %s\nUtiliser par exemple mimms ou msdl pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienMMS ) ) # Lien RTMP trouve if( self.lienRTMP is not None ): logger.info( "Lien RTMP : %s\nUtiliser par exemple rtmpdump pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienRTMP ) ) # N'utilise pas les fragments si cela n'a pas ete demande et que des liens directs ont ete trouves if( ( ( self.lienMMS is not None ) or ( self.lienRTMP is not None ) ) and not self.useFragments ): sys.exit( 0 ) if self.mode == "manifest": # Lien du manifest non trouve if( self.manifestURL is None ): logger.critical( "Pas de lien vers le manifest" ) sys.exit( -1 ) if self.mode == "playlist": # Lien de la playlist M3U8 non trouve if( self.playlistM3U8 is None ): logger.critical( "Pas de lien vers la playlist" ) sys.exit( -1 ) self.nomFichier = os.path.join( self.outDir, "%s.%s" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ], self.ext ) ) else: if self.mode == "manifest": page = self.navigateur.getFichier( self.url ) try: self.manifestURL = re.findall( "(http://.+?manifest.f4m)", page )[ 0 ] except: logger.critical( "Pas de lien vers le manifest" ) sys.exit( -1 ) try: self.nomFichier = os.path.join( self.outDir, "%s.flv" %( self.url.split( "/" )[ -1 ] ) ) except: self.nomFichier = os.path.join( self.outDir, "video.flv" ) self.generateNomFichier() if self.mode == "manifest": self.getVideoViaManifest() if self.mode == "playlist": self.getVideoViaPlaylist() def getVideoViaManifest( self ): # Verifie si le lien du manifest contient la chaine "media-secure" if( self.manifestURL.find( "media-secure" ) != -1 ): logger.critical( "pluzzdl ne sait pas encore gérer ce type de vidéo..." ) sys.exit( 0 ) # Lien du manifest (apres le token) self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" %( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) ) # Recupere le manifest self.manifest = self.navigateur.getFichier( self.manifestURLToken ) # Parse le manifest self.parseManifest() # Calcul les elements self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ] self.pv20, self.hdntl = self.pv2.split( ";" ) self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash self.pvtoken = "pvtoken=%s~hmac=%s" %( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() ) # # Creation de la video # self.premierFragment = 1 self.telechargementFini = False # S'il faut reprendre le telechargement if( self.resume ): video = self.historique.getVideo( self.urlFrag ) # Si la video est dans l'historique if( video is not None ): # Si la video existe sur le disque if( os.path.exists( self.nomFichier ) ): if( video.finie ): logger.info( "La vidéo a déjà été entièrement téléchargée" ) sys.exit( 0 ) else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info( "Reprise du téléchargement de la vidéo au fragment %d" %( video.fragments ) ) else: self.ouvrirNouvelleVideo() logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" %( self.nomFichier ) ) else: # Si la video n'est pas dans l'historique self.ouvrirNouvelleVideo() else: # S'il ne faut pas reprendre le telechargement self.ouvrirNouvelleVideo() # Calcul l'estimation du nombre de fragments self.nbFragMax = round( self.duree / 6 ) logger.debug( "Estimation du nombre de fragments : %d" %( self.nbFragMax ) ) # Ajout des fragments logger.info( "Début du téléchargement des fragments" ) try : i = self.premierFragment while( not self.stopDownloadEvent.isSet() ): frag = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) ) debut = self.debutVideo( i, frag ) self.fichierVideo.write( frag[ debut : ] ) # Affichage de la progression self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) ) i += 1 except urllib2.URLError, e : if( hasattr( e, 'code' ) ): if( e.code == 403 ): if( e.reason == "Forbidden" ): logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" ) newPlayerHash = self.getPlayerHash() if( newPlayerHash != self.playerHash ): self.configuration[ "player_hash" ] = newPlayerHash self.configuration.writeConfig() logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" ) else: logger.critical( "Pas de nouveau hash disponible..." ) else: logger.critical( "Impossible de charger la vidéo" ) elif( e.code == 404 ): self.progressFnct( 100 ) self.telechargementFini = True logger.info( "Fin du téléchargement" ) self.convertVideo() except KeyboardInterrupt: logger.info( "Interruption clavier" )
class PluzzDLM3U8(object): """ Telechargement des liens m3u8 """ def __init__(self, m3u8URL, nomFichier, navigateur, stopDownloadEvent, progressFnct): self.m3u8URL = m3u8URL self.nomFichier = nomFichier self.navigateur = navigateur self.stopDownloadEvent = stopDownloadEvent self.progressFnct = progressFnct self.historique = Historique() self.nomFichierFinal = "%s.mp4" % (self.nomFichier[:-3]) def ouvrirNouvelleVideo(self): """ Creer une nouvelle video """ try: # Ouverture du fichier print "Nom Fichier:", self.nomFichier # fullPathFile = os.path.join(os.getcwd(), self.nomFichier) # print "fullPathFile:", fullPathFile self.fichierVideo = open(self.nomFichier, "wb") # self.fichierVideo = open( fullPathFile, "wb" ) except: raise PluzzDLException("Impossible d'écrire dans le répertoire %s" % (os.getcwd())) # Ajout de l'en-tête # Fait dans creerMKV def ouvrirVideoExistante(self): """ Ouvre une video existante """ try: # Ouverture du fichier self.fichierVideo = open(self.nomFichier, "a+b") except: raise PluzzDLException("Impossible d'écrire dans le répertoire %s" % (os.getcwd())) def creerMKV(self): """ Creer un mkv a partir de la video existante (cree l'en-tete de la video) """ logger.info("Création du fichier MKV (vidéo finale); veuillez attendre quelques instants") logger.info("Convert: %s -> %s" % (self.nomFichier, self.nomFichierFinal)) commande = "ffmpeg -i %s -c:a aac -strict -2 -vcodec copy %s" % (self.nomFichier, self.nomFichierFinal) try: if (os.system(commande) == 0): os.remove(self.nomFichier) logger.info("Fin !") else: logger.warning( "Problème lors de la création du MKV avec FFmpeg ; le fichier %s est néanmoins disponible" % ( self.nomFichier)) except: raise PluzzDLException("Impossible de créer la vidéo finale") def telecharger(self): # Recupere le fichier master.m3u8 self.m3u8 = self.navigateur.getFichier(self.m3u8URL) # Extrait l'URL de tous les fragments self.listeFragments = re.findall(".+?\.ts", self.m3u8) if not self.listeFragments: self.listeFragments = [] self.listeM3U8 = re.findall(".+?index_2_av\.m3u8", self.m3u8) for m3u8 in self.listeM3U8: m3u8data = self.navigateur.getFichier(m3u8) self.listeFragments.extend(re.findall(".+?\.ts", m3u8data)) # # Creation de la video # self.premierFragment = 1 self.telechargementFini = False video = self.historique.getVideo(self.m3u8URL) # Si la video est dans l'historique if (video is not None): # Si la video existe sur le disque if (os.path.exists(self.nomFichier) or os.path.exists(self.nomFichierFinal)): if (video.finie): logger.info("La vidéo a déjà été entièrement téléchargée") if (not os.path.exists(self.nomFichierFinal)): self.creerMKV() return else: self.ouvrirVideoExistante() self.premierFragment = video.fragments logger.info("Reprise du téléchargement de la vidéo au fragment %d" % (video.fragments)) else: self.ouvrirNouvelleVideo() logger.info(u"Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" % ( self.nomFichier)) else: # Si la video n'est pas dans l'historique self.ouvrirNouvelleVideo() # Nombre de fragments self.nbFragMax = float(len(self.listeFragments)) logger.debug("Nombre de fragments : %d" % (self.nbFragMax)) # Ajout des fragments logger.info("Début du téléchargement des fragments") try: i = self.premierFragment while (i <= self.nbFragMax and not self.stopDownloadEvent.isSet()): frag = self.navigateur.getFichier("%s" % (self.listeFragments[i - 1])) self.fichierVideo.write(frag) # Affichage de la progression self.progressFnct(min(int((i / self.nbFragMax) * 100), 100)) i += 1 if (i == self.nbFragMax + 1): self.progressFnct(100) self.telechargementFini = True logger.info("Fin du téléchargement") self.creerMKV() except KeyboardInterrupt: logger.info("Interruption clavier") except Exception as inst: logger.critical("Erreur inconnue %s" % inst) finally: # Ajout dans l'historique self.historique.ajouter(Video(lien=self.m3u8URL, fragments=i, finie=self.telechargementFini)) # Fermeture du fichier self.fichierVideo.close()