Oh! Oh! Cette technique ne fonctionne plus depuis que Noovo a changé sa façon d'utiliser l'API de BrightCove. SVP, veuillez utiliser la nouvelle méthode en suivant ce lien: Télécharger facilement les vidéos de Noovo.ca en deux clics
Ils existent plusieurs raisons pour vouloir télécharger les fichiers vidéos plutôt que d’utiliser l’interface Web fournit par les diffuseurs de contenus. Dans mon cas bien précis, la raison est simple: la qualité de ma connexion internet à la maison est souvent fluctuante en raison de la météo. Eh oui, je suis souvent en campagne profonde et alors limitée à une connexion satellitaire.
Je vais expliquer ma démarche (méthode essai-erreur) utilisée pour découvrir comment télécharger les fichiers vidéo de la plateforme Web de V Télé et Musique Plus afin de pouvoir les trimbaler à sa guise. Cette démarche se fera à l’aide de Chrome uniquement, aucun autre outil nécessaire. Pourquoi Chrome? Car c’est le fureteur le plus populaire en ce moment. Personnellement, j’aime mieux FireFox pour ce genre de recherche, mais bon, on s'en sacre un peu.
Notez bien que le but caché est aussi d'automatiser ce processus plus tard. Par conséquent, on va fouiller un peu plus que nécessaire afin de comprendre comment les programmeurs ont standardisé leur application.
OK, débutons!
Choisissons une émission que j’aime bien : http://noovo.ca/emissions/ca-va-brasser/episodes.
Choisissons maintenant un épisode de courte durée pour faciliter nos tests et cliquons à l’aide du bouton droit de la souris (menu contextuel) sur Ouvrir le lien dans une fenêtre en navigation privée
. Nous avons donc un onglet privé avec ce lien chargé: http://noovo.ca/videos/ca-va-brasser/mousse-chocolat-et-the-kruhnen-dtpa_82975.
Assurons-nous de n’avoir aucune extension qui fonctionne (comme AdBlock par exemple).
Ensuite, désactivons Flash afin de limiter les protocoles utilisés pour livrer le contenu en HTTP seulement.
Désactiver
.Flash permet d’utiliser plusieurs autres protocoles comme RTMP qui est un peu plus complexe à télécharger.
F12
.Nous cherchons des vidéos donc il serait judicieux de regarder si ça télécharge un format bien connu en HTTP directement. Entrons .mp4
dans le champ Filter
pour isoler une requête HTTP avec un fichier MP4. Ah bon, rien du tout. Essayons avec .flv
, .mpeg
, .mpg
. Encore rien.
Nous comprenons maintenant que le site ne charge pas de fichiers vidéos entiers directement, mais utilise probablement un protocole comme HLS ou Dash.
Commençons par HLS et cherchons pour une playlist en filtrant cette fois-ci avec m3u8
. Oh! On voit des requêtes cette fois alors ça utilise HLS par défaut. Enfin on peut avancer!
Regardons maintenant le contenu et URL complet en cliquant avec le bouton droit et Open link in new tab
sur le premier fichier et analysons:
L’URL http://c.brightcove.com/services/mobile/streaming/index/master.m3u8?videoId=4293298759001&pubId=618566855001
nous montre que noovo.ca utilise le service de streaming vidéo de Brightcove, un service très répandu chez les diffuseurs télévisuels qui ne veulent pas gérer ça eux-mêmes.
Cette URL contient aussi un videoId 4293298759001
. Aucune idée pour le moment d’où ça vient.
Le contenu du fichier nous dévoile le même videoId 4293298759001
, quelques assetId et surtout que le vidéo nous est offert en 4 résolutions et bitrate différents:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=264000,RESOLUTION=416x232
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293365253001&pubId=618566855001&videoId=4293298759001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=40000
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293364503001&pubId=618566855001&videoId=4293298759001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=464000,RESOLUTION=416x232
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293365786001&pubId=618566855001&videoId=4293298759001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=664000,RESOLUTION=640x360
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293388608001&pubId=618566855001&videoId=4293298759001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1064000,RESOLUTION=960x540
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293379212001&pubId=618566855001&videoId=4293298759001
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1664000,RESOLUTION=1280x720
http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=4293375897001&pubId=618566855001&videoId=4293298759001
Regardons comment le site fait pour obtenir le videoId de Brightcove, car c’est avec cet ID que nous pourrons surement obtenir de l’information sur les fichiers complets disponibles.
On peut toujours télécharger des fragments HLS et les recombiner avec FFmpeg, mais c’est toujours plus simple de trouver les fichiers mp4 complets directement. La paresse, c'est excellent pour l'automatisation.
Regardons donc le contenu de la page (source HTML) en utilisant CTRL-U
, et cherchons pour 4293298759001
. Rien.
Si la page n’a aucun videoId dans sa source, c’est probablement que Javascript l’obtient grâce à un API. Les programmeurs vont souvent essayer de simplifier leur vie en créant ces API fournissant de l’information à plusieurs sources, mais provenant d’un seul système standardisé.
Cherchons donc pour une requête dans la console qui contient api
, filtrons pour ce texte et regardons les requêtes de type xhr
(XMLHttpRequest). Oh, nous voyons une URL intéressante: http://api.noovo.ca/api/v1/pages/single-episode/ca-va-brasser/mousse-chocolat-et-the-kruhnen-dtpa_82975.
Premièrement, ce qui saute aux yeux est la structure finale de l’URL qui est la même que la page sur laquelle on est présentement. Excellent ça! Ça va bien s’automatiser si on en a besoin.
Deuxièmement, en regardant son contenu de format JSON, on s’aperçoit que le videoID 4293298759001
ici appelé brightcoveId s’y retrouve:
{
"status":"success",
"data":{
"createdAt":"2016-09-09T20:07:39.338Z",
"slug":"mousse-chocolat-et-the-kruhnen-dtpa_82975",
"show":{
"slug":"ca-va-brasser",
"title":"Ça va brasser!",
"productionType":"produite",
"url":"",
"webtv":false,
"id":"57c0a8c45f26ffcc4312653b"
},
"publishDate":"2015-06-15T19:51:00.000Z",
"contentType":2,
"title":"Mousse chocolat et thé | Kruhnen (DTPA)",
"brightcoveId":"4293298759001",
"description":"",
"duration":147,
"source":"vtele",
"image":{
"width":680,
"height":382,
"mediaType":"image",
"trackingPixel":"",
"credits":"",
"caption":"",
"url-home-slideshow":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg/home-slideshow",
"url-web-avatar":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg/web-avatar",
"url-page-header":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg/page-header",
"url-list-thumbnail":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg/list-thumbnail",
"url-list":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg/list",
"url":"http://api.noovo.ca/api/v1/medias/57d3168b898c0d9d322e259e.jpg",
"id":"57d3168b898c0d9d322e259e"
},
"themes":[
{
"title":"Cuisine",
"slug":"cuisine",
"subthemes":[],
"color":"#01665e",
"id":"56defbc7ee05300c05caddd4"
}
],
"viewsCount":148,
"featuredDate":null,
"featured":false,
"popularity":-1,
"popularity_monthly":-1,
"moods":[
"571e73efc2a8524e30b93481",
"56def5664b4804c660c6bd80",
"56def5664b4804c660c6bd7c"
],
"tags":[],
"publishState":"prod",
"expireSoon":false,
"deletedFromBrightcove":false,
"id":"57d3168bc9a67a8d32428d0c"
}
}
On a désormais l’information sur comment le vidéo est diffusé, par quel service, et comment trouver son identifiant unique. C'est probablement suffisant pour obtenir l'information voulue chez Brightcove.
Brightcove fournit un API à ses clients comme à peu près tout le monde offrant un service de type SaaS. En cherchant sur Google brightcove api
, on peut facilement trouver sa documentation. Un des liens intéressants est celui-ci: Accessing Video Content with the Media API.
Dans cette section de la documentation, on lit que pour obtenir l’information voulue sur le contenu vidéo, nous pouvons utiliser une URL ayant une structure comme celle-ci:
http://api.brightcove.com/services/library?command=find_video_by_id&video_id=1520880903001&video_fields=name,length,FLVURL&media_delivery=http&token=jskS1rEtQHy9exQKoc14IcMq8v5x2gCP6yaB7d0hraRtO__6HUuxMg..
Super, on a déjà le videoId. Le token lui, pas encore. Essayons donc de le trouver grâce à Google, on peut toujours être chanceux :
Cherchons pour noovo api.brightcove.com find_video_by_id media_delivery token
. Rien.
Ah, peut-être on peut essayer avec le vieux nom vtélé
. Cherchons alors pour vtele api.brightcove.com find_video_by_id media_delivery token
. Encore rien.
Allons voir sur GitHub. Peut-être quelqu’un a déjà créé un addon pour une plateforme comme Kodi d'où on pourra extirper de l’information : https://github.com/search?utf8=%E2%9C%93&q=noovo+brightcove. Humm, non.
Kodi, anciennement appelé XBMC, est bien connu pour avoir une panoplie de addons non officiels permettant de visualiser des vidéos de plusieurs plateformes de diffusion sans quitter son interface. Tout est open source et utilise python donc c'est facile d'y trouver de l'information.
Ah, essayons encore avec vtele cette fois: https://github.com/search?utf8=%E2%9C%93&q=vtele+brightcove. Oh! Il n’y a pas de code disponible, mais une Issue a été créé : https://github.com/spmjc/plugin.video.freplay/issues/52.
En regardant cette Issue en question, on peut voir ce magnifique token: 2sgr1KCsKKJXcqUFQdti_mXZAhdNB-wCFwCbGW6lz5atwI1QTrElxQ..
BINGO!
Comment cette personne a trouvé le token en question n’est pas cruciale pour le moment, mais pour ceux qui se le demande… Il est possible de l’obtenir en utilisant un appareil mobile (tel qu’un iPad par exemple) et de monitorer les requêtes effectuées à l’aide d’un proxy. Le développement d’applications mobiles contraint souvent les développeurs à oublier les requêtes serveur à serveur cachant habituellement ce genre d’information afin d’être plus efficaces à l’exécution.
Maintenant que nous avons le token et le videoId, en théorie, nous pouvons obtenir l’information de Brightcove sur les vidéos disponibles.
Essayons donc avec cette URL:
http://api.brightcove.com/services/library?command=find_video_by_id&video_id=4293298759001&video_fields=name,length,FLVURL&media_delivery=http&token=2sgr1KCsKKJXcqUFQdti_mXZAhdNB-wCFwCbGW6lz5atwI1QTrElxQ..
Oh yeah! On obtient quelque chose de bien intéressant:
{
"name":"Mousse chocolat et thé | Kruhnen (DTPA)",
"length":146588,
"FLVURL":"http:\/\/uds.ak.o.brightcove.com\/618566855001\/618566855001_4293368125001_4293298759001.mp4"
}
On a donc un appel API permettant d’obtenir un URL nous laissant télécharger un video en HTTP. Ceci dit, nous n’avons qu’un seul choix et non pas les 4 qualités (bitrate+résolution) précédemment détectées. Il nous faut donc comprendre quel appel exact faire à l’API de Brightcove pour obtenir ceux-ci.
En regardant d'un peu plus près, la documentation (http://docs.brightcove.com/en/video-cloud/media/references/reference.html#Video_Read), on nous dit qu’on peut choisir les champs utilisés, et un de ceux-ci est renditions
.
C’est exactement ce que l’on a besoin, alors essayons cette URL:
https://api.brightcove.com/services/library?video_fields=renditions&media_delivery=HTTP&command=find_video_by_id&video_id=4293298759001&token=2sgr1KCsKKJXcqUFQdti_mXZAhdNB-wCFwCbGW6lz5atwI1QTrElxQ..
Ataboy!! Finalement on a nos 4 choix au format MP4 dans cette réponse JSON:
{
"renditions":[
{
"audioOnly":false,
"controllerType":"DEFAULT",
"displayName":"CVB150615_11h00_s04e03.mov",
"encodingRate":1148856,
"frameHeight":404,
"frameWidth":720,
"id":4293368136001,
"referenceId":null,
"remoteStreamName":null,
"remoteUrl":null,
"size":21214406,
"uploadTimestampMillis":1434138086274,
"url":"http:\/\/uds.ak.o.brightcove.com\/618566855001\/618566855001_4293368136001_4293298759001.mp4",
"videoCodec":"H264",
"videoContainer":"MP4",
"videoDuration":146588
},
{
"audioOnly":false,
"controllerType":"DEFAULT",
"displayName":"CVB150615_11h00_s04e03.mov",
"encodingRate":780856,
"frameHeight":360,
"frameWidth":640,
"id":4293368125001,
"referenceId":null,
"remoteStreamName":null,
"remoteUrl":null,
"size":14468970,
"uploadTimestampMillis":1434138082765,
"url":"http:\/\/uds.ak.o.brightcove.com\/618566855001\/618566855001_4293368125001_4293298759001.mp4",
"videoCodec":"H264",
"videoContainer":"MP4",
"videoDuration":146588
},
{
"audioOnly":false,
"controllerType":"DEFAULT",
"displayName":"CVB150615_11h00_s04e03.mov",
"encodingRate":1748856,
"frameHeight":720,
"frameWidth":1280,
"id":4293368099001,
"referenceId":null,
"remoteStreamName":null,
"remoteUrl":null,
"size":32161904,
"uploadTimestampMillis":1434138079650,
"url":"http:\/\/uds.ak.o.brightcove.com\/618566855001\/618566855001_4293368099001_4293298759001.mp4",
"videoCodec":"H264",
"videoContainer":"MP4",
"videoDuration":146588
},
{
"audioOnly":false,
"controllerType":"DEFAULT",
"displayName":"CVB150615_11h00_s04e03.mov",
"encodingRate":512856,
"frameHeight":268,
"frameWidth":480,
"id":4293368106001,
"referenceId":null,
"remoteStreamName":null,
"remoteUrl":null,
"size":9565066,
"uploadTimestampMillis":1434138079982,
"url":"http:\/\/uds.ak.o.brightcove.com\/618566855001\/618566855001_4293368106001_4293298759001.mp4",
"videoCodec":"H264",
"videoContainer":"MP4",
"videoDuration":146588
}
]
}
On a pas mal fini là, on peut simplement télécharger n'importe lequel de ces liens HTTP. Par exemple, si nous allons sur cette URL:
http://uds.ak.o.brightcove.com/618566855001/618566855001_4293368106001_4293298759001.mp4
Nous pouvons télécharger en utilisant CTRL-S et fermer l'onglet une fois le téléchargement entamé.