Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.idea/
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ node-m3u8 is a streaming m3u8 parser tailored for dealing with [Apple's HTTP
Live Streaming protocol](http://tools.ietf.org/html/draft-pantos-http-live-streaming).
It may work for other m3u files, but I have not tested it for those uses.

Note: this is an updated fork of `m3u8` that fixes a bunch of warnings with unknown attributes. These attributes have been accounted for. The main package `m3u8` appears to be dead.

install
-------

npm install --save @chovy/m3u8

example
-------

``` js
var m3u8 = require('m3u8');
var m3u8 = require('@chovy/m3u8');
var fs = require('fs');

var parser = m3u8.createStream();
Expand All @@ -36,7 +43,7 @@ parser.on('item', function(item) {

The M3U and Item objects are available on m3u8:
```
var m3u8 = require('m3u8');
var m3u8 = require('@chovy/m3u8');

var m3u = m3u8.M3U.create();
m3u.addPlaylistItem({
Expand All @@ -45,4 +52,4 @@ m3u.addPlaylistItem({
});
```

See tests for more usage patterns.
See tests for more usage patterns.
186 changes: 96 additions & 90 deletions m3u/AttributeList.js
Original file line number Diff line number Diff line change
@@ -1,124 +1,130 @@
var AttributeList = module.exports = function AttributeList(attributes) {
this.attributes = {};
this.mergeAttributes(attributes);
this.attributes = {};
this.mergeAttributes(attributes);
};

var dataTypes = AttributeList.dataTypes = {
'audio' : 'quoted-string',
'autoselect' : 'boolean',
'bandwidth' : 'decimal-integer',
'byterange' : 'enumerated-string',
'codecs' : 'quoted-string',
'default' : 'boolean',
'duration' : 'decimal-floating-point',
'forced' : 'boolean',
'group-id' : 'quoted-string',
'language' : 'quoted-string',
'name' : 'quoted-string',
'program-id' : 'decimal-integer',
'resolution' : 'decimal-resolution',
'subtitles' : 'quoted-string',
'title' : 'enumerated-string',
'type' : 'enumerated-string',
'uri' : 'quoted-string',
'video' : 'quoted-string'
'audio' : 'quoted-string',
'average-bandwidth' : 'decimal-integer',
'autoselect' : 'boolean',
'bandwidth' : 'decimal-integer',
'byterange' : 'enumerated-string',
'channels' : 'quoted-string',
'_avg-bandwidth' : 'decimal-integer',
'closed-captions' : 'quoted-string',
'codecs' : 'quoted-string',
'default' : 'boolean',
'duration' : 'decimal-floating-point',
'forced' : 'boolean',
'frame-rate' : 'decimal-floating-point',
'group-id' : 'quoted-string',
'instream-id' : 'quoted-string',
'language' : 'quoted-string',
'name' : 'quoted-string',
'program-id' : 'decimal-integer',
'resolution' : 'decimal-resolution',
'subtitles' : 'quoted-string',
'title' : 'enumerated-string',
'type' : 'enumerated-string',
'uri' : 'quoted-string',
'video' : 'quoted-string'
};

AttributeList.prototype.mergeAttributes = function mergeAttributes(attributes) {
var self = this;
if (Array.isArray(attributes)) {
attributes.forEach(function(attribute) {
self.set(attribute.key, attribute.value);
});
}
var self = this;
if (Array.isArray(attributes)) {
attributes.forEach(function (attribute) {
self.set(attribute.key, attribute.value);
});
}
};

AttributeList.prototype.get = function getValue(key) {
return this.attributes[key];
return this.attributes[key];
};

AttributeList.prototype.set = function setValue(key, value) {
key = key.toLowerCase();
this.attributes[key] = parse[dataTypes[key] || 'unknown'](value, key);
key = key.toLowerCase();
this.attributes[key] = parse[dataTypes[key] || 'unknown'](value, key);

return this;
return this;
};

AttributeList.prototype.getCoerced = function getCoerced(key) {
return coerce[dataTypes[key] || 'unknown'](this.get(key));
return coerce[dataTypes[key] || 'unknown'](this.get(key));
};

AttributeList.prototype.toString = function toString() {
var self = this;
return Object.keys(this.attributes).map(function(key) {
return [key.toUpperCase(), self.getCoerced(key)].join('=');
}).join(',');
var self = this;
return Object.keys(this.attributes).map(function (key) {
return [key.toUpperCase(), self.getCoerced(key)].join('=');
}).join(',');
};

AttributeList.prototype.serialize = function serialize() {
return this.attributes;
return this.attributes;
};

AttributeList.unserialize = function unserialize(object) {
var list = new AttributeList;
list.attributes = object;
return list;
var list = new AttributeList;
list.attributes = object;
return list;
};

var coerce = {
'boolean': function coerceBoolean(value) {
return value ? 'YES' : 'NO';
},
'decimal-floating-point': parseFloat,
'decimal-integer': function coerceDecimalInteger(value) {
return parseInt(value, 10);
},
'decimal-resolution': function coerceDecimalResolution(value) {
if (Array.isArray(value)) {
return value.join('x');
} else {
return value;
'boolean': function coerceBoolean(value) {
return value ? 'YES' : 'NO';
},
'decimal-floating-point': parseFloat,
'decimal-integer': function coerceDecimalInteger(value) {
return parseInt(value, 10);
},
'decimal-resolution': function coerceDecimalResolution(value) {
if (Array.isArray(value)) {
return value.join('x');
} else {
return value;
}
},
'enumerated-string': function coerceEnumeratedString(value) {
return value;
},
'quoted-string': function coerceQuotedString(value) {
return '"' + value.replace(/"/g, '\\"') + '"';
},
'unknown': function coerceUnknown(value) {
return value;
}
},
'enumerated-string': function coerceEnumeratedString(value) {
return value;
},
'quoted-string': function coerceQuotedString(value) {
return '"' + value.replace(/"/g, '\\"') + '"';
},
'unknown': function coerceUnknown(value) {
return value;
}
};

var parse = {
'boolean': function parseBoolean(value) {
return typeof value == 'boolean'
? value
: (value == 'YES' ? true : false);
},
'decimal-floating-point': parseFloat,
'decimal-integer': function parseDecimalInteger(value) {
return parseInt(value, 10);
},
'decimal-resolution': function coerceDecimalResolution(value) {
return value.split('x').map(parse['decimal-integer']);
},
'enumerated-string': function parseEnumeratedString(value) {
return value;
},
'quoted-string': function parseQuotedString(value) {
if (Array.isArray(value)) {
return value.join(',');
} else if (value.indexOf('"') === 0 &&
value.lastIndexOf('"') == value.length - 1) {
return value.slice(1,-1);
} else {
return value;
'boolean': function parseBoolean(value) {
return typeof value == 'boolean'
? value
: (value == 'YES' ? true : false);
},
'decimal-floating-point': parseFloat,
'decimal-integer': function parseDecimalInteger(value) {
return parseInt(value, 10);
},
'decimal-resolution': function coerceDecimalResolution(value) {
return value.split('x').map(parse['decimal-integer']);
},
'enumerated-string': function parseEnumeratedString(value) {
return value;
},
'quoted-string': function parseQuotedString(value) {
if (Array.isArray(value)) {
return value.join(',');
} else if (value.indexOf('"') === 0 &&
value.lastIndexOf('"') == value.length - 1) {
return value.slice(1, -1);
} else {
return value;
}
},
'unknown': function parseUnknown(value, key) {
console.error('Handling value:', value, ' for unknown key:', key);
return value;
}
},
'unknown': function parseUnknown(value, key) {
console.error('Handling value:', value, ' for unknown key:', key);
return value;
}
};
};
Loading