| @@ -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 | |||
| } | |||
| ``` | |||