node-m3u8
node-m3u8 copied to clipboard
few extra features
List of additions/changes (all backward compatible)
parser
- added an
options
parameter tocreateStream(options)
-
options.lax
atrue/false
boolean which basically forgives the parsed text if it doesn't start by anEXTM3U
tag, this is useful for merging many m3u8s into one, while tailing a large Live file. -
options.beforeItemEmit()
a function hook which gets called before the emit of eachitem
event, passing thecurrentItem
as the 1st argument. The reason this was useful in my use case is because I had m3u8s without the program-date-time tag, where the .ts files were named using timestamps, so before each item emit, I was doing something like thiscurrentItem.set('date', new Date(currentItem.get('uri')));
- who knew thatffmpeg
does not support the inclusion ofEXT-X-PROGRAM-DATE-TIME
on each segment while generating m3u8s from a raw stream.
-
- added
parser['EXT-X-PROGRAM-DATE-TIME']()
, sincem3u.toString()
does output it if available but the current parser ignores it.
m3u
- added
m3u.clone()
basically just returns a clone of them3u
object. - added
m3u.concat()
which behaves exactly like howm3u.merge()
behaves but it returns a newm3u
object, basically just concats the playlist items. - added
m3u.mergeByUri()
to do a real unique merge, using eachitem.uri
as the identifier, returns a newm3u
object - added
m3u.mergeByDate()
to do a real unique merge using eachitem.date
to find the stream gaps of stream-A and fill them in with slices of stream-B, returns a newm3u
object - added some slicing functions, which each returns a new
m3u
object with a slice of the PlaylistItems. Also, slicing a live m3u while using an end-range, will make the returned m3u as VOD, since the slice has an ending.-
m3u.sliceByIndex()
, (aliasm3u.slice()
) slices based on the segments indices, returns a newm3u
object -
m3u.sliceBySeconds()
, slices based on the position of each segment on the timeline of video seconds duration, returns a newm3u
object -
m3u.sliceByDates()
slices based on the position of each segment on the timeline of real time (depends on theEXT-X-PROGRAM-DATE-TIME
tag of course, or a custom item.date being set via thebeforeItemEmit
hook), returns a newm3u
object
-
- added
m3u.insertPlaylistItemsAfter([newItems], afterItem)
- added
m3u.findDateGaps()
used bym3u.mergeByDate()
- added
m3u.sortByDate()
, sorting is useful if you're merging un-ordered or random playlists - added
m3u.sortByUri()
- added
m3u.resetTargetDuration()
which would either take anewTargetDuration
to compare it and set it, or atrue
boolean to re-check all thePlaylistItems
and figure out the max duration to use. - added
m3u.isDateSupported()
- added 2 functions to keep track if an
ENDLIST
tag was actually found, then it's aVOD
sinceEXT-X-PLAYLIST-TYPE
is optional and might not be there.-
m3u.isVOD()
-
m3u.isLive()
-
- added
m3u.isMaster()
if it's a master playlist or not.
Notes
- I think
m3u.merge()
should return a clone instead of mutating self, but that would be breaking change - OR if you prefer mutating self all the time, we can change all the other merging and slicing functions, i.e.m3u.slice*()
, to mutate self as well instead of returning a clone, let me know what you think - I was just trying to mimic what the javascriptArray
does when doing anarray.slice()
orarray.concat()
, both of these 2 return a newarray
.
Tests
I think I covered all the things I added :), still a little shy but I will submit more as I move along.
Wow, thanks for this. I'll be taking a closer look soon.
Wow, these are awesome additions! I'd love to take advantage of all of these. If you need help reviewing to get this PR merged I would be glad to. I have this module used in production now and I'd love these new additions/fixes.
I haven't had time yet. If you have time @blainsmith, it'd be appreciated.
Great, I will poke around at it. If you ever need another maintainer I'd be glad to help out. I do rely on this plugin a lot so I would love it to stay alive. We are using it at http://oddnetworks.com
So I found and issue with isLive()
and isVOD()
and that is with the following:
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-1",NAME="Audio",LANGUAGE="en",AUTOSELECT=YES,URI="audio_0_128000_hls.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=4928000,CODECS="avc1.64000d,mp4a.40.2",RESOLUTION=1280x544,AUDIO="audio-1"
video_0_2400000_hls.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2528000,CODECS="avc1.64000d,mp4a.40.2",RESOLUTION=854x362,AUDIO="audio-1"
video_0_1200000_hls.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1728000,CODECS="avc1.64000d,mp4a.40.2",RESOLUTION=640x272,AUDIO="audio-1"
video_0_800000_hls.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=928000,CODECS="avc1.64000d,mp4a.40.2",RESOLUTION=426x180,AUDIO="audio-1"
video_0_400000_hls.m3u8
This is actually a VOD, but it is the master.m3u8
file defining the bitrates. Unfortunately, you cannot tell it is either live or VOD until you parse the subsequent m3u8 urls (video_0_X_hls.m3u8). In most cases EXT-X-PLAYLIST-TYPE
and EXT-X-ENDLIST
will never appear in a file like this. Perhaps an isMaster()
method to account for this 3rd format would help identify them.
Sounds good, I can add that in
@bog, @blainsmith any more comments? and/or any idea when this would be merged? if accepted
I could do with these new features as well :)
I'm working on a fork for now so I have can point to it from a package.json file. Will switch it to point here when this is merged :)
ping
@bog