|
|
@@ -1,2 +1,121 @@ |
|
|
|
# m3u82json |
|
|
|
|
|
|
|
This tool let's you encode a HLS m3u8 playlist into json. It support's both master and playlist types. It could handle a URL and download the playlist or read from a file or standard input. |
|
|
|
``` |
|
|
|
$ ./m3u82json -h |
|
|
|
Usage of ./m3u82json: |
|
|
|
-a make URI absolute |
|
|
|
-b string |
|
|
|
Base URL |
|
|
|
-r Recursive download master and playlists |
|
|
|
``` |
|
|
|
|
|
|
|
Example output: |
|
|
|
|
|
|
|
```bash |
|
|
|
$ ./m3u82json 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' |
|
|
|
{ |
|
|
|
"URL": "https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8", |
|
|
|
"BaseUrl": "https://mnmedias.api.telequebec.tv/m3u8", |
|
|
|
"Type": "master", |
|
|
|
"Manifest": { |
|
|
|
"Variants": [ |
|
|
|
{ |
|
|
|
"URI": "https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/yd/yLpoUEilVrxhhYSkpsyGMnn9t0N3AYxWmoMsM7Faw/francstireurs_entrevue_ep472_seq24.mpegts/playlist-de5cb50573ac3952cd031f64973a614828771406.m3u8", |
|
|
|
"Chunklist": null, |
|
|
|
"ProgramId": 1, |
|
|
|
"Bandwidth": 794000, |
|
|
|
"AverageBandwidth": 0, |
|
|
|
"Codecs": "avc1.64001f,mp4a.40.2", |
|
|
|
"Resolution": "640x360", |
|
|
|
"Audio": "", |
|
|
|
"Video": "", |
|
|
|
"Subtitles": "", |
|
|
|
"Captions": "", |
|
|
|
"Name": "", |
|
|
|
"Iframe": false, |
|
|
|
"VideoRange": "", |
|
|
|
"HDCPLevel": "", |
|
|
|
"FrameRate": 0, |
|
|
|
"Alternatives": null |
|
|
|
}, |
|
|
|
{ |
|
|
|
"URI": "https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/pG/_eYmKLIBSVI6S27rSuF_ykGSlW0Qc8D1PALJty4Mk/francstireurs_entrevue_ep472_seq24.mpegts/playlist-3e7933be6a617888b736c1ebbb1f2a6bcda30afd.m3u8", |
|
|
|
"Chunklist": null, |
|
|
|
"ProgramId": 1, |
|
|
|
"Bandwidth": 64000, |
|
|
|
"AverageBandwidth": 0, |
|
|
|
"Codecs": "", |
|
|
|
"Resolution": "398x224", |
|
|
|
"Audio": "", |
|
|
|
... |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
Once you have a json, it is very easy to work with it, for example with jq: |
|
|
|
|
|
|
|
Get the Resolution and bandwidth of each rendition: |
|
|
|
``` |
|
|
|
$ ./m3u82json -r 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' | jq '.Manifest | .Variants[] | {Resolution: .Resolution, BW: .Bandwidth}' |
|
|
|
{ |
|
|
|
"Resolution": "640x360", |
|
|
|
"BW": 794000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "398x224", |
|
|
|
"BW": 64000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "416x234", |
|
|
|
"BW": 209000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "480x270", |
|
|
|
"BW": 429000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "768x432", |
|
|
|
"BW": 1196000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "960x540", |
|
|
|
"BW": 2096000 |
|
|
|
} |
|
|
|
{ |
|
|
|
"Resolution": "1280x720", |
|
|
|
"BW": 3096000 |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
Get the URL of each rendition: |
|
|
|
|
|
|
|
``` |
|
|
|
$ ./m3u82json -r 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' | jq '.Manifest | .Variants[] | .URI' |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/yd/yLpoUEilVrxhhYSkpsyGMnn9t0N3AYxWmoMsM7Faw/francstireurs_entrevue_ep472_seq24.mpegts/playlist-de5cb50573ac3952cd031f64973a614828771406.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/pG/_eYmKLIBSVI6S27rSuF_ykGSlW0Qc8D1PALJty4Mk/francstireurs_entrevue_ep472_seq24.mpegts/playlist-3e7933be6a617888b736c1ebbb1f2a6bcda30afd.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/Sf/0Yz6m4a9H2LvdJs5cXZ2OkLVBsVETi3pQR4LF-Z3k/francstireurs_entrevue_ep472_seq24.mpegts/playlist-767499b7586bfe9b892916f8a24e71928f2e509f.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/DW/tAHYcWrGU7mj9nce4TbYlou5LPRT67U7UKqD1-L2c/francstireurs_entrevue_ep472_seq24.mpegts/playlist-b08bceed9acbde9e396ff9bda6c47b0e2767ffc3.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/Eg/o_fUnlyL800wzDHxFl6hhw-8UQc-ooyDeghAFJJhc/francstireurs_entrevue_ep472_seq24.mpegts/playlist-d4a7a4f0ec6d5166035d24a010a67a11eca19cf4.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/lB/Qc25Nb0TUdQe_w_ScrBJzqxkVpsKUEm1dGtLWhM3g/francstireurs_entrevue_ep472_seq24.mpegts/playlist-10a6530ae4e350c1c757c11287d1a0f7c2fad471.m3u8" |
|
|
|
"https://s2.content.video.llnw.net/smedia/42f4e71183054396907c0dea18241568/Ks/l56Xl_JnkEU-hQoz9-AHS5lrBjICWHZV0dybQSN3w/francstireurs_entrevue_ep472_seq24.mpegts/playlist-933ef269e85350d026f5e55af66a76a52737ff48.m3u8" |
|
|
|
``` |
|
|
|
|
|
|
|
Get the last chunk of the best rendition: |
|
|
|
|
|
|
|
``` |
|
|
|
$ ./m3u82json -r -a 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' | jq '.Manifest | .Variants[] | select(.Resolution == "1280x720") | .Chunklist.Segments[-1]' |
|
|
|
{ |
|
|
|
"SeqId": 104, |
|
|
|
"Title": "", |
|
|
|
"URI": "https://mnmedias.api.telequebec.tv/m3u8/playlist104.ts", |
|
|
|
"Duration": 8.313322, |
|
|
|
"Limit": 0, |
|
|
|
"Offset": 0, |
|
|
|
"Key": null, |
|
|
|
"Map": null, |
|
|
|
"Discontinuity": false, |
|
|
|
"SCTE": null, |
|
|
|
"ProgramDateTime": "0001-01-01T00:00:00Z", |
|
|
|
"Custom": null |
|
|
|
} |
|
|
|
``` |