Last active
August 5, 2022 21:25
-
-
Save erdesigns-eu/c7586e5e6ae135e41f5230f3ee97a2f0 to your computer and use it in GitHub Desktop.
M3U Writer Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Constantes used for constructing. | |
*/ | |
const EXTGRP = 'EXTGRP'; | |
const EXTPLS = 'PLAYLIST'; | |
const GROUPTITLE = 'group-title'; | |
/** | |
* M3U Writer Class | |
*/ | |
export class m3uWriter { | |
// New Line Character(s) | |
#newLine = '\n'; | |
// Use group-title directives? | |
#groupDirectives = false; | |
// Excluded attributes | |
#attributes = []; | |
// Excluded directives | |
#directives = []; | |
// Class constructor | |
constructor(options) { | |
const vm = this; | |
// Set newline character(s) | |
if (options && options.newLine && options.newLine.length) { | |
vm.#newLine = `${options.newLine}`; | |
} | |
// Set use group-title directives | |
if (options && options.groupDirectives && options.groupDirectives === true) { | |
vm.#groupDirectives = options.groupDirectives; | |
} | |
// Set attributes | |
if (options && options.attributes && Array.isArray(options.attributes)) { | |
vm.#attributes = [...options.attributes]; | |
} | |
// Set directives | |
if (options && options.directives && Array.isArray(options.directives)) { | |
vm.#directives = [...options.directives]; | |
} | |
} | |
// Format attribute | |
formatAttribute(attribute, value) { | |
return `${attribute.toLowerCase()}="${value}"`; | |
} | |
// Format directive | |
formatDirective(directive, value) { | |
return `#${directive.toUpperCase()}:${value}`; | |
} | |
// Format #EXTINF line from stream | |
formatStream(stream, group) { | |
const vm = this; | |
let res = `#EXTINF:${stream.length}`; | |
// Add attributes | |
stream.attributes.forEach((attribute) => { | |
if (!vm.#attributes.includes(attribute.attribute)) { | |
res += ` ${vm.formatAttribute(attribute.attribute, attribute.value)}`; | |
} | |
}); | |
// Add group-title? | |
if (group && vm.#groupDirectives !== true) { | |
res += ` ${vm.formatAttribute(GROUPTITLE, group)}`; | |
} | |
// Add title | |
res += `,${stream.title}` | |
return res; | |
} | |
write(m3u) { | |
const vm = this; | |
// Return a promise (Async) | |
return new Promise((resolve, reject) => { | |
// Playlist output | |
let playlist = '#EXTM3U'; | |
if (m3u.attributes && m3u.attributes.length) { | |
m3u.attributes.forEach((attribute) => { | |
playlist += ` ${vm.formatAttribute(attribute.attribute, attribute.value)}`; | |
}); | |
} | |
// Function: Add line to playlist | |
const addLine = (line) => { | |
playlist += vm.#newLine; | |
playlist += line; | |
} | |
// Add playlist title | |
if (m3u.title && m3u.title.length) { | |
addLine(vm.formatDirective(EXTPLS, m3u.title)); | |
} | |
// Add streams | |
if (m3u.groups && Array.isArray(m3u.groups)) { | |
// Loop over groups | |
m3u.groups.forEach((group) => { | |
// Loop over streams in group | |
group.streams.forEach((stream) => { | |
// Add stream #EXTINF | |
addLine(vm.formatStream(stream, group.title)); | |
// Add group directive? | |
if (vm.#groupDirectives === true) { | |
addLine(vm.formatDirective(EXTGRP, group.title)); | |
} | |
// Add directives | |
stream.directives.forEach((directive) => { | |
if (!vm.#directives.includes(directive.directive)) { | |
addLine(vm.formatDirective(directive.directive, directive.value)); | |
} | |
}); | |
// Add stream URL/Filename | |
addLine(stream.url); | |
}); | |
}); | |
} else { | |
reject('error.no-groups-defined'); | |
return; | |
} | |
// Finished constructing M3U playlist | |
resolve(playlist); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment