UNPKG

hls-validator

Version:

this packages helps to validate *.m3u8 files (hls files)

129 lines (122 loc) 4.81 kB
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;