#1751 Le 06/05/2012, à 15:42
- Babar21
Re : TVDownloader: télécharger les médias du net !
J'ai récupéré l'archive et je l'ai décompressée, ça roule mais c'est moins propre. L'heure de la mise à jour d'Ubuntu approche on dirait
Hors ligne
#1752 Le 06/05/2012, à 16:21
- chaoswizard
Re : TVDownloader: télécharger les médias du net !
Il fallait directement essayer d'installer le paquet deb et voir si ça fonctionnait !
Ubuntu ==> Debian ==> Archlinux
Hors ligne
#1753 Le 06/05/2012, à 23:40
- ubuntuzer
Re : TVDownloader: télécharger les médias du net !
@chaoswizard :
encore merci pour ton travail de maintien, cela profite à beaucoup d'internautes libres :-)
Concernant les liens RTMP et MMS, il m'est arriver de les utiliser lorsque le DL ne fonctionnait pas (ex : le dessin animé préféré de mon fils(RTMP) et "Un village Français" (MMS))
Suis-je le seul ?
Hors ligne
#1754 Le 07/05/2012, à 17:07
- chaoswizard
Re : TVDownloader: télécharger les médias du net !
Bon, ben tu fais bien de le dire, j'allais les virer !
Ubuntu ==> Debian ==> Archlinux
Hors ligne
#1755 Le 08/05/2012, à 12:59
- Babar21
Re : TVDownloader: télécharger les médias du net !
Bonjour.
J'ai des téléchargements incomplets sur les vidéos suivantes :
http://www.pluzz.fr/elysee-2012-la-vraie-campagne.html
Les 16 premières minutes dispos, puis le film se coupe. Fichier déclaré à 100% de 689 Mo.
http://www.pluzz.fr/francois-hollande-- … 22h30.html
Le début et la fin sont disponibles, mais grosse coupure au milieu (pas loin d'une heure). Déclaré à 100%, 468 Mo.
Hors ligne
#1756 Le 08/05/2012, à 23:10
- k3c
Re : TVDownloader: télécharger les médias du net !
Bonjour
Je confirme pour la première vidéo, un peu après 16 minutes, on passe à la fin. Fichier de 689 Mo moi aussi.
vlc annonce 1h48, comme mediainfo. Si des experts en vidéo voient un truc qui cloche dans ce qui suit, ils sont les bienvenus
mediainfo elysee-2012-la-vraie-campagne.flv
General
Complete name : elysee-2012-la-vraie-campagne.flv
Format : Flash Video
File size : 657 MiB
Duration : 1h 48mn
Overall bit rate : 849 Kbps
Video
Format : AVC
Format/Info : Advanced Video Codec
Format profile : Main@L3.1
Format settings, CABAC : Yes
Format settings, ReFrames : 4 frames
Codec ID : 7
Duration : 1h 48mn
Bit rate : 768 Kbps
Width : 704 pixels
Height : 400 pixels
Display aspect ratio : 16:9
Frame rate mode : Constant
Frame rate : 25.000 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.109
Stream size : 594 MiB (90%)
Writing library : x264 core 120 r2164 da19765
Encoding settings : cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x1:0 / me=dia / subme=2 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=0 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=0 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=75 / keyint_min=7 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=768 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00
Audio
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 10
Duration : 1h 48mn
Bit rate : 64.0 Kbps
Channel(s) : 2 channels
Channel positions : Front: L R
Sampling rate : 48.0 KHz
Compression mode : Lossy
Stream size : 49.5 MiB (8%)
gg@gg-SATELLITE-L755:~$
Pour la deuxième vidéo, on passe de 16 minutes 23 s à 1h 05 minutes directement.
J'ai mis dans un fichier le log du téléchargement, cela indique nombre approximatif de framents 610, cela en montre finalement 732, sans rupture (on ne passe pas de 223 à 280, par exemple), de 1 à 732.
mediainfo francois-hollande---comment-devenir-2012-05-07-22h30.flv
General
Complete name : francois-hollande---comment-devenir-2012-05-07-22h30.flv
Format : Flash Video
File size : 447 MiB
Duration : 1h 13mn
Overall bit rate : 855 Kbps
Video
Format : AVC
Format/Info : Advanced Video Codec
Format profile : Main@L3.1
Format settings, CABAC : Yes
Format settings, ReFrames : 4 frames
Codec ID : 7
Duration : 1h 13mn
Bit rate : 768 Kbps
Width : 704 pixels
Height : 400 pixels
Display aspect ratio : 16:9
Frame rate mode : Constant
Frame rate : 25.000 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.109
Stream size : 402 MiB (90%)
Writing library : x264 core 120 r2164 da19765
Encoding settings : cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x1:0 / me=dia / subme=2 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=0 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=0 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=75 / keyint_min=7 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=768 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00
Audio
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 10
Duration : 1h 13mn
Bit rate : 64.0 Kbps
Channel(s) : 2 channels
Channel positions : Front: L R
Sampling rate : 48.0 KHz
Compression mode : Lossy
Stream size : 33.5 MiB (7%)
Dernière modification par k3c (Le 08/05/2012, à 23:19)
Debian 12 sur Thinkpad reconditionné
Hors ligne
#1757 Le 08/05/2012, à 23:43
- bibichouchou
Re : TVDownloader: télécharger les médias du net !
salut à tous,
je viens d'essayer et je confirme le problème pour la deuxième vidéo, mêmes manifestations que celles décrites par k3c. je télécharge 731 fragments en tout.
je propose un nouveau motif pour le découpage-collage des fragments.
au lien de
frag.find("\x0f\x09")+1
j'utilise
frag.find("\x00\x0f\x09")+2
c'est du bricolage, mais bon...
cette fois, j'ai la vidéo complète sur notre nouveau président !!!
Edit : cela marche aussi pour le beau reportage de Moati.
A voir ce que cela donne pour d'autres vidéos...
Dernière modification par bibichouchou (Le 09/05/2012, à 00:29)
Hors ligne
#1758 Le 09/05/2012, à 00:38
- k3c
Re : TVDownloader: télécharger les médias du net !
Bravo bibichouchou, j'ai donc appliqué 2 fois ta modif dans /usr/share/pluzzdl/Pluzzdl.py
et le fichier francois-hollande-comment-devenir... est lisible de partout.
Edit : le fichier elysee-2012-la-vraie-campagne.flv est lisible de partout, lui aussi.
Dernière modification par k3c (Le 09/05/2012, à 00:56)
Debian 12 sur Thinkpad reconditionné
Hors ligne
#1759 Le 09/05/2012, à 01:22
- bibichouchou
Re : TVDownloader: télécharger les médias du net !
@k3c
est-ce que chez toi la vidéo de moati a quelques défauts à la toute fin (pdt le générique et un peu avant) ?
c'est juste pour comparer. je me suis aperçu de ça en naviguant dans la vidéo...
Hors ligne
#1760 Le 09/05/2012, à 01:56
- k3c
Re : TVDownloader: télécharger les médias du net !
@ bibichouchou
oui, dans le film elysee.., entre 1h47mn18s et 1h48mns13s, il y a plusieurs défauts.
Edit : si je regarde sur Pluzz, je vois les mêmes défauts. Donc pas de pb je pense.
Je n'ai rien vu à la fin de l'autre vidéo.
Dernière modification par k3c (Le 09/05/2012, à 02:07)
Debian 12 sur Thinkpad reconditionné
Hors ligne
#1761 Le 09/05/2012, à 08:48
- Babar21
Re : TVDownloader: télécharger les médias du net !
Merci à vous deux, j'ai pas bien tout compris à ce qu'il fallait modifier et où, mais je vais tenter le coup
Hors ligne
#1762 Le 09/05/2012, à 10:02
- bibichouchou
Re : TVDownloader: télécharger les médias du net !
@k3c
oui, j'ai aussi noté que les défauts sont présents dans la vidéo en ligne. donc il n'y a rien à faire.
@Babar21
il faut modifier le fichier Pluzzdl.py. il se trouve dans le dossier src/ de l'archive pluzzdl-0.8.1.tar.gz ou alors dans /usr/share/pluzzdl/. ça dépend de comment tu l'as installé.
et tu remplaces
frag.find("\x0f\x09")+1
par
frag.find("\x00\x0f\x09")+2
avec ton éditeur de texte préféré.
bonne journée !
ps : avant de propager la modif dans le paquet source, il faudrait tester avec d'autres vidéos pour voir si c'est ok...
Dernière modification par bibichouchou (Le 09/05/2012, à 10:05)
Hors ligne
#1763 Le 09/05/2012, à 10:18
- Babar21
Re : TVDownloader: télécharger les médias du net !
Bon, j'ai dû me tromper quelque part, ça bloque toujours à 16 minutes.
Je vais attendre une mise à jour ou un correctif "officiel".
Hors ligne
#1764 Le 09/05/2012, à 13:02
- k3c
Re : TVDownloader: télécharger les médias du net !
@ Babar21
Voici mon fichier /usr/share/pluzzdl/Pluzdl.py
#!/usr/bin/env python
# -*- coding:Utf-8 -*-
# Notes :
# -> Filtre Wireshark :
# http.host contains "ftvodhdsecz" or http.host contains "francetv" or http.host contains "pluzz"
# ->
#
# Modules
#
import base64
import binascii
import hashlib
import hmac
import os
import re
import sys
import urllib
import urllib2
import xml.etree.ElementTree
import xml.sax
from Historique import Historique, Video
from Navigateur import Navigateur
import logging
logger = logging.getLogger( "pluzzdl" )
#
# Classes
#
class PluzzDL( object ):
def __init__( self, url, useFragments = False, proxy = None, progressbar = False, resume = False ):
self.url = url
self.useFragments = useFragments
self.proxy = proxy
self.progressbar = progressbar
self.resume = resume
self.navigateur = Navigateur( self.proxy )
self.historique = Historique()
self.lienMMS = None
self.lienRTMP = None
self.manifestURL = None
self.drm = None
self.key = r"bd938d5ee6d9f42016f9c56577b6fdcf415fe4b184932b785ab32bcadc9bb592".decode( "hex" )
self.pvtokenKey = r"3fPHzcjMxiTmRj5AdV0bhzgjjSjk2PqUMBzFxgPEPF4="
# 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 )
# Lien du manifest non trouve
if( self.manifestURL is None ):
logger.critical( "Pas de lien vers le manifest" )
sys.exit( -1 )
# 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.pvtokenKey
self.pvtoken = "pvtoken=%s~hmac=%s" %( urllib.quote( self.pvtokenData ), hmac.new( self.key, self.pvtokenData, hashlib.sha256 ).hexdigest() )
#
# Creation de la video
#
self.nomFichier = "%s.flv" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ] )
self.premierFragment = 1
# 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 * self.bitrate ) / 6040.0, 0 )
logger.debug( "Estimation du nombre de fragments : %d" %( self.nbFragMax ) )
if( self.progressbar and self.nbFragMax != 0 ):
self.progression = Progression( self.nbFragMax, self.premierFragment )
else:
self.progression = ProgressionVide( self.nbFragMax, self.premierFragment )
# Ajout des fragments
logger.info( "Début du téléchargement des fragments" )
try :
i = self.premierFragment
frag = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
if( i == 1 ):
self.fichierVideo.write( frag[ frag.find( "mdat" ) + 4 : ] )
else:
self.fichierVideo.write( frag[ frag.find("\x00\x0f\x09") + 2 : ] )
# self.fichierVideo.write( frag[ frag.find( "\x0f\x09" ) + 1 : ] )
# Affichage de la progression
self.progression.afficher()
for i in xrange( self.premierFragment + 1, 99999 ):
frag = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
self.fichierVideo.write( frag[ frag.find( "\x00\x0f\x09") + 2 : ] )
# self.fichierVideo.write( frag[ frag.find( "mdat" ) + 79 : ] )
# Affichage de la progression
self.progression.afficher()
except urllib2.URLError, e :
if( hasattr( e, 'code' ) ):
if( e.code == 403 ):
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = False ) )
logger.critical( "Impossible de charger la vidéo" )
elif( e.code == 404 ):
self.progression.afficherFin()
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = True ) )
logger.info( "Fin du téléchargement" )
except :
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = False ) )
else :
# Fermeture du fichier
self.fichierVideo.close()
def getID( self ):
try :
page = self.navigateur.getFichier( self.url )
self.id = re.findall( r"http://info.francetelevisions.fr/\?id-video=([^\"]+)", page )[ 0 ]
logger.debug( "ID de l'émission : %s" %( self.id ) )
except :
logger.critical( "Impossible de récupérer l'ID de l'émission" )
sys.exit( -1 )
def parseInfos( self ):
try :
xml.sax.parseString( self.pageInfos, PluzzDLInfosHandler( self ) )
logger.debug( "Lien MMS : %s" %( self.lienMMS ) )
logger.debug( "Lien RTMP : %s" %( self.lienRTMP ) )
logger.debug( "URL manifest : %s" %( self.manifestURL ) )
logger.debug( "Utilisation de DRM : %s" %( self.drm ) )
except :
logger.critical( "Impossible de parser le fichier XML de l'émission" )
sys.exit( -1 )
def parseManifest( self ):
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 :
logger.critical( "Impossible de parser le manifest" )
sys.exit( -1 )
def ouvrirNouvelleVideo( self ):
try :
# Ouverture du fichier
self.fichierVideo = open( self.nomFichier, "wb" )
except :
logger.critical( "Impossible d'écrire dans le répertoire %s" %( os.getcwd() ) )
sys.exit( -1 )
# 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 ):
try :
# Ouverture du fichier
self.fichierVideo = open( self.nomFichier, "a+b" )
except :
logger.critical( "Impossible d'écrire dans le répertoire %s" %( os.getcwd() ) )
sys.exit( -1 )
class PluzzDLInfosHandler( xml.sax.handler.ContentHandler ):
def __init__( self, pluzzdl ):
self.pluzzdl = pluzzdl
self.isUrl = False
self.isDRM = False
def startElement( self, name, attrs ):
if( name == "url" ):
self.isUrl = True
elif( name == "drm" ):
self.isDRM = True
def characters( self, data ):
if( self.isUrl ):
if( data[ : 3 ] == "mms" ):
self.pluzzdl.lienMMS = data
elif( data[ : 4 ] == "rtmp" ):
self.pluzzdl.lienRTMP = data
elif( data[ -3 : ] == "f4m" ):
self.pluzzdl.manifestURL = data
elif( self.isDRM ):
self.pluzzdl.drm = data
def endElement( self, name ):
if( name == "url" ):
self.isUrl = False
elif( name == "drm" ):
self.isDRM = False
class ProgressionVide( object ):
def __init__( self, nbMax, indice = 1 ):
self.nbMax = nbMax
self.indice = indice
self.old = 0
self.new = 0
def afficher( self ):
pass
def afficherFin( self ):
pass
class Progression( ProgressionVide ):
def __init__( self, nbMax, indice ):
ProgressionVide.__init__( self, nbMax, indice )
def afficher( self ):
self.new = min( int( ( self.indice / self.nbMax ) * 100 ), 100 )
if( self.new != self.old ):
logger.info( "Avancement : %3d %%" %( self.new ) )
self.old = self.new
self.indice += 1
def afficherFin( self ):
if( self.old < 100 ):
logger.info( "Avancement : %3d %%" %( 100 ) )
Tu peux donc le copier.
Il y a 2 modifs à faire, j'ai laissé en commentaire l'ancienne ligne pour la première modif, la deuxième modif est 5 ou 6 lignes plus loin.
Debian 12 sur Thinkpad reconditionné
Hors ligne
#1765 Le 09/05/2012, à 14:24
- thom83
Re : TVDownloader: télécharger les médias du net !
Le fait de modifier le fichier Pluzdl.py ne change rien à son pendant Pluzdl.pyc. Cela n'a-t-il pas une incidence sur le résultat final quand on utilise pluzzdl ?
Hors ligne
#1766 Le 09/05/2012, à 14:45
- miztadux
Re : TVDownloader: télécharger les médias du net !
Salut,
Tout d'abord merci pour cet outil et le travail fourni par tous :)
Concernant le "collage des morceaux" j'ai un bout de code alternatif pour sauter le début des fragments.
Il devrait permettre d'eviter certains bugs rencontrés actuellement.
L'idée est, au lieu de se baser sur le "\x0f\x09", de prendre en compte un minimum du format flv pour être sûr de ce que l'on saute.
Ci-dessous le fichier PluzzDL.py v0.8.1 avec les modifs necessaires:
#!/usr/bin/env python
# -*- coding:Utf-8 -*-
# Notes :
# -> Filtre Wireshark :
# http.host contains "ftvodhdsecz" or http.host contains "francetv" or http.host contains "pluzz"
# ->
#
# Modules
#
import struct
import base64
import binascii
import hashlib
import hmac
import os
import re
import sys
import urllib
import urllib2
import xml.etree.ElementTree
import xml.sax
from Historique import Historique, Video
from Navigateur import Navigateur
import logging
logger = logging.getLogger( "pluzzdl" )
#
# Classes
#
class PluzzDL( object ):
def __init__( self, url, useFragments = False, proxy = None, progressbar = False, resume = False ):
self.url = url
self.useFragments = useFragments
self.proxy = proxy
self.progressbar = progressbar
self.resume = resume
self.navigateur = Navigateur( self.proxy )
self.historique = Historique()
self.lienMMS = None
self.lienRTMP = None
self.manifestURL = None
self.drm = None
self.key = r"bd938d5ee6d9f42016f9c56577b6fdcf415fe4b184932b785ab32bcadc9bb592".decode( "hex" )
self.pvtokenKey = r"3fPHzcjMxiTmRj5AdV0bhzgjjSjk2PqUMBzFxgPEPF4="
# 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 )
# Lien du manifest non trouve
if( self.manifestURL is None ):
logger.critical( "Pas de lien vers le manifest" )
sys.exit( -1 )
# 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.pvtokenKey
self.pvtoken = "pvtoken=%s~hmac=%s" %( urllib.quote( self.pvtokenData ), hmac.new( self.key, self.pvtokenData, hashlib.sha256 ).hexdigest() )
#
# Creation de la video
#
self.nomFichier = "%s.flv" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ] )
self.premierFragment = 1
# 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 * self.bitrate ) / 6040.0, 0 )
logger.debug( "Estimation du nombre de fragments : %d" %( self.nbFragMax ) )
if( self.progressbar and self.nbFragMax != 0 ):
self.progression = Progression( self.nbFragMax, self.premierFragment )
else:
self.progression = ProgressionVide( self.nbFragMax, self.premierFragment )
# Ajout des fragments
logger.info( "Début du téléchargement des fragments" )
try :
i = self.premierFragment
for i in xrange( self.premierFragment, 99999 ):
frag = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
# Saute le header "fragment"
start = frag.find( "mdat" ) + 4
if i > 1:
# A part pour le premier fragment, saute les deux premiers tags
for tmp in range(2):
bodylen, = struct.unpack_from( '>L', frag, start )
bodylen &= 0x00ffffff
start += bodylen + 11 + 4
# Ajoute le reste
self.fichierVideo.write( frag[ start : ] )
# Affichage de la progression
self.progression.afficher()
except urllib2.URLError, e :
if( hasattr( e, 'code' ) ):
if( e.code == 403 ):
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = False ) )
logger.critical( "Impossible de charger la vidéo" )
elif( e.code == 404 ):
self.progression.afficherFin()
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = True ) )
logger.info( "Fin du téléchargement" )
except :
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = False ) )
else :
# Fermeture du fichier
self.fichierVideo.close()
def getID( self ):
try :
page = self.navigateur.getFichier( self.url )
self.id = re.findall( r"http://info.francetelevisions.fr/\?id-video=([^\"]+)", page )[ 0 ]
logger.debug( "ID de l'émission : %s" %( self.id ) )
except :
logger.critical( "Impossible de récupérer l'ID de l'émission" )
sys.exit( -1 )
def parseInfos( self ):
try :
xml.sax.parseString( self.pageInfos, PluzzDLInfosHandler( self ) )
logger.debug( "Lien MMS : %s" %( self.lienMMS ) )
logger.debug( "Lien RTMP : %s" %( self.lienRTMP ) )
logger.debug( "URL manifest : %s" %( self.manifestURL ) )
logger.debug( "Utilisation de DRM : %s" %( self.drm ) )
except :
logger.critical( "Impossible de parser le fichier XML de l'émission" )
sys.exit( -1 )
def parseManifest( self ):
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 :
logger.critical( "Impossible de parser le manifest" )
sys.exit( -1 )
def ouvrirNouvelleVideo( self ):
try :
# Ouverture du fichier
self.fichierVideo = open( self.nomFichier, "wb" )
except :
logger.critical( "Impossible d'écrire dans le répertoire %s" %( os.getcwd() ) )
sys.exit( -1 )
# 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 ):
try :
# Ouverture du fichier
self.fichierVideo = open( self.nomFichier, "a+b" )
except :
logger.critical( "Impossible d'écrire dans le répertoire %s" %( os.getcwd() ) )
sys.exit( -1 )
class PluzzDLInfosHandler( xml.sax.handler.ContentHandler ):
def __init__( self, pluzzdl ):
self.pluzzdl = pluzzdl
self.isUrl = False
self.isDRM = False
def startElement( self, name, attrs ):
if( name == "url" ):
self.isUrl = True
elif( name == "drm" ):
self.isDRM = True
def characters( self, data ):
if( self.isUrl ):
if( data[ : 3 ] == "mms" ):
self.pluzzdl.lienMMS = data
elif( data[ : 4 ] == "rtmp" ):
self.pluzzdl.lienRTMP = data
elif( data[ -3 : ] == "f4m" ):
self.pluzzdl.manifestURL = data
elif( self.isDRM ):
self.pluzzdl.drm = data
def endElement( self, name ):
if( name == "url" ):
self.isUrl = False
elif( name == "drm" ):
self.isDRM = False
class ProgressionVide( object ):
def __init__( self, nbMax, indice = 1 ):
self.nbMax = nbMax
self.indice = indice
self.old = 0
self.new = 0
def afficher( self ):
pass
def afficherFin( self ):
pass
class Progression( ProgressionVide ):
def __init__( self, nbMax, indice ):
ProgressionVide.__init__( self, nbMax, indice )
def afficher( self ):
self.new = min( int( ( self.indice / self.nbMax ) * 100 ), 100 )
if( self.new != self.old ):
logger.info( "Avancement : %3d %%" %( self.new ) )
self.old = self.new
self.indice += 1
def afficherFin( self ):
if( self.old < 100 ):
logger.info( "Avancement : %3d %%" %( 100 ) )
En détail pour ceux que ca interesse:
Pour les fragments > 1 on doit sauter les deux premiers blocs de données (=tags).
Avec cette version on lit le minimum pour se déplacer de tag en tag (=la longueur de son contenu) et on avance jusqu'au 3°.
A comparer la version avec "\x0f\x09" assume plusieurs choses:
- le deuxième tag fait 15 octets de long (cad fini par \x0f)
- le troisième tag est de type video (cad commence par \x09)
- "\x0f\x09" n'est pas présent dans le fichier avant ce point
Le code:
bodylen, = struct.unpack_from( '>L', frag, start )
=> extrait les 4 premiers octets sous forme de "long"
bodylen &= 0x00ffffff
=> met à zero le premier octet (qui correspond au type du tag) pour ne garder que les octets 2, 3 et 4 = la longueur du contenu
start += bodylen + 11 + 4
=> avance de bodylen + 11 = la taille du header du tag + 4 = la taille du footer du tag (= la longueur totale d'ailleurs...)
Hors ligne
#1767 Le 09/05/2012, à 15:36
- k3c
Re : TVDownloader: télécharger les médias du net !
@ miztadux
J'ai fait ta modif, j'ai un fichier elysee-2012-la-vraie-campagne.flv bien lisible.
Ton idée de coller au format flv me semble très saine :-)
Je vais faire d'autres tests.
Debian 12 sur Thinkpad reconditionné
Hors ligne
#1768 Le 09/05/2012, à 15:47
- Babar21
Re : TVDownloader: télécharger les médias du net !
Comme K3c, ça a l'air de fonctionner maintenant, merci encore, vous êtes des génies !
Hors ligne
#1769 Le 09/05/2012, à 19:33
- chaoswizard
Re : TVDownloader: télécharger les médias du net !
Effectivement, ça semble pas mal (j'obtiens les mêmes début de fichiers pour les premiers fragments d'une vidéo donnée).
Je ne sais pas pourquoi cela varie après mais si ça marche avec la nouvelle méthode de calcul, tant mieux ! (avec la connexion que j'ai, je ne peux pas tenter de prendre vos vidéos de 2h ).
Je vais mettre à jour ça !
Merci miztadux !
(c'est souvent que les gens qui participent viennent juste de créer un pseudo, je ne comprends pas trop pourquoi...)
Dernière modification par chaoswizard (Le 09/05/2012, à 19:33)
Ubuntu ==> Debian ==> Archlinux
Hors ligne
#1770 Le 09/05/2012, à 22:12
- ubuntuzer
Re : TVDownloader: télécharger les médias du net !
Merci miztadux pour tes modifs sur la v0.8.1
cela m'a permis de récupérer http://www.pluzz.fr/cash-investigation- … 22h25.html
avec la version 0.8, j'obtenais une erreur 403 au bout de quelques Mo.
Hors ligne
#1771 Le 10/05/2012, à 19:49
- thom83
Re : TVDownloader: télécharger les médias du net !
Pour moi, avec Lucid i386, le nouveau PluzzDL.py ne fonctionne pas. En effet, python se plaint dés le début :
thom@provence:~$ pluzzdl -vf http://www.pluzz.fr/cash-investigation-2012-05-04-22h25.html
Traceback (most recent call last):
File "/usr/share/pluzzdl/main.py", line 24, in <module>
from PluzzDL import PluzzDL
File "/usr/share/pluzzdl/PluzzDL.py", line 26, in <module>
from Historique import Historique, Video
ImportError: No module named Historique
Je neutralise donc les deux premières lignes où apparaît le mot «Historique» en les commentant (lignes 26 et 45) et je relance la commande.
Comme je n'ai rien touché aux différents «self.historique.» présents plus bas, j'ai une nouvelle plainte au bout de 45 Mio de parcours :
Traceback (most recent call last):
File "/usr/share/pluzzdl/main.py", line 74, in <module>
PluzzDL( args[ 0 ], options.fragments, options.proxy, options.progressbar )
File "/usr/share/pluzzdl/PluzzDL.py", line 144, in __init__
self.historique.ajouter( Video( lien = self.urlFrag, fragments = i, finie = False ) )
AttributeError: 'PluzzDL' object has no attribute 'historique'
Je vais donc essayer de n'aporter que le minimum de changement au fichier d'origine.
Hors ligne
#1772 Le 10/05/2012, à 20:42
- chaoswizard
Re : TVDownloader: télécharger les médias du net !
Normal, il manque le fichier Historique.py ...
Il ne faut pas mettre à jour que le fichier Pluzzdl.py, il faut bien prendre tous les fichiers... (en utilisant par exemple un deb ou le tar.gz)
Dernière modification par chaoswizard (Le 10/05/2012, à 20:42)
Ubuntu ==> Debian ==> Archlinux
Hors ligne
#1773 Le 11/05/2012, à 14:58
- thom83
Re : TVDownloader: télécharger les médias du net !
Effectivement, la version 0.8.2 fonctionne bien (essayé avec cash-investigation). Avec ubuntu 10.04, il faut ajouter le paquet python-argparse suite à l'abandon du module optparse dans main.py.
Encore merci aux développeurs.
Hors ligne
#1774 Le 11/05/2012, à 15:01
- thom83
Re : TVDownloader: télécharger les médias du net !
Effectivement, la version 0.8.2 fonctionne bien (essayé avec cash-investigation). Avec ubuntu 10.04, il faut ajouter le paquet python-argparse suite à l'abandon du module optparse dans main.py.
Encore merci aux développeurs.
Hors ligne
#1775 Le 11/05/2012, à 16:14
- k3c
Re : TVDownloader: télécharger les médias du net !
J'ai mis dans le forum Trucs astuces et scripts utiles
un script Python qui surveille le répertoire ~/TVDownloader
http://forum.ubuntu-fr.org/viewtopic.ph … 1#p9218931
et quand un fichier .mp4 y arrive, je le convertis en .mkv, vu que ma platine de salon Dune lit tous les formats sauf le .mp4
Ca pourra peut-être intéresser certains.
Debian 12 sur Thinkpad reconditionné
Hors ligne