Skip to content

Instantly share code, notes, and snippets.

@samuelloza
Last active April 15, 2025 14:52
Show Gist options
  • Save samuelloza/df3c0934c7bb55beabb18d0ffae2edb7 to your computer and use it in GitHub Desktop.
Save samuelloza/df3c0934c7bb55beabb18d0ffae2edb7 to your computer and use it in GitHub Desktop.
Wistia downloader to run execute python3 -m http.server
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Descargar Wistia Videos Manualmente</title>
<style>
body {
font-family: Arial, sans-serif;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #999;
padding: 6px;
vertical-align: top;
}
input[type="text"] {
width: 100%;
box-sizing: border-box;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<h2>Lista de Videos (Wistia)</h2>
<table>
<thead>
<tr>
<th>Nombre de archivo</th>
<th>HTML Wistia</th>
<th>Nombre original</th>
</tr>
</thead>
<tbody id="videoTable"></tbody>
</table>
<br>
<button onclick="processAll()">Descargar Videos Seleccionados</button>
<script>
function sanitizeFilename(filename) {
return filename.replace(/[<>:"\/\\|?*]+/g, "");
}
function extractAndPopulateOptions(htmlInput, id) {
let parser = new DOMParser();
let decodedHtml = parser.parseFromString(htmlInput, "text/html").body.innerHTML;
let match = decodedHtml.match(/wvideo=([a-zA-Z0-9_-]+)/);
if (!match) {
alert(`Fila ${id + 1}: HTML inválido`);
return;
}
let extractedValue = match[1];
let embedUrl = `https://fast.wistia.net/embed/iframe/${extractedValue}`;
fetch(embedUrl)
.then(response => {
if (!response.ok) throw new Error("No se pudo obtener el video.");
return response.text();
})
.then(data => {
let titleMatch = data.match(/<title>(.*?)<\/title>/);
let extractedVideoTitle = titleMatch ? titleMatch[1] : `Video${id}`;
//document.getElementById(`video-name${id}`).value = sanitizeFilename(extractedVideoTitle);
let binFiles = data.match(/https?:\/\/[^"\s]+(?:\.bin|\.mp4)/g);
if (!binFiles || binFiles.length <= 2) {
alert(`Fila ${id + 1}: No se encontraron videos válidos.`);
return;
}
binFiles = binFiles.slice(0, -2).map(url => url.replace(".bin", ".mp4"));
// Encontrar el video más pesado
let maxSize = 0;
let bestUrl = "";
let pending = binFiles.length;
binFiles.forEach(url => {
fetch(url, { method: "HEAD" }).then(resp => {
let size = parseInt(resp.headers.get("content-length") || "0");
if (size > maxSize) {
maxSize = size;
bestUrl = url;
}
}).catch(() => {
// continuar aunque falle uno
}).finally(() => {
pending--;
if (pending === 0) {
document.getElementById(`video-select${id}`).value = bestUrl;
}
});
});
})
.catch(error => {
alert(`Fila ${id + 1}: Error al procesar - ${error.message}`);
});
}
function downloadViaForm(fileUrl, filename) {
fetch(fileUrl)
.then(response => {
if (!response.ok) throw new Error("No se pudo descargar el archivo.");
return response.blob();
})
.then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
})
.catch(err => {
console.error("Error al descargar el archivo:", err);
alert("Hubo un problema al descargar el archivo.");
});
}
function processAll() {
for (let i = 0; i < 20; i++) {
const name = document.getElementById(`video-name${i}`).value.trim();
const url = document.getElementById(`video-select${i}`).value.trim();
if (name && url && url.startsWith("http")) {
const filename = sanitizeFilename(name) + ".mp4";
downloadViaForm(url, filename);
}
}
alert("Descarga iniciada para todos los videos con URL válida.");
}
// Crear 20 filas
for (let i = 0; i < 20; i++) {
const tr = document.createElement("tr");
const tdName = document.createElement("td");
const inputName = document.createElement("input");
inputName.type = "text";
inputName.id = `video-name${i}`;
tdName.appendChild(inputName);
const tdHtml = document.createElement("td");
const inputHtml = document.createElement("input");
inputHtml.type = "text";
inputHtml.id = `video-html${i}`;
tdHtml.appendChild(inputHtml);
const tdResult = document.createElement("td");
const inputResult = document.createElement("input");
inputResult.type = "text";
inputResult.id = `video-select${i}`;
tdResult.appendChild(inputResult);
inputHtml.addEventListener("change", () => {
extractAndPopulateOptions(inputHtml.value, i);
});
tr.appendChild(tdName);
tr.appendChild(tdHtml);
tr.appendChild(tdResult);
document.getElementById("videoTable").appendChild(tr);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment