Bref c'était un dimanche et je moulais sur mon PC.
Je moulais tranquillement sur mes sites habituels – xhamster.com linuxfr.org, slashdot.org, quand tout à coup est apparu un journal sur LinuxFR : Bref, j'ai fait un flux atom de bref.
Alors j'me suis dit : "Bref, j'ai bien cette série, il faut que je fais un script pour récupérer directement les épisodes et que je les mets sur ma freebox". Je sais, je suis mauvais en conjugaison, mais il fallait quand même que je les mets sur ma freebox. Bref.
J'ai donc récupéré le flux Atom et j'ai tenté de parser le flux pour récupérer les url des épisodes en HD. La HD, c'est mieux, parce que t'as plus de pixel à l'écran, et vu que j'ai un projecteur dans mon salon, bah les flux HD c'est mieux. Bref.
Le problème, c'est que mon colloc avait pas croqué la pomme depuis 6 mois et que là il voulait que je vais lui acheter des capotes à la pharmacie. Et puis en fait, parser le flux Atom, c'était plus sioux que de parser directement le flux XML original, qui est utilisé dans le script de Luke SKy. Bref, j'ai décidé de parser directement le flux XML original.
Bon. A ce moment-là, j'avais juste le flux des vidéos en HD, mais j'en faisais rien. Il était déjà tard. Et c'est là que je me suis demandé comment télécharger les flux RTMP parce que moi je voulais télécharger les épisodes, pas les regarder en direct. Alors j'ai cherché un peu et j'ai découvert l'outil rtmpdump. J'ai regardé l'aide et j'ai trouvé que ça serait facile de télécharger un épisode à partir de son url rtmp:// :
/usr/bin/rtmpdump -r '<url_rtmp_de_l_episode>' -o '<chemin_du_fichier_de_sortie>'
Là, j'avais les fichiers sur mon serveur local, une Debian qui va bien et qui tourne sur du matériel plutôt économe en énergie : une petite Eee Box. Une tâche cron pour lancer la vérification toutes les 6h, pour pas louper un épisode :
# Verifier et telecharger les episodes de "bref" chaque jour a 3h, 9h, 15h et 21h
0 3,9,15,21 * * * python /opt/perso/bref/dl.bref.py 2>&1 1>>/var/log/dl.bref.log
Il restait plus qu'à les pousser sur la freebox, pour pouvoir les mater ensuite en grand écran. J'ai donc décidé d'utiliser le client ftp en ligne de commande ncftpput :
ncftpput -u freebox -p <mon_mot_de_passe> <ip_de_la_freebox> '/Disque dur/Enregistrements/Bref/' <chemin_du_fichier_cree_avec_rtmpdump>
Bon, c'était nickel, ça marchait bien, mais je savais pas quand un nouvel épisode était disponible. Je récupérais les épisodes automatiquement, mais sans le savoir. Je perdais l'intérêt de l'automatisation. Bref.
J'ai décidé de m'envoyer des alertes parce que comme ça je saurais quand un nouvel épisode était disponible. J'ai décidé d'utiliser XMPP, parce que XMPP, c'est bien. Et puis j'ai fait ça en python parce que python c'est bien. Et j'ai fait deux trois bricoles pour que ça marche mieux, pour que ça ne recharge pas systématiquement les vidéos déjà téléchargées, j'ai fait quelques requêtes Xpath, j'ai rendu les fichiers accessibles par http et ftp, j'ai créé un utilisateur Bender sur mon serveur XMPP et j'ai fait beaucoup d'essais.
Bref, j'ai fait un script python.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# * parser le xml pour récupérer les url HD
# * extraire le nom du fichier (après le dernier "/")
# * vérifier que le fichier n'existe pas
# * le sauvegarder
lsXmlFeedUrl = "http://www.canalplus.fr/rest/bootstrap.php?/bigplayer/search/bref"
lsSaveFolder = "/opt/perso/bref/episodes"
lsXmppSmsList = "{{mon_jid}}" # exemple : bender@monserveurxmpp.net
lsXmppSmsMessageTemplate = "Un nouvel épisode de 'Bref' est disponible : http://{{ip_du_serveur_download}}/perso/bref/%s"
import libxml2
import os.path
import subprocess
import xmpp
class Episode(object):
def __init__(self, psUrl, psFilename, pbLocallyAvailable = False):
self._sUrl = psUrl
self._sFilename = psFilename
self._bLocallyAvailable = pbLocallyAvailable
def getName(self):
return self._sFilename
def getFilename(self):
return self._sFilename
def getFilePath(self, psPathRoot = ""):
lsFilePath = self._sFilename
if psPathRoot!="":
lsFilePath = "%s/%s" % (psPathRoot, lsFilePath)
return lsFilePath
def getUrl(self):
return self._sUrl
class XmppShortMessageService(object):
def __init__(self, psXmppServerName, psXmppServerPort, psXmppSenderUserName, psXmppSenderUserPass, psXmppSenderUserRsc):
self._sXmppServerName = psXmppServerName
self._sXmppServerPort = psXmppServerPort
self._sXmppSenderUserName = psXmppSenderUserName
self._sXmppSenderUserPass = psXmppSenderUserPass
self._sXmppSenderUserRsc = psXmppSenderUserRsc
self._oXmppClient = None
def connect(self):
if self._oXmppClient==None:
self._oXmppClient = xmpp.Client(self._sXmppServerName)
self._oXmppClient.connect(server=(self._sXmppServerName, self._sXmppServerPort))
self._oXmppClient.auth(self._sXmppSenderUserName, self._sXmppSenderUserPass, self._sXmppSenderUserRsc)
self._oXmppClient.sendInitPresence()
def send(self, psMsgText, psMsgTo):
self.connect()
lsXmppMessage = xmpp.Message(psMsgTo, psMsgText)
lsXmppMessage.setAttr('type', 'chat')
self._oXmppClient.send(lsXmppMessage)
if __name__ == '__main__':
# 1. download XML
# 2. search episode urls
# 3. check if the episodes found are already downloaded
# 4. download required files
# STEP 1
loXmlStreamDom = libxml2.parseFile(lsXmlFeedUrl)
loVideoElements = loXmlStreamDom.xpathEval('//VIDEO[./RUBRIQUAGE/RUBRIQUE="BREF"]')
loEpisodeList = list()
for loVideoElement in loVideoElements:
loHdVideoFileUrl = loVideoElement.xpathEval('./MEDIA/VIDEOS/HD')[0] # there is only one HD
lsHdVideoFileUrl = loHdVideoFileUrl.content.strip()
lsHdVideoFileName = lsHdVideoFileUrl.rsplit("/", 1)[1]
loNewEpisode = Episode(lsHdVideoFileUrl, lsHdVideoFileName, False)
loEpisodeList.append(loNewEpisode)
print "Found Episode: %s" % (loNewEpisode.getName())
for loEpisode in loEpisodeList:
lsLocalFilePath = "%s/%s" % (lsSaveFolder, loEpisode.getFilename())
if os.path.isfile(lsLocalFilePath)==True:
print "Skipping %s [already downloaded]" % loEpisode.getName()
else:
lsCmd = "/usr/bin/rtmpdump -r \"%s\" -o \"%s\"" % (loEpisode.getUrl(), loEpisode.getFilePath(lsSaveFolder))
print "Download %s" % (loEpisode.getName())
os.system(lsCmd)
lsCmd = "ncftpput -u freebox -p {{freebox_ftp_password}} {{freebox_ip}} '/Disque dur/Enregistrements/Bref/' %s" % (loEpisode.getFilePath(lsSaveFolder))
print "Upload to freebox: %s" % (loEpisode.getName())
os.system(lsCmd)
# Send an XMPP notification including a link to see the episode
loXmppSms = XmppShortMessageService('{{mon_server_xmpp}}', '5223', 'bender', 'mynameisbender', 'BrefDownloadBot')
loXmppSms.send(lsXmppSmsMessageTemplate % (loEpisode.getFilename(), loEpisode.getFilename()), lsXmppSmsList)
# c'est long
Posté par NeoX . Évalué à 10.
pour quelque chose de BREF, c'est un peu LONG :p
[^] # Re: c'est long
Posté par Fabimaru (site web personnel) . Évalué à 3.
tl;dr
# Encodage
Posté par ®om (site web personnel) . Évalué à 4.
Sympa ;-)
Après, ça serait bien de les réencoder automatiquement vers un format lisible par le navigateur. À l'époque j'avais fait un script pour ça (en parallélisant au maximum la récupération des épisodes et leur encodage), pour créer des OGV (Ogg Theora) :
http://blog.rom1v.com/2010/04/aggreger-differentes-sources-de-vod-en-oggtheora/
Il faudrait un tout petit peu l'adapter pour encoder en WEBM.
blog.rom1v.com
[^] # Re: Encodage
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 2.
Oui ça serait bien. Un autre truc qui serait bien, et pour lequel je n'ai pas trouvé les outils adéquats (mais je pense que je n'ai pas suffisamment cherché), c'est ajouter des méta-données à partir de l'information trouvée dans le flux XML.
Par défaut les vidéos n'ont pas de titre, pas d'auteur, rien.
# XPath
Posté par Axioplase ıɥs∀ (site web personnel) . Évalué à 3.
T'as pas dit que XPath c'était bien.
Doit-on en déduire que XPath, c'est mal, mais que t'as pas osé écrire un journal qui dénonce ?
[^] # Re: XPath
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 4.
XPath, c'est bien. =)
# Thanks...
Posté par GCN (site web personnel) . Évalué à 1.
Merci pour ce petit script...
Je vais l'adapter pour garder les épisodes en local (pas d'upload vers la FBX) et, tant qu'à faire, nommer les fichiers en fonction du titre de l'épisode (plutôt que BREF_EPISODES_110920_CAN_205901_video_HD.mp4 qui est plutôt moche).
Ensuite on verra pour convertir ces fichiers dans un autre format :).
[^] # Re: Thanks...
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 1.
J'y ai pensé, mais je me suis dit que potentiellement il y aurait des apostrophes, des virgules, etc dans les titres, et donc j'avais simplement cherché à mettre des métadonnées. Ceci dit, je suis preneur de ta modification...
Peut-être devrais-je mettre mon script sur bitbucket ?
[^] # Re: Thanks...
Posté par GCN (site web personnel) . Évalué à 1.
Ben c'est un peu (beaucoup) gruik et le code n'est pas aussi clean que le tiens mais bon... Ça marche :).
Après exécution ça me donne ça:
[^] # Re: Thanks...
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 1.
J'ai regardé ton script, et je me pose la question des noms de fichier. Je n'aime pas le fait de mettre des caractères "non-conventionnels" dans les noms de fichier : guillemets, apostrophes, etc, etc.
Je me posais la question : existe-t-il une lib' ou une technique ou n'importe quoi pour convertir des chaînes quelconque en leur version "filename friendly" ? Par exemple qui convertirait Mon coloc a fait l'amour en Mon coloc a fait l-amour ; et qui marcherait pour tous les caractères un peu "sioux" ?
Quelqu'un connait ça ?
[^] # Re: Thanks...
Posté par GCN (site web personnel) . Évalué à 2.
Ben, à part pour "/", je ne crois pas qu'il existe des caractères "non conventionnels" pour nommer un fichier sous Linux :).
Personnellement, cela ne me dérange pas ainsi mais j'imagine qu'il doit être facile d'écrire une petite fonction qui ferait le boulot à ta place !
[^] # Re: Thanks...
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 1.
Hm... en fait je suis excessivement partisan de l'interopérabilité.
Tout à fait ; je me disais que j'étais probablement pas le premier à me poser la question (et donc à chercher une réponse). En fait mon idée, c'est de convertir en un nom de fichier ascii avec les caractères qui vont bien uniquement (en gros, chiffres, lettres, - _ et hm... voilà quoi).
Le hic, c'est les caractères avec accents, etc, etc. C'est pas tant qu'ils soient non supportés, d'ailleurs, mais qu'ils sont transformés en des signes cabalistiques, parfois, quand tu changes d'encodage d'un système de fichier à un autre.
[^] # Re: Thanks...
Posté par BB . Évalué à 1.
echo -n $FILENAME|tr -cd '[:print:]'
En python :
> a = 'Téléchargements'
> u = a.decode('utf-8')
> u.encode('ascii', 'ignore')
: 'Tlchargements'
Après pour éliminer les accents, je crois qu’il n’y a pas le choix faut construire un table de correspondance.
[^] # Re: Thanks...
Posté par lolop (site web personnel) . Évalué à 2.
Il y a des recettes pour les accents, basées sur les tables Unicode des caractéristiques des caractères. google blabla... Mais c'est vrai qu'une simple table de remplacement fait l'affaire - ça a été traité sur le wiki pythonfr.
http://wikipython.flibuste.net/PageD%27Accueil
http://wikipython.flibuste.net/JouerAvecUnicode#Supprimerlesaccents
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
# weboob
Posté par xumelc . Évalué à 6.
Dommage, pour seulement 10 fois plus de code et un effort 20 fois plus important, tu aurais pu faire une nouvelle application weboob de notifications de disponibilité de nouveaux épisodes de séries quelconque de canalplus, en utilisant et éventuellement améliorant le backend canalplus existant. Cette application fonctionnerait au passage pour des canaux youtube ou sur d'autres plateformes de vidéo (moyennant quelques éventuelles modifications des backends concernés).
Tu n'aurais alors eu plus qu'à coder une nouvelle application pour envoyer chaque épisode d'une liste de séries choisies parmi celles disponible directement sur un serveur ftp/sftp/loltp quand il est disponible. Avec une sélection de 'séries'/'canaux'/... commune avec l'application de notifications.
# tu peux faire plus générique
Posté par fearan . Évalué à 3.
généralement la freebox a son ip disponnible sous mafreebox.freebox.fr évidemment si tu utilises des serveurs dns externe ça peut poser problème ;)
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: tu peux faire plus générique
Posté par Thomas Bigot . Évalué à 3.
Non, car quel que soit ton DNS,
mafreebox.freebox.fr
pointe sur212.27.38.253
. C’est cette IP qui est routée en interne par la freebox sur elle-même.[^] # Re: tu peux faire plus générique
Posté par lolop (site web personnel) . Évalué à 2.
Sûr ?
Car chez moi ça ne donne pas cette adresse IP (j'ai le même préfixe 212.27 mais le reste est différent).
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
# Moi j'aime pas Bref
Posté par Moogle . Évalué à 2.
J'aime pas Bref, par contre j'aime les Guignols, Groland ou encore Action Discrète. Et j'imagine que ce script peut être adapté à d'autres programmes. Donc c'est plutôt intéressant ! Par contre, le site de Canal+ change souvent de façon d'accéder à ses vidéos pour justement empêcher ce genre de petit hack, des logiciels un peu plus anciens en avaient déjà fait les frais...
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.