Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#251 Le 01/06/2013, à 13:54

11gjm

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,

Je ne sais pas , si le process suivant peut vous aider .
Il est valable pour Windows et permet de trouver certains T O K E N .

====
[Tutorial] - Finding a SWF Secure Token
http://forum.wiziwig.eu/threads/83849-Tutorial-Finding-a-SWF-Secure-Token

Le 1er post , permet de comprendre le processus de capture du token .
(http://forum.wiziwig.eu/threads/83849-Tutorial-Finding-a-SWF-Secure-Token?p=1604175#post1604175)
====
====
Télécharger "SWF Decompiler.rar" à : http://www.mediafire.com/?lm8qilr6451bygi
_ le décompacter => création d'un répertoire "SWF Decompiler"
_ dans ce dernier :
__ ouvrir le fichier "examples.txt" , le garder ouvert !!!
__ lancer le fichier "SWF Decompiler.bat" ; ouverture d'une fenêtre en mode console

==> demandé pageUrl=...copier dans le txt "http://stream.tv-kino.net" , coller et <entrée>
==> demandé swfUrl=...copier dans le txt "http://stream.tv-kino.net/player.swf" , coller et <entrée>

Il n'y a plus qu'à attendre => "Token.txt"
L'ouvrir , il y a l'info recherchée -T xxxxxx

=== Édité à 23H30
ou + performant ( si besoin du proxy )
http://www.mediafire.com/download/5jcub3us80b9gir/SWF_Token_Grabber.rar

NOTA : le collage des données dans la console est un peu particulier .
Au niveau du "prompt clignotant" ; avec la souris :
_ clic droit
_ choisir "Coller" , puis , Clic de dessus

=======
Certains fichiers peuvent être renommés avec des caractères UNICODES ,
et rendre impossible le processus de récupération du code souhaité .
=======

Cordialement .

Dernière modification par 11gjm (Le 01/06/2013, à 23:29)

Hors ligne

#252 Le 01/06/2013, à 18:10

laslack

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,
Je suis votre discussion avec grand intérêt
Avec 12.04 j'ai chargé pluzzdl  0.9.3 et j'ai lancé des chargements selon 2 méthodes , l'une avec comme commande " pluzzdl http//.........." du tuto de "tvdownloader "  qui n'ouvre rien  et qui a donné ceci :

jeanpaul@jeanpaul-G41M-ES2H:~$ pluzzdl http://pluzz.francetv.fr/videos/infrarouge_,82766049.html
Traceback (most recent call last):
  File "/usr/share/pluzzdl/main.py", line 91, in <module>
    progressFnct = progressFnct )
  File "/usr/share/pluzzdl/PluzzDL.py", line 119, in __init__
    downloader.telecharger()
  File "/usr/share/pluzzdl/PluzzDL.py", line 259, in telecharger
    self.m3u8 = self.navigateur.getFichier( self.m3u8URL )
  File "/usr/share/pluzzdl/Navigateur.py", line 58, in getFichier
    page = self.urlOpener.open( requete, timeout = self.timeOut )
  File "/usr/lib/python2.7/urllib2.py", line 406, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 519, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 444, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 527, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found 

et une autre avec la commande préconisée plus haut : commençant par "cd /" qui n'ouvre  rien non plus mais qui donne ceci:

jeanpaul@jeanpaul-G41M-ES2H:~/Téléchargements/pluzzdl-0.9.3$ http://pluzz.francetv.fr/videos/infrarouge_,82766049.html
bash: http://pluzz.francetv.fr/videos/infrarouge_,82766049.html: Aucun fichier ou dossier de ce type
jeanpaul@jeanpaul-G41M-ES2H:~/Téléchargements/pluzzdl-0.9.3$ 
jeanpaul@jeanpaul-G41M-ES2H:~/Téléchargements/pluzzdl-0.9.3$ http://ftvodhdsecz-f.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2013/S22/J2/82766047-20130528-,398,632,934,k.mp4.csmil/index_2_av.m3u8
bash: http://ftvodhdsecz-f.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2013/S22/J2/82766047-20130528-,398,632,934,k.mp4.csmil/index_2_av.m3u8: Aucun fichier ou dossier de ce type
jeanpaul@jeanpaul-G41M-ES2H:~/Téléchargements/pluzzdl-0.9.3$ http://pluzz.francetv.fr/videos/un_jour_un_destin_,82766047.html
bash: http://pluzz.francetv.fr/videos/un_jour_un_destin_,82766047.html: Aucun fichier ou dossier de ce type

. "
Les  messages obtenus sont différents.pourquoi?
j'ai réessayé avec les adresse données dans le post" 248" et j'obtiens les mêmes résultats . D'où peut devenir l'erreur ?
j'ai aussi essayé avec "tvdownloader" ,  mais impossible de le faire fonctionner.J'aimerai pourtant télécharger depuis Pluzz aussi facilement que sur ARTE
Je ne suis pas très calé dans le fonctionnement en ligne de commande , Merci de votre aide

Hors ligne

#253 Le 01/06/2013, à 18:48

bibichouchou

Re : TVDownloader: télécharger les médias du net ! [2]

Salut,

@ pacome
c'est un coup de bol. je me suis trompé de dossier au lancement de la commande... quand j'ai voulu récupérer une vidéo, je me suis mis dans le dossier de la version 0.9.3 au lieu de 0.9.4.

Hors ligne

#254 Le 01/06/2013, à 18:52

bibichouchou

Re : TVDownloader: télécharger les médias du net ! [2]

à laslack
pourrais-tu essayer cette commande et copier/coller la sortie ?

pluzzdl -v http://pluzz.francetv.fr/videos/infrarouge_,82766049.html

le -v après pluzzdl rend la commande bavarde et affichera un peu plus de texte.

Sinon, dans ton deuxième essai, tu n'as pas tapé de commande. tu as seulement collé une adresse http et a tenté de l'exécuter. D'où l'erreur te disant "aucun fichier ou dossier de ce type".
Il aurait fallu que tu fasses quand tu es dans ~/Téléchargements/pluzzdl-0.9.3

cd src/

puis

python main.py -v http://pluzz.francetv.fr/videos/infrarouge_,82766049.html

