/*
Aerostat Beam Coder - Node.js native bindings to FFmpeg.
Copyright (C) 2019 Streampunk Media Ltd.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
https://www.streampunk.media/ mailto:[email protected]
14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
*/
const os = require('os');
const fs = require('fs');
const util = require('util');
const https = require('https');
const cp = require('child_process');
const [ mkdir, access, rename, execFile, exec ] = // eslint-disable-line
[ fs.mkdir, fs.access, fs.rename, cp.execFile, cp.exec ].map(util.promisify);
async function get(ws, url, name) {
let received = 0;
let totalLength = 0;
return new Promise((comp, err) => {
https.get(url, res => {
if (res.statusCode === 301 || res.statusCode === 302) {
err({ name: 'RedirectError', message: res.headers.location });
} else {
res.pipe(ws);
if (totalLength == 0) {
totalLength = +res.headers['content-length'];
}
res.on('end', () => {
process.stdout.write(`Downloaded 100% of '${name}'. Total length ${received} bytes.\n`);
comp();
});
res.on('error', err);
res.on('data', x => {
received += x.length;
process.stdout.write(`Downloaded ${received * 100/ totalLength | 0 }% of '${name}'.\r`);
});
}
}).on('error', err);
});
}
async function getHTML(url, name) {
let received = 0;
let totalLength = 0;
return new Promise((resolve, reject) => {
https.get(url, res => {
const chunks = [];
if (totalLength == 0) {
totalLength = +res.headers['content-length'];
}
res.on('end', () => {
process.stdout.write(`Downloaded 100% of '${name}'. Total length ${received} bytes.\n`);
resolve(Buffer.concat(chunks));
});
res.on('error', reject);
res.on('data', (chunk) => {
chunks.push(chunk);
received += chunk.length;
process.stdout.write(`Downloaded ${received * 100/ totalLength | 0 }% of '${name}'.\r`);
});
}).on('error', reject);
});
}
async function inflate(rs, folder, name) {
const unzip = require('unzipper');
const directory = await unzip.Open.file(`${folder}/${name}.zip`);
const directoryName = directory.files[0].path;
return new Promise((comp, err) => {
console.log(`Unzipping '${folder}/${name}.zip'.`);
rs.pipe(unzip.Extract({ path: folder }).on('close', () => {
fs.rename(`./${folder}/${directoryName}`, `./${folder}/${name}`, () => {
console.log(`Unzipping of '${folder}/${name}.zip' completed.`);
comp();
});
}));
rs.on('error', err);
});
}
async function win32() {
console.log('Checking/Installing FFmpeg dependencies for Beam Coder on Windows.');
await mkdir('ffmpeg').catch(e => {
if (e.code === 'EEXIST') return;
else throw e;
});
const ffmpegFilename = 'ffmpeg-5.x-win64-shared';
await access(`ffmpeg/${ffmpegFilename}`, fs.constants.R_OK).catch(async () => {
const html = await getHTML('https://github.com/BtbN/FFmpeg-Builds/wiki/Latest', 'latest autobuilds');
const htmlStr = html.toString('utf-8');
const autoPos = htmlStr.indexOf('
', autoPos);
const autoStr = htmlStr.substring(autoPos, endPos);
const sharedEndPos = autoStr.lastIndexOf('">win64-gpl-shared-5.');
if (sharedEndPos === -1)
throw new Error('Failed to find latest v4.x autobuild from "https://github.com/BtbN/FFmpeg-Builds/wiki/Latest"');
const startStr = '