Script para descargar y desencriptar videos de la plataforma Platzi
- Node.js
- ffmpeg
Entrar por el navegador a un curso, abre las "Herramienats de desarrollador", pega el siguiente código y te descargará un zip con todos los segmentos del video
let s0 = document.createElement("script");
s0.onload = () => {
console.log('[Status]: Inject fflate')
let url = document.location.href.split("/");
let filename = `${url[url.length - 2]}.zip`;
let course = url[url.length - 3];
var toZip = {
[course]: {
[filename]: {}
},
};
console.log({ course, filename, toZip });
let s1 = document.createElement("script");
s1.onload = () => {
console.log('[Status]: Inject m3u8 parser')
const { zipSync, strToU8 } = fflate;
console.log('[Status]: Starting...')
fetch(location.href)
.then((response) => response.text())
.then((response) => {
let m3u8Url = response.match(/"hls":"(.[^}]+)"}/)[1];
console.log('[Status]: Download m3u8...')
fetch(m3u8Url)
.then((response) => response.text())
.then((EXTM3U) => {
let splited = EXTM3U.split("\n");
let bestQualityUrl = splited[splited.length - 1];
console.log('[Status]: Download best quality...')
fetch(bestQualityUrl)
.then((response) => response.text())
.then((m3u8) => {
var parser = new m3u8Parser.Parser();
parser.push(m3u8);
parser.end();
console.log('[Status]: Download key encription...')
fetch(parser.manifest.segments[0].key.uri)
.then((response) => response.arrayBuffer())
.then(async (key) => {
try {
toZip[course][filename]["enc.key"] = new Uint8Array(await key);
console.log('[Status]: Download segments...')
await parser.manifest.segments.reduce(
(acc, segment, index) => {
return acc.then(() => {
console.log(`[Status]: Downloding ${index+1} of ${parser.manifest.segments.length}`)
return fetch(segment.uri)
.then((response) => response.arrayBuffer())
.then(async (ab) => {
toZip[course][filename][`seg-${index}.ts.enc`] =
new Uint8Array(await ab);
return ab;
});
});
},
Promise.resolve()
);
console.log(`[Status]: Creating new m3u8 file`)
let parsedM3u8 = m3u8;
parsedM3u8 = parsedM3u8.replace(
parser.manifest.segments[0].key.uri,
"enc.key"
);
parser.manifest.segments = parser.manifest.segments.map(
(seg, index) => {
parsedM3u8 = parsedM3u8.replace(
seg.uri,
`seg-${index}.ts.enc`
);
return seg;
}
);
toZip[course][filename][`lista.m3u8`] = strToU8(parsedM3u8);
console.log('[Status]: Creating Zip File...')
var zipped = zipSync(toZip, {
level: 9,
});
var blob = new Blob([zipped.buffer], {
type: "application/zip",
});
blob.lastModifiedDate = new Date();
blob.name = filename;
let a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
console.log(`[Status]: Finished`)
} catch (error) {
console.error(error);
}
});
});
});
});
};
s1.src = "https://cdn.jsdelivr.net/npm/m3u8-parser@4.7.0/dist/m3u8-parser.js";
document.body.appendChild(s1);
};
s0.src = "https://cdn.jsdelivr.net/npm/fflate/umd/index.js";
document.body.appendChild(s0);
Una vez decargado el archivo XXXX.zip
descomprime y entra el archivo lista.m3u8
y los segmentos. Corre un servidor local con el siguiente comando
npx static-server
por lo general te genera un sitio estatico en http://localhost:9080/
en una terminal ejecutar
ffmpeg -i http://localhost:9080/lista.m3u8 -c copy output.ts