concernant l'adresse gentiment donnée par 11gjm un peu plus haut, elle n'est pas utile. elle permettrait par contre de réparer la version 0.9.4 de pluzzdl (qui ne marche plus depuis environ 1 semaine, d'où l'utilisation d'une version "inférieure").

concernant tvdownloader, il ne sert à rien pour la plateforme pluzz de france télé. Pour Linux, il n'y a que pluzzdl via la ligne de commande. Ou alors le script AdobeHDS (écrit en php) par KSV. Mais il est générique et ne permet pas à ma connaissance l'obtention des sous-titres (s'ils sont dispo) comme le fait pluzzdl.

Dernière modification par bibichouchou (Le 01/06/2013, à 19:14)

Hors ligne

#255 Le 01/06/2013, à 19:17

laslack

Re : TVDownloader: télécharger les médias du net ! [2]

Voila le résultat de la commande :

jeanpaul@jeanpaul-G41M-ES2H:~$ pluzzdl -v http://pluzz.francetv.fr/videos/infrarouge_,82766049.html
[DEBUG   ]  main.py             pluzzdl 0.9.4 avec Python 2.7.3 (i686)
[DEBUG   ]  main.py             OS : Linux #70-Ubuntu SMP Wed May 29 20:31:05 UTC 2013
[DEBUG   ]  Navigateur.py       GET http://pluzz.francetv.fr/videos/infrarouge_,82766049.html
[DEBUG   ]  PluzzDL.py          ID de l'émission : 82766049
[DEBUG   ]  Navigateur.py       GET http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=82766049
[DEBUG   ]  PluzzDL.py          Lien MMS : None
[DEBUG   ]  PluzzDL.py          Lien RTMP : None
[DEBUG   ]  PluzzDL.py          URL manifest : http://ftvodhdsecz-f.akamaihd.net/z/streaming-adaptatif_france-dom-tom/2013/S22/J2/82766049-20130528-,398,632,934,k.mp4.csmil/manifest.f4m
[DEBUG   ]  PluzzDL.py          URL m3u8 : http://medias2.francetv.fr/catchup-mobile/france-dom-tom/non-token/non-drm/m3u8/2013/S22/J2/82766049-20130528.m3u8
[DEBUG   ]  PluzzDL.py          Utilisation de DRM : non
[DEBUG   ]  PluzzDL.py          Chaine : France 2
[DEBUG   ]  Historique.py       Historique chargé
[DEBUG   ]  Navigateur.py       GET http://medias2.francetv.fr/catchup-mobile/france-dom-tom/non-token/non-drm/m3u8/2013/S22/J2/82766049-20130528.m3u8
[DEBUG   ]  Navigateur.py       Not Found
Traceback (most recent call last):
  File "/usr/share/pluzzdl/main.py", line 91, in <module>
    progressFnct = progressFnct )
  File "/usr/share/pluzzdl/PluzzDL.py", line 119, in __init__
    downloader.telecharger()
  File "/usr/share/pluzzdl/PluzzDL.py", line 259, in telecharger
    self.m3u8 = self.navigateur.getFichier( self.m3u8URL )
  File "/usr/share/pluzzdl/Navigateur.py", line 58, in getFichier
    page = self.urlOpener.open( requete, timeout = self.timeOut )
  File "/usr/lib/python2.7/urllib2.py", line 406, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 519, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 444, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 527, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found
[DEBUG   ]  Historique.py       Historique sauvé

Pour le deuxième essai , je vais rectifier et  je te dis quoi
Merci

Hors ligne

#256 Le 01/06/2013, à 19:24

bibichouchou

Re : TVDownloader: télécharger les médias du net ! [2]

à laslack
tu vois, avec la commande pluzzdl, tu fais appel à la version 0.9.4 de pluzzdl, qui est installée sur ton système. c'est inscrit sur la première ligne de la sortie. malheureusement, cette version est cassée depuis qques jours.
il est possible de la réparer mais c'est plus simple d'utiliser la version 0.9.3.

Dernière modification par bibichouchou (Le 01/06/2013, à 19:25)

Hors ligne

#257 Le 01/06/2013, à 21:54

11gjm

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,

@bibichouchou : Pluzzdl 0.9.3

Ce que tu indiques au #254 , python...html , fonctionne ( 719 frags ) .
C'est en cours de téléchargement .

Cordialement .

Hors ligne

#258 Le 01/06/2013, à 22:34

mattetti

Re : TVDownloader: télécharger les médias du net ! [2]

J'ai rajouté un fix pour le changement recent du format m3u8, vous le trouverez dans ma fork sur GitHub:
https://github.com/mattetti/pluzzdl
(marche aussi sous OS X)

Si j'avais plus de temps j'aurais aussi changé le téléchargement pour qu'il tourne en parallele et assemble les fragments a la fin a la place d'etre séquentiel.. ou alors peut etre que quelqu'un d'autre aura plus de temps libre.

Hors ligne

#259 Le 01/06/2013, à 23:28

laslack

Re : TVDownloader: télécharger les médias du net ! [2]

Ok Merci 11gjm et bibichouchou Ca marche !

Hors ligne

#260 Le 02/06/2013, à 00:07

coxon

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour, Tvdownloader marche très lentement  chez moi,
il faut attendre plusieurs minutes quand on choisit une émission pour que l'application l'actualise et le télécharge.
De plus, existe-t-il une autre solution pour télécharger les émissions de francetv sous Xubuntu 12.04?

Hors ligne

#261 Le 02/06/2013, à 00:25

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

@ coxon

Il y a aussi AdobeHDS de KSV, regarde le post explicatif de pacome un peu avant.


Archlinux sur Xiaomi Air 13

Hors ligne

#262 Le 02/06/2013, à 00:42

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

@ matteti

Merci pour le fix.
>>>Si j'avais plus de temps j'aurais aussi changé le téléchargement pour qu'il tourne en parallele et assemble les fragments a la fin a la place d'etre séquentiel.. ou alors peut etre que quelqu'un d'autre aura plus de temps libre.

tu peux t'inspirer de mon script pour M6, qui est comme pluzz du Http Dynamic streaming, il va aussi vite que le script de KSV.
Il y a 2 queues
http://forum.ubuntu-fr.org/viewtopic.php?id=1268721


Archlinux sur Xiaomi Air 13

Hors ligne

#263 Le 02/06/2013, à 09:48

grandtoubab

Re : TVDownloader: télécharger les médias du net ! [2]

Salut
Ne surtout pas retirer le paquet python-socksipy (1.0-1ubuntu2) même s'il est détecté comme orphelin, sinon sad

@ubuntu-desktop:~/Videos$ pluzzdl http://pluzz.francetv.fr/videos/la_grande_librairie.html
Traceback (most recent call last):
  File "/usr/share/pluzzdl/main.py", line 25, in <module>
    from PluzzDL        import PluzzDL
  File "/usr/share/pluzzdl/PluzzDL.py", line 33, in <module>
    from Navigateur    import Navigateur
  File "/usr/share/pluzzdl/Navigateur.py", line 12, in <module>
    import socks
ImportError: No module named socks

ça marche mieux avec big_smile

@ubuntu-desktop:~/Videos$ pluzzdl http://pluzz.francetv.fr/videos/la_grande_librairie.html
[INFO    ]  Configuration.py    Copie du fichier de configuration par défaut
[INFO    ]  PluzzDL.py          Début du téléchargement des fragments
[INFO    ]  PluzzDL.py          Fin du téléchargement

Dernière modification par grandtoubab (Le 02/06/2013, à 09:59)


Linux tout seul sur HP Pavilion DV7 et Acer aspire T650
Debian 10 Buster XFCE/Gnome3 sur sda1
Canon MG3650 en wifi

Hors ligne

#264 Le 04/06/2013, à 00:28

pacome

Re : TVDownloader: télécharger les médias du net ! [2]

Bonsoir à tous,

@bibichouchou:
Coup de bol ou pas: trop fort quand même! lol

@mattetti:
Merci pour la correction: je l'utiliserai à la prochaine émission à télécharger et je regarderai ton code avec intérêt wink.

@k3c:
Merci pour ta transposition en python du script PHP de KSV; il faudra que je regarde ça de plus près aussi; de mon coté j'ai jeté un œil sur le code du plugin qui extrait le manifeste, mais je ne suis pas sur que ce soit une bonne piste, d'autant que c'est fait dans le code de pluzzdl (une mine, ce code! une mine! smile)

Voici une version 0.9.4.4 (version 0.9.4.3 3 pages plus haut) de tmc_tf1.py dans laquelle j'ai:

  • ajouté la possibilité de passer l'url d'un player swf

  • rétabli le calcul du hash/size par rtmpdump

  • rajouté la possibilité de forcer ce calcul

  • maintenu la possibilité de le calculer dans le script (pas très utile mais intéressant, non?)

  • rajouté les options de lancement pour piloter tout ça (liste complète avec -h ou --help)

  • codé une fonction pour gérer la reprise sur erreur du téléchargement par rtmpdump qui jongle avec les différentes possibilités

  • encore une fois zappé de faire quelque chose de similaire pour le téléchargement par curl hmm

  • modifié la cardinalité du paramètre positionnel (i.e. l'url à télécharger), comme ça on peut en mettre plusieurs à la file

  • commenté quelques log.debug et renommé quelques variables

  • renommé ce script en watdl.py (marre de tmc_tf1... tongue)

#!/usr/bin/python
#-*- coding:utf-8 -*-
# TF1 TMC NT1 HD1 V0.9.4.4 par k3c, bibichouchou et pacome

# args & log
import argparse
from time import localtime, strftime
import logging

import subprocess, re, sys, shlex
import socket
import urllib2                  # → urlopen & exceptions
import hashlib                  # → sha256sum
import hmac
import zlib
import StringIO
import time, md5, random, urllib2, json
import bs4 as BeautifulSoup
import os                       # → os.rename
from urlparse import urlparse

# global var
scriptName='watdl.py'
scriptVersion='0.9.4.4'

# programmes externes utilisés
ffmpegEx='ffmpeg'               # ou avconv
rtmpdumpEx='rtmpdump'
curlEx='curl'

# Player swf
defaultSwfPlayerUrl='http://www.wat.tv/images/v40/PlayerWat.swf'
KEY = "Genuine Adobe Flash Player 001"

listeUserAgents = [ 
    'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; fr-fr) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
    'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1',
    'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.',
    'Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) midori',
    'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
    'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.940.0 Safari/535.8' ]

WEBROOTWAT="http://www.wat.tv"
wat_url="/web/"
jsonVideosInfos=""

# random user agent
ua=random.choice(listeUserAgents)

# global logger
log=logging.getLogger(__name__)

def checkExternalProgram(prog, optArg='', expectedValue=''):
    """ Permet de vérifier la présence des programmes externes requis """
    log.debug('→checkExternalProgram(%s, %s, %s)'%(prog, optArg, expectedValue))
    args=shlex.split('%s %s' % (prog, optArg))
    try:
        process=subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
        stdout, stderr = process.communicate()
        if expectedValue == '':
            return True
        else:
            if expectedValue in stdout: # à améliorer pour versions > ...
                return True
            else:
                return False
    except OSError:
        log.error('Le programme %s n\'est pas présent sur votre système' % (prog))
        return False

def get_soup(url, referer, ua):
    """ on récupère la soupe """
    req  = urllib2.Request(url)
    req.add_header('User-Agent', ua)
    req.add_header('Referer', referer)
    soup = urllib2.urlopen(req).read()
    # log.debug('←get_soup(%s, %s, %s): %s' % (url, referer, ua, soup))
    return soup

def get_wat(id, HDFlag):
    """la fonction qui permet de retrouver une video sur wat"""
    def base36encode(number):
        if not isinstance(number, (int, long)):
            raise TypeError('number must be an integer')
        if number < 0:
            raise ValueError('number must be positive')
        alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        base36 = ''
        while number:
            number, i = divmod(number, 36)
            base36 = alphabet[i] + base36
        return base36 or alphabet[0]
    if HDFlag:
        wat_url = "/webhd/"
    else:
        wat_url = "/web/"
    ts = base36encode(int(time.time())-60)
    timesec = hex(int(ts, 36))[2:]
    while(len(timesec)<8):
        timesec = "0"+timesec
    token = md5.new(
        "9b673b13fa4682ed14c3cfa5af5310274b514c4133e9b3a81e6e3aba00912564" +
        wat_url + str(id) + "" + timesec).hexdigest()
    id_url1 = (WEBROOTWAT + "/get" + wat_url + str(id) + "?token=" + token +
    "/" + str(timesec) + "&country=FR&getURL=1")
    # log.debug('←get_wat(%s, %s):%s' %(id, HDFlag, id_url1))
    return id_url1

def swfPlayerHashAndSize(swfPlayerUrl):
    """
    Calcule et renvoie le tuple (hash, taille) du player swf
    ← (swfHash, swfSize)
    """
    global KEY
    try:
        swfPlayer= urllib2.urlopen(swfPlayerUrl).read()
    except (ValueError, urllib2.URLError):
        log.error('→swfPlayerHashAndSize(%s): Url invalide!' % (swfPlayerUrl))
        raise
    except urllib2.HTTPError:
        log.error('→swfPlayerHashAndSize(%s): Pb http!' % (swfPlayerUrl))
        raise

    swfPlayerHash=hashlib.sha256(swfPlayer).hexdigest()
    if type(swfPlayer) is str:
        swfData=StringIO.StringIO(swfPlayer)
    swfData.seek(0, 0)
    magic=swfData.read(3)
    if magic != "CWS":
        log.error("Pas de CWS...")
        raise ValueError('NoCWS')
    else:
        unzPlayer="FWS" + swfData.read(5) + zlib.decompress(swfData.read())
        unzPlayerSize=len(unzPlayer)
        unzPlayerHash = hmac.new(KEY, unzPlayer, hashlib.sha256).hexdigest()
    log.debug('←computeSwfPlayerHash(%s):(%s, %s)' %(
            swfPlayerUrl, unzPlayerHash, unzPlayerSize))
    return (unzPlayerHash, unzPlayerSize)

def rtmpDownload(rtmpUrl,
                 swfPlayerUrl,
                 swfForceRefresh,
                 swfComputeHashSize,
                 fileName,
                 swfHash=None,
                 swfSize=None):
    """ Appel de rtmpdump avec traitement des options et reprise (récursif)
    """
    log.debug('→rtmpDownload(%s, %s, %s, %s, %s, %s, %s)' % (
            rtmpUrl, swfPlayerUrl, swfForceRefresh, swfComputeHashSize,
            fileName, swfHash, swfSize))
    rtmpCmd = '%s --resume --rtmp "%s" --port 443 --timeout 10' % (
        rtmpdumpEx, rtmpUrl)    # initialisation de la commande

    if swfComputeHashSize:
        if not swfHash and not swfSize: # pour ne pas recalculer en récursion
            try:
                (swfHash, swfSize)=swfPlayerHashAndSize(swfPlayerUrl)
            except:
                log.warning('Impossible de calculer le hash/size du player swf!')
                log.info('calcul du hash/size par %s' % (rtmpdumpEx))
                return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                    False, fileName)
            if swfForceRefresh:
                log.warning('pas encore codé!')
                # et je ne sais pas si ça le sera... ;)
            rtmpCmd += ' --swfhash %s --swfsize %i' % (swfHash, swfSize)
    else:
        if swfForceRefresh:
            rtmpCmd += ' --swfVfy %s --swfAge 0' % (swfPlayerUrl)
        else:
            rtmpCmd += ' --swfVfy %s' % (swfPlayerUrl)
    rtmpCmd += ' -o "%s"' % (fileName)
    log.info(rtmpCmd)
    rtmpCall = shlex.split(rtmpCmd)
    rtmpProc = subprocess.Popen(rtmpCall,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
    (stdout, stderr) = rtmpProc.communicate()
    if rtmpProc.returncode == 1:   # sortie en erreur →
        if swfComputeHashSize:     # on ré-essaye avec le calcul par rtmpdump
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                 False, fileName)
        elif not swfForceRefresh: # on ré-essaye en forçant le recalcul
                return rtmpDownload(rtmpUrl, swfPlayerUrl, True,
                                    False, fileName)
        else:               # rtmpdump computation & refresh KO →
            log.warning ('Veuillez ré-essayer plus tard (pb réseau ou algo?)')
    elif rtmpProc.returncode == 2:   # téléchargement incomplet →
        log.info('Téléchargement incomplet: nouvel essai dans 3s...')
        time.sleep(3)                # petite temporisation
        if swfComputeHashSize:       # pas la peine de les recalculer
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName, swfHash, swfSize)
        elif swfForceRefresh:   # pas la peine de le refaire
            return rtmpDownload(rtmpUrl, swfPlayerUrl, False,
                                swfComputeHashSize , fileName)
        else:                   # on rappelle avec les mêmes options
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName, swfHash, swfSize)
    else:
        return rtmpProc.returncode # = 0

def downloadWatVideo(videoUrl,
                     swfPlayerUrl,
                     swfForceRefresh,
                     swfComputeHashSize):
    """ recuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT)"""
    log.debug('→downloadWatVideo(%s, %s, %s, %s)' % (
            videoUrl, swfPlayerUrl, swfForceRefresh, swfComputeHashSize))
    # timeout en secondes
    socket.setdefaulttimeout(90)
    debut_id = ''
    html = urllib2.urlopen(videoUrl).read()
    # log.debug('html=%s' %(html))
    nom = videoUrl.split('/')[-1:][0]
    no = nom.split('.')[-2:][0]
    soup = BeautifulSoup.BeautifulSoup(html)
    # log.debug('soup=%s' %(soup))
    site = urlparse(videoUrl).netloc
    if 'tmc.tv' in site or 'tf1.fr' in site:
        debut_id = str(soup.find('div', attrs={'class' : 'unique' }))
    if 'nt1.tv' in site or 'hd1.tv' in site:
        debut_id = str(soup.find('section', attrs={'class' : 'player-unique' }))
    id = [x.strip() for x in re.findall("mediaId :([^,]*)", debut_id)][0]
    referer = [x.strip() for x in re.findall('url : "(.*?)"', debut_id)][0]
    jsonVideoInfos = get_soup(WEBROOTWAT+'/interface/contentv3/'+id, referer, ua)
    videoInfos = json.loads(jsonVideoInfos)
    # log.debug('videoInfos=%s' % (videoInfos))
    try:
        HD = videoInfos["media"]["files"][0]["hasHD"]
    except:
        HD = False

    NumberOfParts = len(videoInfos["media"]["files"])
    ListOfIds = []
    for iPart in range(NumberOfParts):
        ListOfIds.append(videoInfos["media"]["files"][iPart]["id"])
    log.debug('NumberOfParts=%s' % (NumberOfParts))
    for PartId in ListOfIds:
        id_url1 = get_wat(PartId, HD)
        req  = urllib2.Request(id_url1)
        req.add_header('User-Agent', ua)
        req.add_header('Referer', referer)
        data = urllib2.urlopen(req).read()
        # log.debug('data=%s' % (data))
        if data[0:4] == 'http':
            if not checkExternalProgram(curlEx):
                log.warning('Ce script requiert %s' % (curlEx))
            else:
                arguments = '%s "%s" -C - -L -g -A "%s" -o "%s.mp4"' % (
                    curlEx, data, ua, no + "-" + str(PartId))
                log.info(arguments)
                process = subprocess.Popen(arguments,
                                           stdout=subprocess.PIPE,
                                           shell=True).communicate()[0]
            # no retry loop?
        if data[0:4] == 'rtmp':
            # vérification de la présence de rtmpdump v2.4 ou v2.5
            if not (checkExternalProgram(rtmpdumpEx, '-help', 'v2.4') or 
                    checkExternalProgram(rtmpdumpEx, '-help', 'v2.5')): # pas top
                log.warning('Ce script requiert %s v2.4 ou v2.5' % (rtmpdumpEx))
            else:
                if '.hd' in data:
                    rtmpUrl = re.search('rtmpte://(.*)hd', data).group(0)
                if '.h264' in data:
                    rtmpUrl = re.search('rtmpte://(.*)h264', data).group(0)
                # log.debug('rtmpUrl=%s'%(rtmpUrl))
                rtmpUrl = rtmpUrl.replace('rtmpte','rtmpe')
                fName=str(no) + '-' + str(PartId) # nom du fichier sans extension
                fileName=fName+'.mp4'             # nom du fichier avec extension
                if rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName) == 0:
                    log.info('Téléchargement terminé')
                    # ffmpeg est-il disponible?
                    if not checkExternalProgram(ffmpegEx):
                        log.info("L'installation de ffmpeg sur votre système" +
                                 " permettrait de corriger automatiquement" +
                                 " le conteneur de la vidéo (flash→mp4).")
                    else:
                        log.info('conversion ffmpeg fileName → tmpFileName' +
                                 ' (pour corriger le conteneur)')
                        tmpFileName = fName+'.tmp.mp4'
                        ffmpegCmd = ('%s -i "%s" -acodec copy -vcodec' +
                        ' copy "%s"') % (ffmpegEx, fileName, tmpFileName)
                        ffmpegCall = shlex.split(ffmpegCmd)
                        ffmpegProc = subprocess.Popen(ffmpegCall,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.STDOUT)
                        (stdout, stderr) = ffmpegProc.communicate()
                        if ffmpegProc.returncode != 0:
                            log.error('La conversion ffmpeg s\'est terminée' +
                                      ' avec le code d\'erreur %i.\nLe' +
                                      ' fichier %s est néanmois disponible' % (
                                    ffmpegProc.returncode, fileName))
                        else:
                            log.debug('remplacement tmpFileName → fileName')
                            os.rename(tmpFileName, fileName)
                        log.info('%s est maintenant disponible!' % (fileName))
                else:
                    log.info('Problème réseau ou algo?')

def main():
    """
    Analyse les arguments et lance le téléchargement
    """
    parser=argparse.ArgumentParser(prog=scriptName,
                                   description='Récuperation de vidéos sur' +
                                   ' TF1/TMC/NT1/HD1 (donc WAT).',
                                   version='%s v%s' % (scriptName,
                                                       scriptVersion))
    verbOrLog=parser.add_mutually_exclusive_group()
    verbOrLog.add_argument('-V', '--verbose',
                           help="affiche des messages",
                           dest='verbose',
                           action='store_true',
                           default=False)
    verbOrLog.add_argument('-l', '--log',
                           help="logue les messages",
                           dest='log',
                           action='store_const',
                           const='%s-%s.log' % (scriptName,
                                                strftime("%Y%m%d%H%M%S",
                                                         localtime())),
                           metavar='FILE')
    parser.add_argument('-p', '--swf-player-url',
                        help='url du player swf à utiliser (défaut= %s)' % (
            defaultSwfPlayerUrl),
                        dest='swfPlayerUrl',
                        default=defaultSwfPlayerUrl,
                        action='store',
                        metavar='URL')
    parser.add_argument('-f', '--swf-force-refresh',
                        help='force la vérification du hash/size du player swf' +
                        ' (met éventuellement à jour ~/.swfinfo)',
                        dest='swfForceRefresh',
                        default=False,
                        action='store_true')
    parser.add_argument('-c', '--swf-compute-hash-size',
                        help='calcul du hash/size par le script',
                        dest='swfComputeHashSize',
                        default=False,
                        action='store_true')
    parser.add_argument('url',
                        help='url de la page de la video',
                        metavar='URL',
                        nargs='+')
    args=parser.parse_args()

    if args.verbose:
        logging.basicConfig(format='%(levelname)s:\t%(asctime)s: %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.INFO)
        log.info('verbose mode')
    else:
        if args.log:
            logging.basicConfig(filename=args.log,
                                format='%(levelname)s:\t%(asctime)s: %(message)s',
                                datefmt='%H:%M:%S',
                                level=logging.DEBUG)
            log.info(args.log)
        else:
            logging.basicConfig(format='%(message)s',
                                datefmt='%H:%M:%S',
                                level=logging.WARNING)
    if args.url:
        for url in args.url:
            log.info('url: %s' % (args.url))
            downloadWatVideo(url,
                             args.swfPlayerUrl,
                             args.swfForceRefresh,
                             args.swfComputeHashSize)

if __name__ == "__main__":
    main()

Je l'ai testée sur plusieurs urls, avec diverses options et en jouant à débrancher puis rebrancher la prise réseau... je crois que ça fonctionne bien cool

J'essayerai de penser à curl la prochaine fois! wink

À+

Hors ligne

#265 Le 04/06/2013, à 13:12

11gjm

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,

@Pacome : Merci pour cette nouvelle version ( et pour ton travail ) .

Pourrais-tu nous indiquer quelques exemples de lignes de commandes ?

Cordialement .

Hors ligne

#266 Le 04/06/2013, à 19:28

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

@ pacome

Bravo pour ton code !

J'ai trouvé quelques problèmes en testant

gg@gg-SATELLITE-L755:~$ python watdl.py http://videos.tf1.fr/les-experts-manhattan/episode-6-saison-03-publicite-macabre-7978324.html
Traceback (most recent call last):
  File "watdl.py", line 379, in <module>
    main()
  File "watdl.py", line 376, in main
    args.swfComputeHashSize)
  File "watdl.py", line 299, in downloadWatVideo
    ffmpegProc.returncode, fileName))
