Contenu | Rechercher | Menus

Annonce

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.

À propos de l'équipe du forum.

#176 Le 11/05/2013, à 18:22

11gjm

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

Bonjour ,

@inbox : Merci pour l'info . Il n'empêche que c'est la galère !!!

Alors que si on met 3 point à la ligne : QUEL CONFORT !!!

Cordialement .

Hors ligne

#177 Le 11/05/2013, à 18:49

bibichouchou

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

@11gjm

j'avoue m'être toujours demandé pourquoi tes blocs de code se terminaient toujours par trois points et j'ai enfin l'explication big_smile
c'est à tout à ton honneur de penser à faciliter le travail des autres mais en l'occurrence, ces trois points ne sont pas nécessaires. et ne sont pas très esthétiques.
J'utilise toujours l'astuce du triple-clic qui est très pratique. d'accord, c'est un coup à prendre. note aussi que tu peux cliquer au début de la ligne de code, maintenir le clic et bouger ta souris vers le bas (comme s'il y avait ta ligne avec les trois points) et la sélection se fera aussi.

amicalement wink

Dernière modification par bibichouchou (Le 11/05/2013, à 18:51)

Hors ligne

#178 Le 11/05/2013, à 19:29

11gjm

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

Re-... ,

@bibichouchou :

> l'astuce du triple-clic qui est très pratique
Oui , cela fonctionne . Sorry pour le débordement .

A+ .

Hors ligne

#179 Le 12/05/2013, à 00:19

duocore

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

Bonsoir ,

j'ai essayer de voir ce script:python tf1_04.py http://videos.nt1.tv/haven/saison-2-epi … 9-846.html

j'ai eu ce fichier de créé:rtmpdump -r "rtmpte://wske.wat.tv/ondemand/mp4:vod/H264-384x288/08/05/10510805.h264" -c 1935 -m 10 -w ebb7a6fbdc9021db95e2bd537d73fabb9717508f085bea50bde75f7a8e27698c -x 343642 -o "saison-2-episode-1-malediction-7608719-846.mp4" " --resume"
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)
Erreur : le sous-process s'est terminé avec (le code d'erreur est 1)


pouvez vous m'aider

merci

Hors ligne

#180 Le 12/05/2013, à 08:18

pacome

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

Bonjour à tous.

Voici une version 0.9.4.2 corrigée de tmc_tf1.py (version 0.9.4) dans laquelle j'ai:

  • rétabli les options -w swfHash et -x swfSize à l'appel de rtmpdump (au lieu de -W swfPlayer; variables définies aux lignes 28 et 29)

  • rajouté le test de la présence de curl

  • légèrement modifié l'algo pour la conversion ffmpeg

  • remplacé optparse par argparse pour rajouter des options

  • rajouté l'utilisation du module logging pour gérer messages et logs

  • renommé le main() en downloadWatVideo(videoUrl)

  • regroupé dans le nouveau main() la gestion des options et des logs

@duocore: ta version n'utilise pas le bon hash/size; la version ci-dessous télécharge l'épisode de Haven.

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

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

import subprocess, re, sys, shlex
import socket
from urllib2 import urlopen
import time, md5, random, urllib2, json
import bs4 as BeautifulSoup
import os                       # → os.rename
from urlparse import urlparse

# global var
scriptName='tmc_tf1.py'
scriptVersion='0.9.4.2'

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

# hash et size du player swf (valide au 05/2013)
swfHash='0818931e9bfa764b9c33e42de6d06f924ac7fc244d0d4941019b9cdfe8706705'
swfSize=352043

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 downloadWatVideo(videoUrl):
    """ recuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT)"""
    # timeout en secondes
    log.debug('→downloadWatVideo(%s)' %(videoUrl))
    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:
                    data0 = re.search('rtmpte://(.*)hd', data).group(0)
                if '.h264' in data:
                    data0 = re.search('rtmpte://(.*)h264', data).group(0)
                log.debug('data0=%s'%(data0))
                data0 = data0.replace('rtmpte','rtmpe')
                fName=str(no) + '-' + str(PartId) # nom du fichier sans extension
                fileName=fName+'.mp4'             # nom du fichier avec extension
                rtmpCmd = '%s -e -r "%s" -c 443 -m 10 -w %s -x %i -o "%s"' % (
                    rtmpdumpEx, data0, swfHash, swfSize, fileName)
                log.info(rtmpCmd)
                arguments = shlex.split( rtmpCmd )
                cpt = 0 
                while True:
                    p = subprocess.Popen(arguments,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)
                    stdout, stderr = p.communicate()
                    if p.returncode != 0:
                        log.error('Le sous-process s\'est terminé avec le code d\'erreur ' + str(p.returncode) + ')')
                        if cpt > 5:
                            break
                        cpt += 1
                        log.error('Essai de reprise...')
                        time.sleep(3) 
                    else:
                        # 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:
                            tmpFileName=fName+'.tmp.mp4'
                            # conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)
                            ffmpegCmd='%s -i "%s" -acodec copy -vcodec copy "%s"' % (
                                ffmpegEx, fileName, tmpFileName)
                            arguments=shlex.split(ffmpegCmd)
                            p=subprocess.Popen(arguments,
                                               stdout=subprocess.PIPE,
                                               stderr=subprocess.PIPE)
                            stdout, stderr = p.communicate()
                            if p.returncode != 0:
                                log.error('La conversion ffmpeg s\'est terminée avec le code d\'erreur %i.\nLe fichier %s est néanmois disponible' % (
                                        p.returncode, fileName))
                            else:
                                # remplacement tmpFileName → fileName
                                os.rename(tmpFileName, fileName)
                        break

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('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:
        log.info('url: %s' % (args.url))
        downloadWatVideo(args.url)

if __name__ == "__main__":
    main()

Je n'ai donc toujours pas réussi à calculer le hash: soit la méthode de calcul (reprise de PluzzDL.py) est inadaptée, soit je n'ai pas encore trouvé la bonne adresse pour le player (peut-être générée par les javascripts...).
Si quelqu'un souhaite se pencher sur la question voici un petit script pour tester les players

#!/usr/bin/python
#-*- coding:utf-8 -*-

# generic
import argparse
from time import localtime, strftime
import logging

# specific
import base64
import urllib2                  # → pas que urlopen (exceptions, etc.)
import hashlib                  # → sha256sum
import zlib
import StringIO

# script globvars
scriptName='getSwfInfo'
scriptVersion='1.0'
versionString='%s v%s' % (scriptName, scriptVersion)

# default/valid values
validHash='0818931e9bfa764b9c33e42de6d06f924ac7fc244d0d4941019b9cdfe8706705'
validSize=352043

# global logger
log=logging.getLogger(__name__)

def computeSwfPlayerHash(swfPlayerUrl):
    """
    Essais → swf size & hash
    """
    try:
        swfPlayer= urllib2.urlopen(swfPlayerUrl).read()
    except ValueError:
        log.error('Url invalide: %s' %(swfPlayerUrl))
        return
    except urllib2.URLError:
        log.error("Pb avec l'url")
        return
    except urllib2.HTTPError:
        log.error("Pb http")
        return

    swfPlayerSize=len(swfPlayer)
    swfPlayerHash=hashlib.sha224(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...")
    else:
        unzPlayer="CWS" + swfData.read(5) + zlib.decompress(swfData.read())
        unzPlayerSize=len(unzPlayer)
        sha256Player=hashlib.sha256(unzPlayer)
        unzPlayerHash=sha256Player.hexdigest()
        # b64PlayerHash=base64.b64encode(unzPlayerHash.decode('hex'))
        b64PlayerHash=base64.urlsafe_b64encode(sha256Player.hexdigest().decode('hex'))

    log.info('url: %s\n' %(swfPlayerUrl))
    log.debug('*-*- Compressed -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
            swfPlayerSize, swfPlayerHash, len(swfPlayerHash)))
    log.info('*-*- Uncompressed -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
            unzPlayerSize, unzPlayerHash, len(unzPlayerHash)))
    log.debug('*-*- b64Encoded -*-*\n\thash: %s\n\thlen: %i\n' % (
            b64PlayerHash, len(b64PlayerHash)))


def main():
    """
    compute/display/log size & hash of swf player
    """
    parser=argparse.ArgumentParser(prog=scriptName,
                                     description='compute swf player hash.',
                                     version=versionString)
    parser.add_argument('-d', '--default',
                        help='show default value',
                        dest='displayValidHash',
                        action='store_true',
                        default=False)
    parser.add_argument('-u', '--url',
                        help='url of swf player',
                        dest='swfPlayerUrl',
                        action='store',
                        metavar='URL')
    verbOrLog=parser.add_mutually_exclusive_group()
    verbOrLog.add_argument('-V', '--verbose',
                           help="display information messages",
                           dest='verbose',
                           action='store_true',
                           default=False)
    verbOrLog.add_argument('-l', '--log',
                           help="log information messages",
                           dest='log',
                           action='store_const',
                           const='%s-%s.log' % (scriptName,
                                                strftime("%Y%m%d%H%M%S",
                                                         localtime())),
                           metavar='FILE')
    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')
    if args.log:
        logging.basicConfig(filename=args.log,
                            format='%(levelname)s:\t%(asctime)s: %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.DEBUG)
        logging.info(args.log)

    if args.swfPlayerUrl:
        log.debug('swfPlayerUrl: %s' % (args.swfPlayerUrl))
        computeSwfPlayerHash(args.swfPlayerUrl)

    if args.displayValidHash:
        log.info('*-*- Valid hash -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
                validSize, validHash, len(validHash)))
        
if __name__ == "__main__":
    main()

À+

Hors ligne

#181 Le 12/05/2013, à 10:59

Frédéric Stemmelin

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

Bonne nouvelle, le problème est réglé, et je remercie toutes les personnes qui m'ont aidées à trouver la solution ainsi que la personne à l'origine de ce merveilleux script (K-S-V).

@bibichouchou

Merci pour ta réponse, ça n'a pas marché, mais j'ai quand même compris quelque chose.

@thom83

Merci d'avoir testé pour moi, du coup j'ai bien compris que le problème venait de mon PC et non pas du site web ou du script en lui-même, vu que nos commandes sont semblables aux chiffres près.

@k3c

Je suis d'accord avec toi, copier la sortie du script aurai été intéressant et j'ai d'ailleurs essayé de le faire.
Dans mon explication plus bas tu va comprendre pourquoi je n'avais pas réussi à copier/coller la sortie du script (il faisait même planter pluma, l'éditeur de texte).


Pour faire simple, le problème vient de la façon dont j'ai téléchargé le fameux script php.
Sous Firefox, avec un clic droit sur l'ancien lien github du script que j'avais posté (https://github.com/K-S-V/Scripts/blob/m … obeHDS.php), avec option "enregistrer la cible sous", j'obtiens quelque chose comme ça:


<!DOCTYPE html>
<html>
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
    <meta charset='utf-8'>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Scripts/AdobeHDS.php at master · K-S-V/Scripts · GitHub</title>
    <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" />
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-114.png" />
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114.png" />
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-144.png" />
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144.png" />
    <link rel="logo" type="image/svg" href="http://github-media-downloads.s3.amazonaws.com/github-logo.svg" />
    <link rel="xhr-socket" href="/_sockets" />

Maintenant que j'ai trouvé comment télécharger proprement le script depuis github (https://raw.github.com/K-S-V/Scripts/ma … obeHDS.php), voici ce que j'obtiens:

<?php
  define('AUDIO', 0x08);
  define('VIDEO', 0x09);
  define('SCRIPT_DATA', 0x12);
  define('FRAME_TYPE_INFO', 0x05);
  define('CODEC_ID_AVC', 0x07);
  define('CODEC_ID_AAC', 0x0A);
  define('AVC_SEQUENCE_HEADER', 0x00);
  define('AAC_SEQUENCE_HEADER', 0x00);
  define('AVC_SEQUENCE_END', 0x02);
  define('FRAMEFIX_STEP', 40);
  define('INVALID_TIMESTAMP', -1);
  define('STOP_PROCESSING', 2);

  class CLI
    {
      protected static $ACCEPTED = array();
      var $params = array();

      function __construct($options = false, $handleUnknown = false)

Bref, on vois maintenant qu'il s'agit enfin d'un script php valide (70ko) alors que lors de la première tentative il s'agissait d'une page html (600ko) qui englobait le script php, donc pas du tout exécutable. En essayant d’exécuter du code html (sous forme de fichier .php) avec la commande php ça ne pouvait bien sur ne pas fonctionner.

Solution => télécharger le script en faisant un clic droit "enregistrer la cible du lien sous" sur cette url: https://raw.github.com/K-S-V/Scripts/ma … obeHDS.php
C'est la partie "raw" de l'url qui est importante ici smile

Me voila reparti à l'assaut avec cette fois-ci le bon script et le manifeste, mais j'ai encore un soucis de paquet.
Au moment de lancer la commande (que j'ai volontairement tronqué ici pour une plus grande lisibilité):

php AdobeHDS.php --manifest "http://ftvodhdsecz-f.akamaihd.net/z/streaming-adaptatif/2013/S19/J3/81446656-20130508-,398,632,934,k.mp4.csmil/manifest.f4m?hdnea= ...

J'obtiens la réponse suivante:

KSV Adobe HDS Downloader

You don't have 'curl' extension installed. please install it before continuing.

Solution =>

apt-get install php5-curl

Je lance la commande (j'ai rajouté des retours chariots pour la lisibilité):

php AdobeHDS.php 
--manifest "http://ftvodhdsecz-f.akamaihd.net/z/streaming-adaptatif/2013/S19/J3/81446656-20130508-,398,632,934,k.mp4.csmil/manifest.f4m
?hdnea=exp=1368351568~acl=%2fz%2fstreaming-adaptatif%2f2013%2fS19%2fJ3%2f81446656-20130508-*
~hmac=1578446290e5b6983eddecc8f077afeddc1cbcf8eb201b4da40b1d08ae9108f4&hdcore=2.8.0&g=GPSACDKUDOHO" 
--delete 
--auth "hdntl=exp=1368437369~acl=%2fz%2fstreaming-adaptatif%2f2013%2fS19%2fJ3%2f81446656-20130508-*~data=hdntl
~hmac=433f96b09104c8dd61edec2dcc75f894fbfb56e20fe3396157eece83c02ab057&als=0,0.1,0,0,0,NaN,0,0,0,18,f,0,2690.64,f,s,GPSACDKUDOHO,2.8.0,18
&hdcore=2.8.0" 
--useragent "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0"

Et maintenant le téléchargement se passe très bien. Il ne faut que quelques minutes pour télécharger les fichiers pour former la vidéo de 280Mo qui correspond à une émission de 45 minutes:

KSV Adobe HDS Downloader

Processing manifest info....                                                   
Quality Selection:                                                             
 Available: 833 577 304
 Selected : 833
Downloading 448/448 fragments                                                  
Found 448 fragments                                                            
Finished
-rw-r--r-- 1 fred users 283967418 mai   12 11:39 bea259013a49a3b4e2ea26e22f920d8d_2_f1614de61a57c735_Seg1-Frag.flv

Merci encore à tous pour votre aide précieuse.

Hors ligne

#182 Le 12/05/2013, à 12:10

11gjm

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

Bonjour ,

@Frédéric Stemmelin : Merci pour ton compte-rendu .

Je vais de ce pas copier/coller "CURL" à l'emplacement qui va bien .

Cordialement .

Hors ligne

#183 Le 12/05/2013, à 15:19

k3c

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

Excellent tout ton travail, en particulier,

pacome a écrit :

rajouté l'utilisation du module logging pour gérer messages et logs

que je comptais faire !

Je vais voir si je trouve quelque chose pour calculer le hash du Player de manière dynamique.


Archlinux sur Xiaomi Air 13

Hors ligne

#184 Le 14/05/2013, à 13:19

k3c

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

@ pacome

merci pour ton programme testant les players.
Je viens de vérifier avec Captvty, donc pour l'instant

-w d81147a6992da310aa0b2c439044f2a127ca619b7154049eb58bdaa119c2ddcd

-x 352074

Ton programme me donne

python ~/test_hash.py -u http://www.wat.tv/images/v40/PlayerWat.swf -V
INFO:	14:10:16: verbose mode
INFO:	14:10:18: url: http://www.wat.tv/images/v40/PlayerWat.swf

INFO:	14:10:18: *-*- Uncompressed -*-*
	size: 352074
	hash: 4f7b0ffc05b1360151af491f1d97babf46bc4aae36d6a5ad9ff9b797f3a19ac6
	hlen: 64

donc la taille est bonne mais pas le hash.

On progresse !

Dernière modification par k3c (Le 14/05/2013, à 13:41)


Archlinux sur Xiaomi Air 13

Hors ligne

#185 Le 14/05/2013, à 14:04

bibichouchou

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

salut à tous,

voici la solution minimaliste que je vous propose. je n'ai pas eu le temps de la publier hier soir...

import hashlib
import zlib
import StringIO
import base64
import hmac

f = open('player.swf', 'rb')
swfData0 = f.read()
f.close()

swfData = StringIO.StringIO(swfData0)
swfData.seek(0, 0)
magic = swfData.read(3)
print magic
uncompressedswfData = "FWS" + swfData.read(5) + zlib.decompress(swfData.read())

swfHash = hmac.new("Genuine Adobe Flash Player 001", uncompressedswfData, hashlib.sha256).hexdigest()
swfSize = len(uncompressedswfData)

print swfHash
print swfSize

le fichier player.swf est le lecteur flash trouvé à cette adresse lecteur

A+

Hors ligne

#186 Le 14/05/2013, à 14:29

k3c

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

Bon c'est ok

python ~/test_hash.py -u http://www.wat.tv/images/v40/PlayerWat.swf -V
INFO:	15:27:32: verbose mode
INFO:	15:27:32: url: http://www.wat.tv/images/v40/PlayerWat.swf

INFO:	15:27:32: *-*- Uncompressed -*-*
	size: 352074
	hash: d81147a6992da310aa0b2c439044f2a127ca619b7154049eb58bdaa119c2ddcd
	hlen: 64

Le code modifié, il fallait "saler" avec la clé que je passe dans KEY
KEY = "Genuine Adobe Flash Player 001"

(merci à Pacome pour son code qui aide bien)

Edit: pour bibichouchou
1) bravo
2) on dirait que tu t'es mis à Python :-)

#!/usr/bin/python
#-*- coding:utf-8 -*-

# generic
import argparse
from time import localtime, strftime
import logging

# specific
import base64
import urllib2                  # → pas que urlopen (exceptions, etc.)
import hashlib                  # → sha256sum
import hmac
import zlib
import StringIO

# script globvars
scriptName='getSwfInfo'
scriptVersion='1.0'
versionString='%s v%s' % (scriptName, scriptVersion)
KEY = "Genuine Adobe Flash Player 001"

# default/valid values
validHash='0818931e9bfa764b9c33e42de6d06f924ac7fc244d0d4941019b9cdfe8706705'
validSize=352043

# global logger
log=logging.getLogger(__name__)

def computeSwfPlayerHash(swfPlayerUrl):
    """
    Essais → swf size & hash
    """
    global KEY
    try:
        swfPlayer= urllib2.urlopen(swfPlayerUrl).read()
    except ValueError:
        log.error('Url invalide: %s' %(swfPlayerUrl))
        return
    except urllib2.URLError:
        log.error("Pb avec l'url")
        return
    except urllib2.HTTPError:
        log.error("Pb http")
        return

    swfPlayerSize=len(swfPlayer)
    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...")
    else:
        unzPlayer="FWS" + swfData.read(5) + zlib.decompress(swfData.read())
        unzPlayerSize=len(unzPlayer)
        sha256Player = hmac.new(KEY, unzPlayer, hashlib.sha256) #.hexdigest()
        # sha256Player=hashlib.sha256(unzPlayer)
        unzPlayerHash=sha256Player.hexdigest()
        # b64PlayerHash=base64.b64encode(unzPlayerHash.decode('hex'))
        b64PlayerHash=base64.urlsafe_b64encode(sha256Player.hexdigest().decode('hex'))

    log.info('url: %s\n' %(swfPlayerUrl))
    log.debug('*-*- Compressed -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
            swfPlayerSize, swfPlayerHash, len(swfPlayerHash)))
    log.info('*-*- Uncompressed -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
            unzPlayerSize, unzPlayerHash, len(unzPlayerHash)))
    log.debug('*-*- b64Encoded -*-*\n\thash: %s\n\thlen: %i\n' % (
            b64PlayerHash, len(b64PlayerHash)))


def main():
    """
    compute/display/log size & hash of swf player
    """
    parser=argparse.ArgumentParser(prog=scriptName,
                                     description='compute swf player hash.',
                                     version=versionString)
    parser.add_argument('-d', '--default',
                        help='show default value',
                        dest='displayValidHash',
                        action='store_true',
                        default=False)
    parser.add_argument('-u', '--url',
                        help='url of swf player',
                        dest='swfPlayerUrl',
                        action='store',
                        metavar='URL')
    verbOrLog=parser.add_mutually_exclusive_group()
    verbOrLog.add_argument('-V', '--verbose',
                           help="display information messages",
                           dest='verbose',
                           action='store_true',
                           default=False)
    verbOrLog.add_argument('-l', '--log',
                           help="log information messages",
                           dest='log',
                           action='store_const',
                           const='%s-%s.log' % (scriptName,
                                                strftime("%Y%m%d%H%M%S",
                                                         localtime())),
                           metavar='FILE')
    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')
    if args.log:
        logging.basicConfig(filename=args.log,
                            format='%(levelname)s:\t%(asctime)s: %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.DEBUG)
        logging.info(args.log)

    if args.swfPlayerUrl:
        log.debug('swfPlayerUrl: %s' % (args.swfPlayerUrl))
        computeSwfPlayerHash(args.swfPlayerUrl)

    if args.displayValidHash:
        log.info('*-*- Valid hash -*-*\n\tsize: %i\n\thash: %s\n\thlen: %i\n' % (
                validSize, validHash, len(validHash)))
        
if __name__ == "__main__":
    main()

Dernière modification par k3c (Le 14/05/2013, à 18:56)


Archlinux sur Xiaomi Air 13

Hors ligne

#187 Le 14/05/2013, à 14:52

bibichouchou

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

à k3c

je t'ai un peu devancé pour la solution smile

Hors ligne

#188 Le 14/05/2013, à 20:16

pacome

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

Woah!

Alors là bravo les gars! Je ne cherchais pas du tout du bon coté...

Je vais intégrer la fonction computeSwfPlayerHash(swfPlayerUrl) au script principal et voir si je peux récupérer l'url du player automatiquement wink

Petite note: comme on précise l'interpréteur dans le shebang il suffit de rendre le script exécutable (avec chmod 755 ou chmod +x) pour le lancer "directement":

~/test_hash.py -u http://www.wat.tv/images/v40/PlayerWat.swf -V

(sous linux en tout cas...)

Edit:
Voilà déjà une version 0.9.4.3 avec une url statique:

#!/usr/bin/python
#-*- coding:utf-8 -*-
# TF1 TMC NT1 HD1 V0.9.4.3 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='tmc_tf1.py'
scriptVersion='0.9.4.3'

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

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

# hash et size du player swf (valide au 05/2013)
swfHashValid='0818931e9bfa764b9c33e42de6d06f924ac7fc244d0d4941019b9cdfe8706705'
swfSizeValid=352043


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...")
        return False
    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, unzPlayerSize, unzPlayerHash))
    return (unzPlayerHash, unzPlayerSize)

def downloadWatVideo(videoUrl):
    """ recuperation de vidéos sur TF1/TMC/NT1/HD1 (donc WAT)"""
    # timeout en secondes
    log.debug('→downloadWatVideo(%s)' %(videoUrl))
    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:
                try:
                    (swfHash, swfSize)=swfPlayerHashAndSize(swfPlayerUrl)
                except:
                    log.warning('Impossible de calculer dynamiquement le (hash, size) du player swf! Utilisation des valeurs par défaut.')
                    swfHash=swfHashValid
                    swfSize=swfSizeValid

                if '.hd' in data:
                    data0 = re.search('rtmpte://(.*)hd', data).group(0)
                if '.h264' in data:
                    data0 = re.search('rtmpte://(.*)h264', data).group(0)
                log.debug('data0=%s'%(data0))
                data0 = data0.replace('rtmpte','rtmpe')
                fName=str(no) + '-' + str(PartId) # nom du fichier sans extension
                fileName=fName+'.mp4'             # nom du fichier avec extension
                rtmpCmd = '%s -e -r "%s" -c 443 -m 10 -w %s -x %i -o "%s"' % (
                    rtmpdumpEx, data0, swfHash, swfSize, fileName)
                log.info(rtmpCmd)
                arguments = shlex.split( rtmpCmd )
                cpt = 0 
                while True:
                    p = subprocess.Popen(arguments,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)
                    stdout, stderr = p.communicate()
                    if p.returncode != 0:
                        log.error('Le sous-process s\'est terminé avec le code d\'erreur ' + str(p.returncode) + ')')
                        if cpt > 5:
                            break
                        cpt += 1
                        log.error('Essai de reprise...')
                        time.sleep(3) 
                    else:
                        # 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.debug('conversion ffmpeg fileName → tmpFileName (pour corriger le conteneur)')
                            tmpFileName=fName+'.tmp.mp4'
                            ffmpegCmd='%s -i "%s" -acodec copy -vcodec copy "%s"' % (
                                ffmpegEx, fileName, tmpFileName)
                            arguments=shlex.split(ffmpegCmd)
                            p=subprocess.Popen(arguments,
                                               stdout=subprocess.PIPE,
                                               stderr=subprocess.PIPE)
                            stdout, stderr = p.communicate()
                            if p.returncode != 0:
                                log.error('La conversion ffmpeg s\'est terminée avec le code d\'erreur %i.\nLe fichier %s est néanmois disponible' % (
                                        p.returncode, fileName))
                            else:
                                log.debug('remplacement tmpFileName → fileName')
                                os.rename(tmpFileName, fileName)
                        break
    log.debug('Fini!')

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('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:
        log.info('url: %s' % (args.url))
        downloadWatVideo(args.url)

if __name__ == "__main__":
    main()

Je verrai plus tard pour trouver l'url du player dynamiquement tongue

À+

Dernière modification par pacome (Le 14/05/2013, à 22:58)

Hors ligne

#189 Le 15/05/2013, à 06:47

k3c

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

pacome a écrit :

Je verrai plus tard pour trouver l'url du player dynamiquement tongue

À+

Ave

Pour trouver l'url du player, je lance dans un terminal (remplacer wlan0 par eth0 ou le nom de votre carte réseau)

sudo ngrep -d wlan0 -lqi -p -W none ^get\|^post > player_tf1

je lance une video, j'arrête le sudo ngrep, et je recherche dans le fichier la chaîne
.swf

mais ce n'est pas tellement automatisable, ni forcément fiable.

Si quelqu'un a une idée, je suis preneur.

PS: merci pour ta version, je vais tester.


Archlinux sur Xiaomi Air 13

Hors ligne

#190 Le 16/05/2013, à 23:35

11gjm

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

Bonjour ,

Je viens de tester le size et le hash ( le 17 mai ) :

"python.exe" test_hash.py -u http://www.wat.tv/images/v40/PlayerWat.swf -V
INFO:   00:14:42: verbose mode
INFO:   00:14:43: url: http://www.wat.tv/images/v40/PlayerWat.swf

INFO:   00:14:43: *-*- Uncompressed -*-*
        size: 352164
        hash: 66cb3adf8c63275782ce5070a9d314805252932922a9bce7f3cc42a74d3c29ee
        hlen: 64

Effectivement les valeurs ont changées , par rapport à celles fournies dans la version 0.9.4.3 .

Est-ce que cela sous-entend que les téléchargements ne pourront s'effectuer ?
Sauf à lancer le test du player , puis faire la modif du TF... .py ,
et ensuite lancer le téléchargement de la vidéo souhaitée ( ??? ) .
----
NB: le calcul que vous proposez est valable pour d'autres players .
----
Cordialement .

ADDITIF :
Sous Windows , j'ai un fichier .swinfo , qui est créé ( je ne sais pas ENCORE , par qui ? ) ,
dans celui-ci figure adresse du swf , size et hash .

Réponse à mon interrogation :
---
The information is cached in a .swfinfo file in the user's home directory, so that it
doesn't need to be retrieved and recalculated every time rtmpdump is run.
---

Dernière modification par 11gjm (Le 17/05/2013, à 00:58)

Hors ligne

#191 Le 17/05/2013, à 19:29

pacome

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

Bonjour,

11gjm a écrit :

Effectivement les valeurs ont changées , par rapport à celles fournies dans la version 0.9.4.3 .

Est-ce que cela sous-entend que les téléchargements ne pourront s'effectuer ?
Sauf à lancer le test du player , puis faire la modif du TF... .py ,
et ensuite lancer le téléchargement de la vidéo souhaitée ( ??? ) .

J'ai intégré la formule (magique? smile) de bibichouchou et k3c dans la fonction swfPlayerHashAndSize(swfPlayerUrl) de la version 0.9.4.3 (ligne 115), et je lui passe l'url définie ligne 32.
J'ai conservé des valeurs "par défaut" (lignes 36,37) au cas où le calcul ne fonctionne pas: elles sont déjà obsolètes, et en plus le calcul fonctionne; il faudra donc enlever tout ça (y compris leur utilisation (lignes 202→207) dans une prochaine version.
Mais pour répondre à ta question: tu devrais pouvoir utiliser la version 0.9.4.3 sans modification cool.

J'ai vu aussi le fichier .swfinfo et j'ai envisagé de l'utiliser comme rtmpdump pour ne pas recalculer le hash à chaque fois...

Pour le moment je m'intéresse surtout au code de pluzzdl (qui est une vrai mine! big_smile).

À+

Hors ligne

#192 Le 17/05/2013, à 20:01

bibichouchou

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

coucou,
le crédit revient surtout à k3c qui avait publié toutes les infos nécessaires ! big_smile

Dernière modification par bibichouchou (Le 17/05/2013, à 20:15)

Hors ligne

#193 Le 17/05/2013, à 20:09

bibichouchou

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

je viens de m'apercevoir que l'option "-W | --swfVfy" de rtmpdump fonctionne mais est un peu capricieuse.
NB je supprime le fichier .swfinfo avant chaque test

si j'utilise la syntaxe

-W 'www.wat.tv/images/v40/PlayerWat.swf'

le fichier .swfinfo n'est pas crée et rtmpdump me dit d'ailleurs qu'il n'a pas pu trouver le lecteur et me suggère d'utiliser l'option --swfVfy

RTMPDump v2.4
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
ERROR: RTMP_HashSWF: couldn't contact swfurl www.wat.tv/images/v40/PlayerWat.swf (HTTP error -1)
Connecting ...
WARNING: HandShake: Type mismatch: client sent 6, server answered 9
INFO: Connected...
ERROR: HandleCtrl: Ignoring SWFVerification request, use --swfVfy!

si j'utilise (ajout de http)

-W 'http://www.wat.tv/images/v40/PlayerWat.swf'

cette fois-ci le fichier .swfinfo est créé et on note un petit temps de latence avant le début du téléchargement (temps nécessaire pour rapatrier le lecteur + calculs des quantités tant désirées)

pacome, je crois que tu utilisais l'adresse sans le http dans une version précédente (bon en plus tu utilisais PlayerLite qui n'est pas le bon lecteur, on va pas chipoter).
donc je retire ce que j'ai dit, l'option de rtmpdump n'est pas un gadget big_smile

Dernière modification par bibichouchou (Le 17/05/2013, à 20:15)

Hors ligne

#194 Le 17/05/2013, à 21:42

bibichouchou

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

à pacome
j'imagine que ton souhait de garder un historique des hash+taille est d'éviter le rapatriement du lecteur à chaque fois. mais le problème d'utiliser des quantités (hash + taille) déjà calculées est de savoir si elles sont toujours valides. donc il faudrait lancer la ligne rtmpdump avec les données précédemment calculées (si elles existent), contrôler l'exécution du téléchargement et s'il y a un arrêt brutal, décider de mettre à jour le hash + la taille. or un arrêt du téléchargement pourrait aussi être dû à une défaillance de la connexion... je trouve que ça va compliquer le code pour un gain limité : télécharger un truc qui fait 200Ko, c'est pas la mort. bon je réfléchis tout haut là...

Hors ligne

#195 Le 17/05/2013, à 23:13

pacome

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

@bibichouchou
Excellente nouvelle! merci d'avoir persévéré et d'avoir trouvé comment utiliser l'option -W | --swfVfy de rtmpdump.

Je pensais effectivement reprendre le principe de fonctionnement de cette option avec l'utilisation du fichier .swfinfo: c'est implémenté dans le code de pluzzdl (dans Configuration.py, avec un autre fichier et un autre format smile).

Si ça fonctionne correctement dans rtmpdump on peut bien le laisser faire wink. D'autant que la page man dit:

      --swfVfy       -W url
              ...             By default, the cached info
              will be used for 30 days before re-checking.

       --swfAge       -X days
              Specify how many days to use the cached SWF info before re-check‐
              ing.  Use  0  to always check the SWF URL. Note that if the check
              shows that the SWF file has the same  modification  timestamp  as
              before, it will not be retrieved again.

On peut donc aussi utiliser l'option --swfAge | -X 0 si on veut forcer le recalcul du hash big_smile.

À+

Hors ligne

#196 Le 21/05/2013, à 08:54

tramberlimpe

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

Bonjour,

j'ai une question idiote, et je ne trouve pas la réponse en parcourant les forums.

Où est la vidéo téléchargée ? Dans quel dossier ?

Merci

Hors ligne

#197 Le 21/05/2013, à 09:13

bibichouchou

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

bonjour,
à tramberlimpe

normalement à l'endroit où tu lances le script. pourrais-tu préciser de quel script tu parles (car plusieurs ont été publiés ici) ?

Dernière modification par bibichouchou (Le 21/05/2013, à 09:13)

Hors ligne

#198 Le 21/05/2013, à 12:06

tramberlimpe

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

Salut,

