// ==UserScript==
// @name Arte+7 Downloader
// @namespace GuGuss
// @description Download videos or get stream link of ARTE programs in the selected language.
// @include https://*.arte.tv/*
// @version 2.7
// @updateURL https://github.com/GuGuss/ARTE-7-Downloader/raw/master/arte-downloader.user.js
// @grant GM_xmlhttpRequest
// @icon http://www.arte.tv/favicon.ico
// ==/UserScript==
/*
Support:
- new 360 HTML5 player: http://info.arte.tv/fr/wasala-arriver
- old 360 flash player: http://future.arte.tv/fr/5-metres-une-plongee-360deg-sur-votre-ordinateur
*/
/* --- GLOBAL VARIABLES --- */
var scriptVersion = "2.6";
var player = [];
var nbVideoPlayers = 0;
var is_playlist = false;
var playerJson;
var nbVideos;
var nbHTTP;
var nbRTMP;
var nbHLS;
var languages;
var qualities;
var videoPlayerElements;
var videoPlayerClass = {
'standard': 'arte_vp_url',
'oembed': 'arte_vp_url_oembed',
'general': 'video-container',
'live-oembed': 'arte_vp_live-url-oembed',
'generic': 'data-url',
'teaser': 'data-teaser-url'
};
var videoPlayerClassEmbedded = {
'story': 'embed.embed--delay iframe',
'embedded': 'media_embed iframe'
};
/* --- FUNCTIONS: utilities --- */
function getURLParameter(url, name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [, ""])[1].replace(/\+/g, '%20')) || null;
}
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function stringStartsWith(string, prefix) {
return string.slice(0, prefix.length) === prefix;
}
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
// Get a parent node of the chosen type and class
function getParent(nodeReference, nodeName, classString) {
var parent = node;
var nbNodeIteration = 0;
var nbNodeIterationMax = 10;
// any node
if (nodeName === '') {
console.log("> Looking for a parent node with class '" + classString + "'");
while (parent.nodeName !== "BODY" &&
nbNodeIteration < nbNodeIterationMax &&
hasClass(parent, classString) === false) {
nbNodeIteration++;
parent = parent.parentNode;
}
}
// with defined node type
else {
console.log("> Looking for a <" + nodeName + " class='" + classString + "'> parent node");
while (parent.nodeName !== "BODY" &&
nbNodeIteration < nbNodeIterationMax &&
(parent.nodeName !== nodeName.toUpperCase() || hasClass(parent, classString) === false)) {
nbNodeIteration++;
parent = parent.parentNode;
}
}
return parent;
}
/* --- FUNCTIONS: analysis --- */
function addLanguage(videoElementIndex, language, wording) {
if (!languages[videoElementIndex].hasOwnProperty(language)) {
languages[videoElementIndex][language] = wording;
}
}
function addQuality(videoElementIndex, quality, wording) {
if (!qualities[videoElementIndex].hasOwnProperty(quality)) {
qualities[videoElementIndex][quality] = wording;
}
}
function preParsePlayerJson(videoElementIndex) {
if (playerJson[videoElementIndex]) {
var videos = Object.keys(playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"]);
nbVideos[videoElementIndex] = videos.length;
// Loop through all videos URLs.
for (var key in videos) {
var video = playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"][videos[key]];
// Check if video format or media type
if (video["videoFormat"] === "HBBTV" || video["mediaType"] === "mp4") {
nbHTTP[videoElementIndex]++;
} else if (video["videoFormat"] === "RMP4" || video["mediaType"] === "rtmp") {
nbRTMP[videoElementIndex]++;
} else if (video["videoFormat"] === "M3U8" || video["mediaType"] === "hls") {
nbHLS[videoElementIndex]++;
}
addLanguage(videoElementIndex, video["versionCode"], video["versionLibelle"]);
addQuality(videoElementIndex, (
video["VQU"] !== undefined ? video["VQU"] : video["quality"]),
video["height"] ? video["height"] + "p@" + video["bitrate"] + "bps" : video["quality"]);
}
// Remove Apple HLS if HTTP available
if (nbHTTP[videoElementIndex] > 0) {
delete qualities[videoElementIndex]["XS"];
delete qualities[videoElementIndex]["XQ"];
}
// Reorder qualities
var sortedKeys = Object.keys(qualities[videoElementIndex]).sort(
function(a, b) {
// array of sorted keys
return qualities[videoElementIndex][b].split('@')[1].split('b')[0] * 1 - qualities[videoElementIndex][a].split('@')[1].split('b')[0] * 1;
}
);
// Create new object to rearrange qualities according to new key order
var temp = new Object;
for (var i = 0; i < sortedKeys.length; i++) {
temp[sortedKeys[i]] = qualities[videoElementIndex][sortedKeys[i]];
}
qualities[videoElementIndex] = temp; // replace with new ordered object
// Display preparse info
console.log("\n====== player #" + videoElementIndex + " ======\n> " +
nbVideos[videoElementIndex] + " formats: " + nbHTTP[videoElementIndex] + " HTTP videos | " + nbRTMP[videoElementIndex] + " RTMP streams | " + nbHLS[videoElementIndex] + " HLS streams.");
var languagesFound = "";
for (l in languages[videoElementIndex]) {
languagesFound += "\n - " + languages[videoElementIndex][l];
}
console.log("> Languages:" + languagesFound);
}
}
function parsePlayerJson(playerJsonUrl, videoElement, videoElementIndex) {
console.log(" - #" + videoElementIndex + " player JSON: " + playerJsonUrl);
GM_xmlhttpRequest({
method: "GET",
url: playerJsonUrl,
onload: function(response) {
playerJson[videoElementIndex] = JSON.parse(response.responseText);
preParsePlayerJson(videoElementIndex);
decoratePlayer(videoElement, videoElementIndex);
}
});
}
function getVideoName(videoElementIndex) {
var name = playerJson[videoElementIndex]['videoJsonPlayer']['VTI'];
if (name === null) {
name = playerJson[videoElementIndex]['videoJsonPlayer']['VST']['VNA'];
if (name === null) {
return "undefined";
}
}
name = name.split('_').join(' ');
return name.charAt(0).toUpperCase() + name.slice(1);
}
function getVideoUrl(videoElementIndex, quality, language) {
// Get videos object
var videos = Object.keys(playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"]);
// Check if there are HTTP videos
if (nbHTTP[videoElementIndex] > 0) {
// Loop through all videos URLs.
for (var key in videos) {
var video = playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"][videos[key]];
// Check language, format, quality
if (video["versionCode"] === language &&
(video["videoFormat"] === "HBBTV" || video["mediaType"] === "mp4") &&
(video["VQU"] === quality || video["quality"] === quality)) {
console.log("> " + quality + " MP4 in " + language + ": " + video["url"]);
return video["url"];
}
}
}
// Search RTMP streams
if (nbRTMP[videoElementIndex] > 0) {
for (var key in videos) {
var video = playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"][videos[key]];
if ((video["versionCode"] === language || language === undefined) &&
(video["VQU"] === quality || video["quality"] === quality) &&
(video["videoFormat"] === "RMP4" || video["mediaType"] === "rtmp")
) {
var url = video["streamer"] + video["url"];
console.log("> " + quality + " RTMP stream: " + url);
return url;
}
}
}
// Search HLS streams
if (nbHLS[videoElementIndex] > 0) {
for (var key in videos) {
var video = playerJson[videoElementIndex]["videoJsonPlayer"]["VSR"][videos[key]];
if (
(video["videoFormat"] === "M3U8" || video["mediaType"] === "hls") &&
(video["VQU"] === quality || video["quality"] === quality) &&
video["versionCode"] === language
) {
console.log("> HLS stream: " + video["url"]);
return video["url"];
}
}
}
console.log("> Video not found.")
return '';
}
function findPlayerJson(videoElement, videoElementIndex) {
// Get player URL to find its associated json
var playerUrl = null;
var jsonUrl = null;
for (key in videoPlayerClass) {
playerUrl = videoElement.getAttribute(videoPlayerClass[key]);
if (playerUrl !== null) {
break;
}
}
// oembed
if (playerUrl !== null && (key === "oembed" || (key === "live-oembed"))) {
GM_xmlhttpRequest({
method: "GET",
url: playerUrl,
onload: function(response) {
jsonUrl = unescape(response.responseText.split("json_url=")[1].split('"')[0]);
if (jsonUrl !== undefined) {
parsePlayerJson(jsonUrl, videoElement, videoElementIndex);
}
}
});
}
// http://www.arte.tv/arte_vp/
else if (stringStartsWith(location.href, "http://www.arte.tv/arte_vp/")) {
playerUrl = unescape(location.href.split("json_url=")[1]);
parsePlayerJson(playerUrl, videoElement, videoElementIndex);
}
// iframe embedded media
else if (playerUrl === null) {
playerUrl = unescape(videoElement.getAttribute('src'));
jsonUrl = playerUrl.split('json_url=')[1];
if (jsonUrl !== undefined) {
parsePlayerJson(jsonUrl, videoElement, videoElementIndex);
} else {
console.log("> Searching a 360 video in: " + playerUrl);
GM_xmlhttpRequest({
method: "GET",
url: playerUrl,
onload: function(response) {
var doc = response.responseText;
var videoName, videoURL;
// new 360 HTML5 player
if (playerUrl.indexOf("arte360") > -1) {
var playerJS = playerUrl.split("?root")[0] + "jsmin/output.min.js?" + doc.split("window.appVersion = \"")[1].split("\"")[0];
console.log("> 360 player JS: " + playerJS);
var root = getURLParameter(playerUrl, "root")
videoName = getURLParameter(playerUrl, "video")
videoURL = root + "/video/download/4K/" + videoName + "_4K.mp4";
console.log("> Video URL: " + videoURL);
var subtitlesURL = root + "/subtitles/" + videoName + "_" + getURLParameter(playerUrl, "lang") + ".srt";
console.log("> Subtitles URL: " + subtitlesURL);
decoratePlayer360(videoElement, videoURL, videoName, subtitlesURL);
}
// old 360 flash player
else if (playerUrl.indexOf("360FlashPlayers") > -1) {
console.log("> old player");
var xml = doc.split('xml:"')[1].split('"')[0];
GM_xmlhttpRequest({
method: "GET",
url: playerUrl + xml,
onload: function(response) {
xml = response.responseText;
// Get video URL
videoName = xml.split('videourl="%SWFPATH%/')[1].split('"')[0];
videoURL = playerUrl + videoName;
console.log(videoURL);
decoratePlayer360(videoElement, videoURL, videoName);
}
});
}
}
});
}
}
// Check if player URL is the json
else if (playerUrl.substring(playerUrl.length - 6, playerUrl.length - 1) === ".json") {
parsePlayerJson(playerUrl, videoElement, videoElementIndex);
}
// Look for player URL inside the player json
else {
GM_xmlhttpRequest({
method: "GET",
url: playerUrl,
onload: function(response) {
var json = JSON.parse(response.responseText);
playerUrl = json["videoJsonPlayer"]["videoPlayerUrl"];
if (playerUrl === undefined) { // not found ? Look for playlist file inside the livestream player
console.log("Video player URL not available. Fetching livestream player URL");
playerUrl = videoElement.getAttribute(videoPlayerClass['live']);
}
parsePlayerJson(playerUrl, videoElement, videoElementIndex);
}
});
}
}
function findPlayers() {
// Check playlist
playlistJson = /playlist_url=([^&]+)/.exec(window.location.href);
if (playlistJson != null) {
playlistJson=unescape(playlistJson[1]);
console.log("> Found playlist json: " + playlistJson)
console.log()
videoPlayerElements = parent.document.querySelectorAll("div.arte-playerfs.arte-playerfs--show");
GM_xmlhttpRequest({
method: "GET",
url: playlistJson,
onload: function(response) {
jsonUrl = JSON.parse(response.responseText);
//check whether exists a valid entry
if(typeof jsonUrl["videos"]!=="undefined" && typeof jsonUrl["videos"][0]!=="undefined") {
jsonUrl = jsonUrl["videos"][0]["jsonUrl"];
jsonUrl = jsonUrl.replace(/\\/g, ''); // remove backslashes from the URL
parsePlayerJson(jsonUrl, videoPlayerElements[0], 0);
}
}
});
nbVideoPlayers = videoPlayerElements.length;
return true;
} else {
// Check regular tags
for (tag in videoPlayerClass) {
videoPlayerElements = document.querySelectorAll("div[" + videoPlayerClass[tag] + "]");
if (videoPlayerElements.length > 0) {
console.log(videoPlayerClass[tag])
break;
}
}
// Check embedded tags
if (videoPlayerElements.length === 0) {
for (tag in videoPlayerClassEmbedded) {
videoPlayerElements = document.querySelectorAll("div." + videoPlayerClassEmbedded[tag]);
if (videoPlayerElements.length > 0) {
console.log(tag)
break;
}
}
}
// Check iframe
if (videoPlayerElements.length === 0) {
videoPlayerElements = document.querySelectorAll("iframe[arte-video]");
// Check 360 (no attributes yet)
if (videoPlayerElements.length === 0) {
videoPlayerElements = document.querySelectorAll("iframe");
}
}
// Check arte_vp with no parent frame
if (videoPlayerElements.length === 0 && stringStartsWith(unescape(top.location), "http://www.arte.tv/arte_vp/")) {
videoPlayerElements = document.querySelectorAll("body");
}
nbVideoPlayers = videoPlayerElements.length;
return false;
}
}
/* --- FUNCTIONS: decorating --- */
function createButtonDownload(videoElementIndex, language) {
var button = document.createElement('a');
var videoUrl;
for (q in qualities[videoElementIndex]) {
videoUrl = getVideoUrl(videoElementIndex, q, language);
if (videoUrl !== '') {
quality = q;
break;
}
}
// Check if video exists
if (videoUrl === null) {
console.log("Could not find video feed");
return null;
}
// Check RTMP stream
if (nbRTMP[videoElementIndex] > 0 && videoUrl.substring(0, 7) === "rtmp://") { // check first because it ends with .mp4 like HTTP
button.innerHTML = "Open VLC > CTRL+R > Network > Copy this link > Convert/Save video. ";
}
// Check HTTP
else if (nbHTTP[videoElementIndex] > 0 && videoUrl.substring(videoUrl.length - 4, videoUrl.length) === ".mp4") {
button.innerHTML = "Download video ";
}
// Check HLS stream : should not happen
else if (nbHLS[videoElementIndex] > 0 && videoUrl.substring(videoUrl.length - 5, videoUrl.length === ".m3u8")) {
button.innerHTML = "Open VLC > CTRL+R > Network > Copy this link > Convert/Save video. ";
}
// Unknown URL format : should not happen
else {
console.log('Unknown URL format');
return null;
}
button.setAttribute('id', 'btnDownload' + videoElementIndex); // to refer later in select changes
button.setAttribute('href', videoUrl);
button.setAttribute('target', '_blank');
button.setAttribute('download', getVideoName(videoElementIndex) + ".mp4");
button.setAttribute('class', 'btn btn-default');
button.setAttribute('style', 'line-height: 17px; margin-left:10px; text-align: center; padding-top: 9px; padding-bottom: 9px; padding-left: 12px; padding-right: 12px; color:rgb(40, 40, 40); background-color: rgb(230, 230, 230); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px; font-weight: 400;');
return button;
}
function createButtonMetadata(videoElementIndex) {
var title = getVideoName(videoElementIndex);
var subtitle = playerJson[videoElementIndex]['videoJsonPlayer']['VSU'];
var description_short = playerJson[videoElementIndex]['videoJsonPlayer']['V7T'];
var description = playerJson[videoElementIndex]['videoJsonPlayer']['VDE'];
var tags = playerJson[videoElementIndex]['videoJsonPlayer']['VTA'];
// Continue if at least one field is filled
if (title !== undefined || description_short !== undefined || subtitle !== undefined || description !== undefined || tags !== undefined) {
var button = document.createElement('a');
button.setAttribute('class', 'btn btn-default');
button.setAttribute('style', 'line-height: 17px; margin-left:10px; text-align: center; padding: 10px; color:rgb(40, 40, 40); background-color: rgb(230, 230, 230); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px;');
button.innerHTML = "Download description ";
var metadata = "[Title]\n" + title + "\n\n[Subtitle]\n" + subtitle + "\n\n[Description-short]\n" + description_short + "\n\n[Description]\n" + description + "\n\n[Tags]\n" + tags;
var encodedData = window.btoa(unescape(encodeURIComponent(metadata)));
button.setAttribute('href', 'data:application/octet-stream;charset=utf-8;base64,' + encodedData);
button.setAttribute('download', getVideoName(videoElementIndex) + '.txt');
return button;
} else {
return null;
}
}
function getComboboxSelectedValue(combobox) {
var cb = document.getElementById(combobox);
if (cb == null) {
cb = parent.document.getElementById(combobox);
}
return cb[cb.selectedIndex].value;
}
function createLanguageComboBox(videoElementIndex) {
var languageComboBox = document.createElement('select');
languageComboBox.setAttribute('id', 'cbLanguage' + videoElementIndex);
// Associate onchange event with function (bypass for GM)
languageComboBox.onchange = function() {
var selectedLanguage = languageComboBox.options[languageComboBox.selectedIndex].value;
console.log("\n> Language changed to " + selectedLanguage);
var btn = document.getElementById('btnDownload' + videoElementIndex);
var selectedQuality = getComboboxSelectedValue('cbQuality' + videoElementIndex);
var url = getVideoUrl(videoElementIndex, selectedQuality, selectedLanguage);
if (url !== '') {
btn.style.visibility = "visible";
btn.setAttribute('href', url);
} else {
btn.style.visibility = "hidden";
}
};
// Fill with available languages
for (l in languages[videoElementIndex]) {
if (languages[videoElementIndex][l] !== 0) {
languageComboBox.innerHTML += "";
}
}
languageComboBox.setAttribute('class', 'btn btn-default');
languageComboBox.setAttribute('style', (languageComboBox.innerHTML === "" ? "visibility:hidden;" : "max-width: 140px; padding: 6px; color:rgb(40, 40, 40); background-color: rgb(230, 230, 230); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px; font-weight: 400;"));
return languageComboBox;
}
function createQualityComboBox(videoElementIndex) {
var qualityComboBox = document.createElement('select');
qualityComboBox.setAttribute('id', 'cbQuality' + videoElementIndex);
// Associate onchange event with function (bypass for GM)
qualityComboBox.onchange = function() {
var selectedQuality = qualityComboBox.options[qualityComboBox.selectedIndex].value;
console.log("\n> Quality changed to " + selectedQuality);
var btn = document.getElementById('btnDownload' + videoElementIndex);
if (btn == null) {
btn = parent.document.getElementById('btnDownload' + videoElementIndex);
}
var selectedLanguage = getComboboxSelectedValue('cbLanguage' + videoElementIndex);
console.log(selectedLanguage);
var url = getVideoUrl(videoElementIndex, selectedQuality, selectedLanguage);
if (url !== '') {
btn.style.visibility = "visible";
btn.setAttribute('href', url);
} else {
console.log("Video not found for these settings!")
btn.style.visibility = "hidden";
}
};
// Fill with available qualities
for (q in qualities[videoElementIndex]) {
if (qualities[videoElementIndex][q] !== 0) {
qualityComboBox.innerHTML += "";
}
}
qualityComboBox.setAttribute('class', 'btn btn-default');
qualityComboBox.setAttribute('style', 'width:140px; padding: 6px; margin-left:10px; color:rgb(40, 40, 40); background-color: rgb(230, 230, 230); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px; font-weight: 400;');
return qualityComboBox;
}
function createCreditsElement() {
var credits = document.createElement('div');
credits.setAttribute('style', 'text-align: center; line-height: 20px; font-size: 11.2px; color: rgb(255, 255, 255); font-family: ProximaNova, Arial, Helvetica, sans-serif; padding: 5px; background-image:url("data:image/gif;base64,R0lGODlhAwADAIAAAMhFJuFdPiH5BAAAAAAALAAAAAADAAMAAAIERB5mBQA7")');
credits.innerHTML = 'Arte Downloader v.' + scriptVersion + ' built by and for the community with love' +
'
Contribute Here.';
return credits;
}
function decoratePlayer360(videoElement, videoURL, videoName) {
var container = document.createElement('div');
insertAfter(container, videoElement);
container.setAttribute('class', 'ArteDownloader-v' + scriptVersion)
container.setAttribute('style', 'background-image:url("data:image/gif;base64,R0lGODlhAwADAIAAAMhFJuFdPiH5BAAAAAAALAAAAAADAAMAAAIERB5mBQA7"); padding: 10px;');
var button = document.createElement('a');
button.innerHTML = "Download " + videoName + " ";
button.setAttribute('id', 'btnArteDownloader');
button.setAttribute('href', videoURL);
button.setAttribute('target', '_blank');
button.setAttribute('download', videoName);
button.setAttribute('class', 'btn btn-default');
button.setAttribute('style', 'margin-left:10px; text-align: center; padding-top: 9px; padding-bottom: 9px; padding-left: 12px; padding-right: 12px; color:rgb(40, 40, 40); background-color: rgb(230, 230, 230); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px; font-weight: 400;');
container.appendChild(button);
}
function decoratePlayer(videoElement, videoElementIndex) {
var parent;
var bRoyalSlider = false;
var container = document.createElement('div');
if (is_playlist) {
console.log("> Decorating playlist player")
videoElement.insertBefore(container, videoElement.firstChild)
} else {
// Look for the parent to decorate
parent = videoElement.parentNode;
if (videoElement.id == "jwPlayerContainer") {
console.log("> Decorating playlist player");
}
// iframe player
else if (videoElement.nodeName === "IFRAME") {
console.log("> Decorating iFrame player");
// Arte touslesinternets
if (stringStartsWith(window.location.href, "http://touslesinternets.arte")) {
parent.insertBefore(container, videoElement);
} else {
// Arte Tracks
if (stringStartsWith(window.location.href, "http://tracks.arte")) {
parent = getParent(videoElement, '', "video");
}
insertAfter(container, parent);
}
}
// http://www.arte.tv/arte_vp
else if (stringStartsWith(unescape(top.location), "http://www.arte.tv/arte_vp/")) {
console.log("> Decorating arte_vp");
var child = document.getElementById("arte_vp_player_container");
child.parentNode.insertBefore(container, child);
parent = container;
}
// overlayed player for Arte Cinema or media embedded
else if (stringStartsWith(location.href, "http://cinema.arte") ||
(parent.parentNode.getAttribute('id') === "embed_widget")) {
console.log("> Decorating overlayed Cinema player");
parent = parent.parentNode.parentNode;
parent.appendChild(container);
}
// royal slider player
else if (stringStartsWith(videoElement.getAttribute('class'), 'rsContent')) {
console.log("> Decorating RoyalSlider player");
bRoyalSlider = true;
// Get the parent with SliderTeaserView type
while (parent.getAttribute('data-teaser-type') !== "SliderTeaserView" && parent.getAttribute('class') !== 'dnd-drop-wrapper') {
parent = parent.parentNode;
}
insertAfter(container, parent);
}
// regular player
else {
console.log("> Decorating regular player");
if (stringStartsWith(location.href, "http://concert.arte")) {
var playerSection = document.querySelector('section#section-player');
if (playerSection !== null) {
insertAfter(container, playerSection);
} else {
parent = parent.parentNode;
parent.appendChild(container);
}
} else {
parent = parent.parentNode;
parent.appendChild(container);
}
}
}
container.setAttribute('class', 'ArteDownloader-v' + scriptVersion)
container.setAttribute('style', 'background-image:url("data:image/gif;base64,R0lGODlhAwADAIAAAMhFJuFdPiH5BAAAAAAALAAAAAADAAMAAAIERB5mBQA7"); padding: 10px;');
// Create index indicator if Royal Slider
if (bRoyalSlider === true) {
var indexElement = document.createElement('span');
indexElement.innerHTML = "Video " + (videoElementIndex + 1) + " / " + nbVideoPlayers;
indexElement.setAttribute('style', 'margin:10px; text-align: center; color:rgb(255, 255, 255); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px;');
container.appendChild(indexElement);
}
// Create video name + description span
var videoNameSpan = document.createElement('span');
var subtitle = playerJson[videoElementIndex]['videoJsonPlayer']['VSU'];
videoNameSpan.innerHTML = "" + getVideoName(videoElementIndex) + (subtitle !== undefined ? " - " + subtitle : "") + "
";
videoNameSpan.setAttribute('style', 'margin:10px; text-align: center; color:rgb(255, 255, 255); font-family: ProximaNova,Arial,Helvetica,sans-serif; font-size: 13px;');
container.appendChild(videoNameSpan);
// Create language combobox
var languageComboBox = createLanguageComboBox(videoElementIndex)
container.appendChild(languageComboBox);
// Check if there are languages available to select
var selectedLanguage;
if (languageComboBox.options.length > 0) {
selectedLanguage = languageComboBox.options[languageComboBox.selectedIndex].value;
}
// Create quality combobox
container.appendChild(createQualityComboBox(videoElementIndex));
// Create download button
var btnDownload = createButtonDownload(videoElementIndex, selectedLanguage);
if (btnDownload !== null) {
container.appendChild(btnDownload);
}
// Create metadata button
var btnMetadata = createButtonMetadata(videoElementIndex);
if (btnMetadata !== null) {
container.appendChild(btnMetadata);
}
// Create credits element if not RoyalSlider or if last player from RoyalSlider
if (bRoyalSlider === false || videoElementIndex === nbVideoPlayers - 1) { // glitch with javascript XHR requests concurrency
var credits = createCreditsElement();
parent.appendChild(credits);
}
}
is_playlist = findPlayers();
console.log("> Found " + nbVideoPlayers + " video player(s):");
if (nbVideoPlayers > 0) {
// Init global vars
playerJson = [nbVideoPlayers];
nbVideos = [nbVideoPlayers];
nbHTTP = [nbVideoPlayers];
nbRTMP = [nbVideoPlayers];
nbHLS = [nbVideoPlayers];
languages = [nbVideoPlayers];
qualities = [nbVideoPlayers];
for (i = 0; i < nbVideoPlayers; i++) {
playerJson[i] = 0;
nbVideos[i] = 0;
nbHTTP[i] = 0;
nbRTMP[i] = 0;
nbHLS[i] = 0;
languages[i] = new Object;
qualities[i] = new Object;
}
if (!is_playlist) {
// Analyse each video player, then decorate them
for (var i = 0; i < nbVideoPlayers; i++) {
findPlayerJson(videoPlayerElements[i], i);
}
}
}