TypeError: not all arguments converted during string formatting
[1]+  Fini            
gg@gg-SATELLITE-L755:~$ python watdl.py http://www.hd1.tv/une-famille-formidable/videos/une-famille-formidable-tous-en-scene-7976100-1069.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0 1678M    0  110k    0     0   1428      0  14d 06h  0:01:19  14d 06h   707
curl: (18) transfer closed with 1759662431 bytes remaining to read
gg@gg-SATELLITE-L755:~$ 

Je vais regarder ce qui se passe.


Archlinux sur Xiaomi Air 13

Hors ligne

#267 Le 04/06/2013, à 21:56

11gjm

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,

@k3c : Tests .

N°1

python watdl.py "http://videos.tf1.fr/les-experts-manhattan/episode-6-saison-03-publicite-macabre-7978324.html"

Création du fichier "episode-6-saison-03-publicite-macabre-7978324-10561237.mp4"
puis chargement jusqu'à 27Mo
---
Traceback (most recent call last):
  File "watdl.py", line 379, in <module>
    main()
  File "watdl.py", line 376, in main
    args.swfComputeHashSize)
  File "watdl.py", line 302, in downloadWatVideo
    os.rename(tmpFileName, fileName)
WindowsError: [Error 183] Impossible de crÚer un fichier dÚjÓ existant
---
puis 3mn , plus tard : episode-6-saison-03-publicite-macabre-7978324-10561237.tmp.mp4 ( de 26Mo )

Puis le crash (???) .

N°2 : Édité à 23H10

python watdl.py "http://www.hd1.tv/une-famille-formidable/videos/une-famille-formidable-tous-en-scene-7976100-1069.html"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
 24 1678M   24  407M    0     0  99544      0  4:54:38  1:11:32  3:43:06   99k
curl: (18) transfer closed with 1332486755 bytes remaining to read

durée de la vidéo (visible) 26mn sur 1H30
Cordialement .

Dernière modification par 11gjm (Le 04/06/2013, à 23:12)

Hors ligne

#268 Le 04/06/2013, à 22:11

pacome

Re : TVDownloader: télécharger les médias du net ! [2]

Bonsoir,

@11gjm & k3c:
Merci pour vos retour (et désolé pour les bugs! sad)
Au moins une erreur est due à un mauvais formatage de chaîne: je suis tombé sur je ne sais plus quelle PEP qui recommandait de coder en 80 colonnes et j'ai fait quelques modifs pour m'y conformer avant de poster...

Je reprends ça rapidement.

À+

(Édit: et je rajoute un tuto pour me faire pardonner wink)

Dernière modification par pacome (Le 04/06/2013, à 22:12)

Hors ligne

#269 Le 04/06/2013, à 23:14

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

Hors sujet, désolé

Autre chose, je me suis demandé si je pouvais modifier l'extension Firefox de KSV
Hds Link detector
pour qu'elle génère pour pluzz seulement un code avec
--outfile un_joli_nom_de_fichier.flv
à partir de la fin du html
exemple, à partir de
http://pluzz.francetv.fr/videos/miss_fi … 93336.html
générer un --outfile miss_fisher_enquete_saison1_ep1_
(on peut chipoter et enlever l'underscore final)

Mes modifications ne fonctionnant pas, je vais détailler ce que j'ai fait.

Dans firefox, si je tape

about:support

ça me montre entre autres choses une ligne

HDS Link Detector 0.5 true jid0-HFFmJoceGjTSKDBEWPpzfX9By7I@jetpack

les extensions firefox étant dans

~/.mozilla/firefox/*default/extensions

il faut regarder le fichier d'extension .xpi commençant par jid0 comme indiqué ci-dessus
Ce fichier est comme un zip, on le décompresse, et on trouve plein de fichiers, dont un
main.js
qui s'occupe de générer la commande de KSV

Je l'ai modifié, j'ai recréé le .xpi, je l'ai installé,  mais sans effet, l'extension hds-link-detector ne fonctionne plus.

Le début de "mon" main.js modifié

// The main module of the hds-link-detector Add-on.
// Modules needed are `require`d, similar to CommonJS modules.
var {Cc, Ci, Cr} = require('chrome');
var clipboard = require('sdk/clipboard');
var events = require("sdk/system/events");
var notifications = require("sdk/notifications");
var self = require("sdk/self");
var widget = require("sdk/widget");

var enabled = false;
var manifestUrl = false;
var hdsDisabled = self.data.url("hds_disabled.png");
var hdsEnabled = self.data.url("hds_enabled.png");

function onHttpRequest(event)
{
    if (manifestUrl)
    {
        var httpChannel = event.subject.QueryInterface(Ci.nsIHttpChannel);
        var fullUrl = httpChannel.URI.path;
        outfil = fullUrl.split("/").slice(-1)[0];


        // Double slash in beginning of relative url causes resolve function to
        // return wrong absolute url
        if (fullUrl.substr(0, 2) == "//") fullUrl = fullUrl.substr(1);
        fullUrl = httpChannel.URI.resolve(fullUrl);

        var url = fullUrl;
        if (url.indexOf("?") != -1) url = url.substr(0, url.indexOf("?"));
        if (url.search(/seg\d+\-frag\d+$/i) != -1)
        {
            var command = "php AdobeHDS.php --manifest \"" + manifestUrl + "\" --delete --outfile " + outfil;
            var authParams = false;

en fait j'ai ajouté la ligne

  outfil = fullUrl.split("/").slice(-1)[0];

et plus loin quand on crée la commande

 var command = "php AdobeHDS.php --manifest \"" + manifestUrl + "\" --delete --outfile " + outfil;

Clairement ça ne fonctionne pas, mais comme je ne connais pas le Javascript, si une âme charitable peut m'aider, je lui en serai reconnaisant.

Merci

Dernière modification par k3c (Le 04/06/2013, à 23:27)


Archlinux sur Xiaomi Air 13

Hors ligne

#270 Le 05/06/2013, à 01:03

pacome

Re : TVDownloader: télécharger les médias du net ! [2]

J'ai recollé les morceaux de chaînes dans cette 0.9.4.5:

#!/usr/bin/python
#-*- coding:utf-8 -*-
# TF1 TMC NT1 HD1 V0.9.4.5 par k3c, bibichouchou et pacome

# args & log
import argparse
from time import localtime, strftime
import logging

import subprocess, re, sys, shlex
import socket
import urllib2                  # → urlopen & exceptions
import hashlib                  # → sha256sum
import hmac
import zlib
import StringIO
import time, md5, random, urllib2, json
import bs4 as BeautifulSoup
import os                       # → os.rename
from urlparse import urlparse

# global var
scriptName='watdl.py'
scriptVersion='0.9.4.5'

# programmes externes utilisés
ffmpegEx='ffmpeg'               # ou avconv
rtmpdumpEx='rtmpdump'
curlEx='curl'

# Player swf
defaultSwfPlayerUrl='http://www.wat.tv/images/v40/PlayerWat.swf'
KEY = "Genuine Adobe Flash Player 001"

listeUserAgents = [ 
    'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; fr-fr) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
    'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1',
    'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.',
    'Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) midori',
    'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
    'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.940.0 Safari/535.8' ]

WEBROOTWAT="http://www.wat.tv"
wat_url="/web/"
jsonVideosInfos=""

# random user agent
ua=random.choice(listeUserAgents)

# global logger
log=logging.getLogger(__name__)

def checkExternalProgram(prog, optArg='', expectedValue=''):
    """ Permet de vérifier la présence des programmes externes requis """
    log.debug('→checkExternalProgram(%s, %s, %s)'%(prog, optArg, expectedValue))
    args=shlex.split('%s %s' % (prog, optArg))
    try:
        process=subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
        stdout, stderr = process.communicate()
        if expectedValue == '':
            return True
        else:
            if expectedValue in stdout: # à améliorer pour versions > ...
                return True
            else:
                return False
    except OSError:
        log.error('Le programme %s n\'est pas présent sur votre système' % (prog))
        return False

def get_soup(url, referer, ua):
    """ on récupère la soupe """
    req  = urllib2.Request(url)
    req.add_header('User-Agent', ua)
    req.add_header('Referer', referer)
    soup = urllib2.urlopen(req).read()
    # log.debug('←get_soup(%s, %s, %s): %s' % (url, referer, ua, soup))
    return soup

def get_wat(id, HDFlag):
    """la fonction qui permet de retrouver une video sur wat"""
    def base36encode(number):
        if not isinstance(number, (int, long)):
            raise TypeError('number must be an integer')
        if number < 0:
            raise ValueError('number must be positive')
        alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        base36 = ''
        while number:
            number, i = divmod(number, 36)
            base36 = alphabet[i] + base36
        return base36 or alphabet[0]
    if HDFlag:
        wat_url = "/webhd/"
    else:
        wat_url = "/web/"
    ts = base36encode(int(time.time())-60)
    timesec = hex(int(ts, 36))[2:]
    while(len(timesec)<8):
        timesec = "0"+timesec
    token = md5.new(
        "9b673b13fa4682ed14c3cfa5af5310274b514c4133e9b3a81e6e3aba00912564" +
        wat_url + str(id) + "" + timesec).hexdigest()
    id_url1 = (WEBROOTWAT + "/get" + wat_url + str(id) + "?token=" + token +
    "/" + str(timesec) + "&country=FR&getURL=1")
    # log.debug('←get_wat(%s, %s):%s' %(id, HDFlag, id_url1))
    return id_url1

def swfPlayerHashAndSize(swfPlayerUrl):
    """
    Calcule et renvoie le tuple (hash, taille) du player swf
    ← (swfHash, swfSize)
    """
    global KEY
    try:
        swfPlayer= urllib2.urlopen(swfPlayerUrl).read()
    except (ValueError, urllib2.URLError):
        log.error('→swfPlayerHashAndSize(%s): Url invalide!' % (swfPlayerUrl))
        raise
    except urllib2.HTTPError:
        log.error('→swfPlayerHashAndSize(%s): Pb http!' % (swfPlayerUrl))
        raise

    swfPlayerHash=hashlib.sha256(swfPlayer).hexdigest()
    if type(swfPlayer) is str:
        swfData=StringIO.StringIO(swfPlayer)
    swfData.seek(0, 0)
    magic=swfData.read(3)
    if magic != "CWS":
        log.error("Pas de CWS...")
        raise ValueError('NoCWS')
    else:
        unzPlayer="FWS" + swfData.read(5) + zlib.decompress(swfData.read())
        unzPlayerSize=len(unzPlayer)
        unzPlayerHash = hmac.new(KEY, unzPlayer, hashlib.sha256).hexdigest()
    log.debug('←computeSwfPlayerHash(%s):(%s, %s)' %(
            swfPlayerUrl, unzPlayerHash, unzPlayerSize))
    return (unzPlayerHash, unzPlayerSize)

def rtmpDownload(rtmpUrl,
                 swfPlayerUrl,
                 swfForceRefresh,
                 swfComputeHashSize,
                 fileName,
                 swfHash=None,
                 swfSize=None):
    """ Appel de rtmpdump avec traitement des options et reprise (récursif)
    """
    log.debug('→rtmpDownload(%s, %s, %s, %s, %s, %s, %s)' % (
            rtmpUrl, swfPlayerUrl, swfForceRefresh, swfComputeHashSize,
            fileName, swfHash, swfSize))
    rtmpCmd = '%s --resume --rtmp "%s" --port 443 --timeout 10' % (
        rtmpdumpEx, rtmpUrl)    # initialisation de la commande

    if swfComputeHashSize:
        if not swfHash and not swfSize: # pour ne pas recalculer en récursion
            try:
                (swfHash, swfSize)=swfPlayerHashAndSize(swfPlayerUrl)
            except:
                log.warning('Impossible de calculer le hash/size du player swf!')
                log.info('calcul du hash/size par %s' % (rtmpdumpEx))
                return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                    False, fileName)
            if swfForceRefresh:
                log.warning('pas encore codé!')
                # et je ne sais pas si ça le sera... ;)
            rtmpCmd += ' --swfhash %s --swfsize %i' % (swfHash, swfSize)
    else:
        if swfForceRefresh:
            rtmpCmd += ' --swfVfy %s --swfAge 0' % (swfPlayerUrl)
        else:
            rtmpCmd += ' --swfVfy %s' % (swfPlayerUrl)
    rtmpCmd += ' -o "%s"' % (fileName)
    log.info(rtmpCmd)
    rtmpCall = shlex.split(rtmpCmd)
    rtmpProc = subprocess.Popen(rtmpCall,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
    (stdout, stderr) = rtmpProc.communicate()
    if rtmpProc.returncode == 1:   # sortie en erreur →
        if swfComputeHashSize:     # on ré-essaye avec le calcul par rtmpdump
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                 False, fileName)
        elif not swfForceRefresh: # on ré-essaye en forçant le recalcul
                return rtmpDownload(rtmpUrl, swfPlayerUrl, True,
                                    False, fileName)
        else:               # rtmpdump computation & refresh KO →
            log.warning ('Veuillez ré-essayer plus tard (pb réseau ou algo?)')
    elif rtmpProc.returncode == 2:   # téléchargement incomplet →
        log.info('Téléchargement incomplet: nouvel essai dans 3s...')
        time.sleep(3)                # petite temporisation
        if swfComputeHashSize:       # pas la peine de les recalculer
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName, swfHash, swfSize)
        elif swfForceRefresh:   # pas la peine de le refaire
            return rtmpDownload(rtmpUrl, swfPlayerUrl, False,
                                swfComputeHashSize , fileName)
        else:                   # on rappelle avec les mêmes options
            return rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName, swfHash, swfSize)
    else:
        return rtmpProc.returncode # = 0

def downloadWatVideo(videoUrl,
                     swfPlayerUrl,
                     swfForceRefresh,
                     swfComputeHashSize):
    """ recuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT)"""
    log.debug('→downloadWatVideo(%s, %s, %s, %s)' % (
            videoUrl, swfPlayerUrl, swfForceRefresh, swfComputeHashSize))
    # timeout en secondes
    socket.setdefaulttimeout(90)
    debut_id = ''
    html = urllib2.urlopen(videoUrl).read()
    # log.debug('html=%s' %(html))
    nom = videoUrl.split('/')[-1:][0]
    no = nom.split('.')[-2:][0]
    soup = BeautifulSoup.BeautifulSoup(html)
    # log.debug('soup=%s' %(soup))
    site = urlparse(videoUrl).netloc
    if 'tmc.tv' in site or 'tf1.fr' in site:
        debut_id = str(soup.find('div', attrs={'class' : 'unique' }))
    if 'nt1.tv' in site or 'hd1.tv' in site:
        debut_id = str(soup.find('section', attrs={'class' : 'player-unique' }))
    id = [x.strip() for x in re.findall("mediaId :([^,]*)", debut_id)][0]
    referer = [x.strip() for x in re.findall('url : "(.*?)"', debut_id)][0]
    jsonVideoInfos = get_soup(WEBROOTWAT+'/interface/contentv3/'+id, referer, ua)
    videoInfos = json.loads(jsonVideoInfos)
    # log.debug('videoInfos=%s' % (videoInfos))
    try:
        HD = videoInfos["media"]["files"][0]["hasHD"]
    except:
        HD = False

    NumberOfParts = len(videoInfos["media"]["files"])
    ListOfIds = []
    for iPart in range(NumberOfParts):
        ListOfIds.append(videoInfos["media"]["files"][iPart]["id"])
    log.debug('NumberOfParts=%s' % (NumberOfParts))
    for PartId in ListOfIds:
        id_url1 = get_wat(PartId, HD)
        req  = urllib2.Request(id_url1)
        req.add_header('User-Agent', ua)
        req.add_header('Referer', referer)
        data = urllib2.urlopen(req).read()
        # log.debug('data=%s' % (data))
        if data[0:4] == 'http':
            if not checkExternalProgram(curlEx):
                log.warning('Ce script requiert %s' % (curlEx))
            else:
                arguments = '%s "%s" -C - -L -g -A "%s" -o "%s.mp4"' % (
                    curlEx, data, ua, no + "-" + str(PartId))
                log.info(arguments)
                process = subprocess.Popen(arguments,
                                           stdout=subprocess.PIPE,
                                           shell=True).communicate()[0]
            # no retry loop?
        if data[0:4] == 'rtmp':
            # vérification de la présence de rtmpdump v2.4 ou v2.5
            if not (checkExternalProgram(rtmpdumpEx, '-help', 'v2.4') or 
                    checkExternalProgram(rtmpdumpEx, '-help', 'v2.5')): # pas top
                log.warning('Ce script requiert %s v2.4 ou v2.5' % (rtmpdumpEx))
            else:
                if '.hd' in data:
                    rtmpUrl = re.search('rtmpte://(.*)hd', data).group(0)
                if '.h264' in data:
                    rtmpUrl = re.search('rtmpte://(.*)h264', data).group(0)
                # log.debug('rtmpUrl=%s'%(rtmpUrl))
                rtmpUrl = rtmpUrl.replace('rtmpte','rtmpe')
                fName=str(no) + '-' + str(PartId) # nom du fichier sans extension
                fileName=fName+'.mp4'             # nom du fichier avec extension
                if rtmpDownload(rtmpUrl, swfPlayerUrl, swfForceRefresh,
                                swfComputeHashSize, fileName) == 0:
                    log.info('Téléchargement terminé')
                    # ffmpeg est-il disponible?
                    if not checkExternalProgram(ffmpegEx):
                        log.info("L'installation de ffmpeg sur votre système permettrait de corriger automatiquement le conteneur de la vidéo (flash→mp4).")
                    else:
                        log.info('conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)')
                        tmpFileName = fName+'.tmp.mp4'
                        ffmpegCmd = '%s -i "%s" -acodec copy -vcodec copy "%s"' % (ffmpegEx, fileName, tmpFileName)
                        ffmpegCall = shlex.split(ffmpegCmd)
                        ffmpegProc = subprocess.Popen(ffmpegCall,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.STDOUT)
                        (stdout, stderr) = ffmpegProc.communicate()
                        if ffmpegProc.returncode != 0:
                            log.error('La conversion ffmpeg s\'est terminée avec le code d\'erreur %i.\nLe fichier %s est néanmois disponible' % (
                                    ffmpegProc.returncode, fileName))
                        else:
                            log.debug('remplacement tmpFileName → fileName')
                            os.rename(tmpFileName, fileName)
                        log.info('%s est maintenant disponible!' % (fileName))
                else:
                    log.info('Problème réseau ou algo?')

def main():
    """
    Analyse les arguments et lance le téléchargement
    """
    parser=argparse.ArgumentParser(prog=scriptName,
                                   description='Récuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT).',
                                   version='%s v%s' % (scriptName,
                                                       scriptVersion))
    verbOrLog=parser.add_mutually_exclusive_group()
    verbOrLog.add_argument('-V', '--verbose',
                           help="affiche des messages",
                           dest='verbose',
                           action='store_true',
                           default=False)
    verbOrLog.add_argument('-l', '--log',
                           help="logue les messages",
                           dest='log',
                           action='store_const',
                           const='%s-%s.log' % (scriptName,
                                                strftime("%Y%m%d%H%M%S",
                                                         localtime())),
                           metavar='FILE')
    parser.add_argument('-p', '--swf-player-url',
                        help='url du player swf à utiliser (défaut= %s)' % (defaultSwfPlayerUrl),
                        dest='swfPlayerUrl',
                        default=defaultSwfPlayerUrl,
                        action='store',
                        metavar='URL')
    parser.add_argument('-f', '--swf-force-refresh',
                        help='force la vérification du hash/size du player swf (met éventuellement à jour ~/.swfinfo)',
                        dest='swfForceRefresh',
                        default=False,
                        action='store_true')
    parser.add_argument('-c', '--swf-compute-hash-size',
                        help='calcul du hash/size par le script',
                        dest='swfComputeHashSize',
                        default=False,
                        action='store_true')
    parser.add_argument('url',
                        help='url de la page de la video',
                        metavar='URL',
                        nargs='+')
    args=parser.parse_args()

    if args.verbose:
        logging.basicConfig(format='%(levelname)s:\t%(asctime)s: %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.INFO)
        log.info('verbose mode')
    else:
        if args.log:
            logging.basicConfig(filename=args.log,
                                format='%(levelname)s:\t%(asctime)s: %(message)s',
                                datefmt='%H:%M:%S',
                                level=logging.DEBUG)
            log.info(args.log)
        else:
            logging.basicConfig(format='%(message)s',
                                datefmt='%H:%M:%S',
                                level=logging.WARNING)
    if args.url:
        for url in args.url:
            log.info('url: %s' % (args.url))
            downloadWatVideo(url,
                             args.swfPlayerUrl,
                             args.swfForceRefresh,
                             args.swfComputeHashSize)

if __name__ == "__main__":
    main()

Mais Il y a clairement un gag avec les urls de tf1.
Je viens de tester les urls suivantes avec succès:

Pour cette dernière j'ai arrêté le téléchargement en cours (avec un Ctrl-c) et relancé la même commande pour le reprendre et ça a fonctionné (il faudra vraiment rajouter la boucle de reprise dans le code). J'avoue ne pas avoir attendu la fin, mais j'obtiens un fichier lisible.

Par contre pour les urls suivantes:

je récupère un fichier de 27Mo (resp. 30Mo) illisible qui contient pourtant la bande son (obtenue en forçant la conversion avec avconv).
J'avais déjà eu ce genre de truc en testant les players swf: du coup je me demande s'il y a un player spécifique pour tf1 ou une modif dans "la soupe"...

@k3c:
J'avais essayé de bricoler un plugin en m'inspirant d'un tuto... je ne sais plus si il n'y a pas une astuce pour reconstruire le xpi...

@11gjm: (rapidement, j'y reviendrai si nécessaire)

$ ./watdl.py --help
usage: watdl.py [-h] [-v] [-V | -l] [-p URL] [-f] [-c] URL [URL ...]

Récuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT).

positional arguments:
  URL                   url de la page de la video

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  -V, --verbose         affiche des messages
  -l, --log             logue les messages
  -p URL, --swf-player-url URL
                        url du player swf à utiliser (défaut=
                        http://www.wat.tv/images/v40/PlayerWat.swf)
  -f, --swf-force-refresh
                        force la vérification du hash/size du player swf (met
                        éventuellement à jour ~/.swfinfo)
  -c, --swf-compute-hash-size
                        calcul du hash/size par le script

J'utilise assez souvent l'option --verbose pour savoir où en est le script (j'ai essayé d'afficher une "progress-bar", mais ce n'est pas encore au point), ou (exclusif) --log pour avoir plus de détails dans un fichier texte.
Le --swf-player-url va peut-être nous être utile pour tester d'autres players, mais pour un usage courant:

$ ./watdl.py -V http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846.html http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846.html http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846.html
INFO:	00:47:00: verbose mode
INFO:	00:47:00: url: ['http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846.html']
INFO:	00:47:02: rtmpdump --resume --rtmp "rtmpe://wske.wat.tv/ondemand/mp4:vod/H264-384x288/28/59/10572859.h264" --port 443 --timeout 10 --swfVfy http://www.wat.tv/images/v40/PlayerWat.swf -o "saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846-10572859.mp4"
INFO:	00:47:07: Téléchargement terminé
INFO:	00:47:07: conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)
INFO:	00:47:07: saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846-10572859.mp4 est maintenant disponible!
INFO:	00:47:07: url: ['http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846.html']
INFO:	00:47:08: rtmpdump --resume --rtmp "rtmpe://wske.wat.tv/ondemand/mp4:vod/H264-384x288/92/29/10549229.h264" --port 443 --timeout 10 --swfVfy http://www.wat.tv/images/v40/PlayerWat.swf -o "saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846-10549229.mp4"
INFO:	00:47:14: Téléchargement terminé
INFO:	00:47:15: conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)
INFO:	00:47:15: saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846-10549229.mp4 est maintenant disponible!
INFO:	00:47:15: url: ['http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846.html', 'http://videos.nt1.tv/fringe/saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846.html']
INFO:	00:47:17: rtmpdump --resume --rtmp "rtmpe://wske.wat.tv/ondemand/mp4:vod/H264-384x288/29/77/10542977.h264" --port 443 --timeout 10 --swfVfy http://www.wat.tv/images/v40/PlayerWat.swf -o "saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846-10542977.mp4"
INFO:	00:47:23: Téléchargement terminé
INFO:	00:47:23: conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)
INFO:	00:47:23: saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846-10542977.mp4 est maintenant disponible!

fournit

$ ls -oh saison-3-la-bande-annonce-de-l-episode-1*
-rw-rw-r-- 1 pacome 1,7M juin   5 00:47 saison-3-la-bande-annonce-de-l-episode-11-de-l-homme-a-la-machine-7973789-846-10542977.mp4
-rw-rw-r-- 1 pacome 1,8M juin   5 00:47 saison-3-la-bande-annonce-de-l-episode-14-appartement-6b-7976321-846-10549229.mp4
-rw-rw-r-- 1 pacome 1,4M juin   5 00:47 saison-3-la-bande-annonce-de-l-episode-17-passager-clandestin-7987449-846-10572859.mp4

À+

Hors ligne

#271 Le 05/06/2013, à 07:27

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

@ pacome

>>>J'avais essayé de bricoler un plugin en m'inspirant d'un tuto... je ne sais plus si il n'y a pas une astuce pour reconstruire le xpi...

Apparemment non, sur mozillazine j'ai trouvé des liens, ils disent de zipper, puis renommer le .zip en .xpi

Ca s'installe bien, sans râler, mais je n'ai plus le symbole en bas à droite de hds link detector, et ça ne génère plus de commande
adobehds.php....

Je reprends ce soir


Archlinux sur Xiaomi Air 13

Hors ligne

#272 Le 05/06/2013, à 13:31

11gjm

Re : TVDownloader: télécharger les médias du net ! [2]

Bonjour ,

@Pacome : Merci .

Cordialement .

Hors ligne

#273 Le 05/06/2013, à 19:18

thom83

Re : TVDownloader: télécharger les médias du net ! [2]

k3c a écrit :

Ca s'installe bien, sans râler, mais je n'ai plus le symbole en bas à droite

Même avec un «Ctrl+Shift+K» qu'il est possible d'oublier ?

Hors ligne

#274 Le 05/06/2013, à 19:18

Nai2Lille

Re : TVDownloader: télécharger les médias du net ! [2]

Merci infiniment @Pacome pour ce message ! big_smile
J'ai pu télécharger et regarder tranquillement Au Royaume des Plantes d'Arte !
Je ne l'avais pas trouvé avec arte+7recorder (qui a changé de nom en Qarte, je viens de le voir)

Par contre, existe-t-il quelque chose de similaire pour télécharger les vidéos du groupe M6 ?
Je souhaite en particulier regarder Xplora que j'aime beaucoup.

Le script "AdobeHDS.php" permet-il de télécharger Xplora ?
Si oui, je n'ai pas réussi. "HDS Link Detector" ne me montre aucun lien à copier...

Je vous remercie infiniment pour votre aide !
Et pour votre gentillesse ! smile
Et pour la clarté de vos messages ! big_smile

Bien à vous,
Naï.


OS : Ubuntu 13.04 32 bits
Processeur : Intel® Celeron(R) CPU 550 @ 2.00GHz
Mémoire : 2Gio
Carte graphique : Intel® 965GM x86/MMX/SSE2

Hors ligne

#275 Le 05/06/2013, à 22:11

k3c

Re : TVDownloader: télécharger les médias du net ! [2]

@ Nai2Lille

Rien ne sait télécharger M6, car ils ont mis des DRM, et c'est loin d'être trivial à résoudre.
Le script AdobeHDS.php, déclare forfait dans ce cas. Captvty aussi.

Edit : une discussion intéressante sur ce thème
http://code.google.com/p/get-flash-vide … ail?id=379

Edit2 : KSV a mis à jour son script il y a 9 jours, il faut que je mette à jour ma version Python
https://github.com/K-S-V/Scripts
et que je lance son programme avec --update

Dernière modification par k3c (Le 05/06/2013, à 23:38)


Archlinux sur Xiaomi Air 13

Hors ligne