hls-validator
Version:
this packages helps to validate *.m3u8 files (hls files)
129 lines (122 loc) • 4.81 kB
JavaScript
const Fs = require('fs');
const axios = require('axios');
class HlsValidator {
/**
* @description this instance helps to validate any hls file, weather its working to broken
* if any chunks or bitrates file is broken, this will failed the hls validation
*/
constructor() {}
/**
* @description this functions entry point of the validation, this initates all validations instances
* and make it test 10 chucks at a time
* @returns promise, if failed its returns objects {status: false: url: ''}, if its passed its just return boolean
*/
async init(url) {
this.url = url;
return new Promise(async (resolve, reject) => {
try {
const allChunks = await this.getAllChunks();
const checkAllChunks = async (chunks) => {
let requestPromises = chunks.splice(0, 10);
await Promise.all(
requestPromises.map(async (url) => {
try {
await this.download(url);
} catch (error) {
return reject(false);
} finally {
if (chunks.length) {
await checkAllChunks(chunks);
} else {
return resolve(true);
}
}
})
);
};
await checkAllChunks(allChunks);
} catch (error) {
reject(false);
}
});
}
/**
* @description this functions helps to make request to urls and returns promise
* @param save {boolean}, if you want to save files or not, deafult its false
* @returns Promise if it success or not
*/
async download(url, save = false) {
return new Promise(async (resolve, reject) => {
try {
const response = await axios({
method: 'GET',
url: url,
responseType: 'stream',
});
if (save) {
let file = url.split('/')[url.split('/').length - 1];
response.data.pipe(Fs.createWriteStream(file));
}
resolve(true);
} catch (error) {
reject(url);
}
});
}
/**
* @description this functions helps to get all data of *.m3u8, bitrates and chunks
* @param {string} url its takes hls url
* @returns promise, if resolved its returns array of the *.m3u8 data, if rejected returns error
*/
async getM3u8Data(url) {
return new Promise(async (resolve, reject) => {
try {
const response = await axios({ method: 'GET', url: url });
const initData = response.data.split('\n');
let m3u8Data = initData.filter(
(key) => key.endsWith('.m3u8') || key.endsWith('.ts')
);
return resolve(m3u8Data);
} catch (error) {
reject(error);
}
});
}
/**
* @description this functions helps to get all chunks of *.m3u8 files
* @returns its returns objects, {bitRate, url}
*/
getAllChunks() {
return new Promise(async (resolve, reject) => {
try {
let bitRates = await this.getM3u8Data(this.url);
bitRates = bitRates.map((suffix) => suffix.split('/')[0]);
let suffixFile =
this.url.split('/')[this.url.split('/').length - 1];
const baseURl = this.url.replace(suffixFile, '');
const bitRateUrls = bitRates.map((bitRate) => ({
bitRate,
url: `${baseURl}${bitRate}/${bitRate}.m3u8`,
}));
const allChunks = [];
await Promise.all(
bitRateUrls.map(async ({ bitRate, url }) => {
try {
let chunks = await this.getM3u8Data(url);
chunks = chunks.map(
(chunk) => `${baseURl}${bitRate}/${chunk}`
);
allChunks.push(...chunks);
} catch (err) {
reject(err);
}
})
);
return resolve(allChunks);
} catch (error) {
return reject(error);
}
});
}
}
module.exports = HlsValidator;