Mon OS : debian Wheezy
Pluzzdl installé avec apt-get.

J'ai fait :
cd /home/bertrand/Documents

et j'ai lancé la commande : pluzzdl -bt http://pluzz.francetv.fr/videos/jt_1920 … 75457.htlm
il m'a indiqué que le téléchargement était complété.

devrais-je avoir la vidéo dans /Documents ?

Dernière modification par tramberlimpe (Le 21/05/2013, à 12:09)

Hors ligne

#199 Le 21/05/2013, à 17:50

11gjm

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

Bonjour ,

@tramberlimpe : regardes dans le répertoire \pluzzdl\Videos ( pour moi , sous windows ) .

N'existe-t-il pas une fonction "Rechercher" ?
Si , oui : tu cherches un fichier .mp4 , créé le jour de ton téléchargement ( ou à partir de la veille ) .

Cordialement .

Hors ligne

#200 Le 21/05/2013, à 20:23

pacome

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

Bonjour,

@tramberlimpe:
pluzzdl télécharge la vidéo dans le répertoire courant (celui dans lequel tu lances la commande: /home/bertrand/Documents dans ton cas) dans un fichier .ts (jt_1920_rhone_alpes_,82475457.ts) puis convertit celui-ci en .mkv (jt_1920_rhone_alpes_,82475457.mkv) pour associer vidéo et sous-titres (quand il y en a, ce qui ne semble pas être le cas ici).

Tu devrais donc trouver un jt_1920_rhone_alpes_,82475457.mkv de 124Mo dans ton répertoire /home/bertrand/Documents.

À+

Hors ligne