m3ufu


Namem3ufu JSON
Version 0.0.87 PyPI version JSON
download
home_pagehttps://github.com/futzu/m3u8fu
SummaryM3U8 Parser with SCTE-35 Support
upload_time2024-01-23 05:37:20
maintainer
docs_urlNone
authorAdrian
requires_python>=3.6
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [Requires](#requires) | [Install](#install) | [Usage](#usage) | [Output](#output) | [SCTE-35](#scte-35) | [AES Decrypt](#automatic-aes-decryption) | [Super Kabuki](https://github.com/futzu/threefive/blob/master/superkabuki.md)


# M3uFu
The Most Advanced M3U8 Parser Available.
## Latest Version `v0.0.87`  __Critical Update__
* TagParser update to handle tags without values.

### `Features:`
* All HLS Tags are Supported.
* Private / Custom Tags are Supported.
* Master Playlists are Supported.
* HTTP(S), Multicast,UDP, and File Source URIs are Supported.
* Full 2022 SCTE-35 Support. 
* Base64, Bytes, and Hex formated SCTE-35 Cues are Supported.
* Automatic Decryption of AES Encrypted Segments.
* Desegmentation. Playlist Segments can be Reassembled into a Single Mpegts File.


### `Requires`:
* python3.6+ or pypy3

### `Install`:
```smalltalk
python3 -mpip install  m3ufu

         # and/or 

pypy3 -mpip install m3ufu
```

### `Usage`:
```lua
usage: m3ufu [-h] [-i INPUT] [-o OUTFILE] [-v] [-d]

optional arguments:

 -h, --help            show this help message and exit
 
 -i INPUT, --input INPUT
                        Input source, like "/home/a/vid.ts" or 
                        "udp://@235.35.3.5:3535" or "https://futzu.com/xaa.ts"

-o OUTFILE, --outfile OUTFILE
                        download and reassemble segments and write to outfile.
                        SCTE35 cues are written to sidecar.txt

-v, --version         Show version

-d, --debug           Enable debug output.


```

### `Automatic AES Decryption`
* When m3ufu detects AES-128,  it automatically decrypts the segment
  * This is used:
     * to read PTS from the segment
     * desegmenting a playlist and combining them into a single mpegts file

### `Output`:
* Returns JSON 
```smalltalk
{
    "headers": {
        "#EXTM3U": "",
        "#EXT-X-VERSION": "3",
        "#EXT-X-TARGETDURATION": "12",
        "#EXT-X-MEDIA-SEQUENCE": "1",
        "#EXT-X-PLAYLIST-TYPE": "VOD"
    },
    "media": [
        {
            "media": "file_60p_1_00001.ts",
            "end": 10.0,
            "duration": 10.0,
            "tags": {
                "#EXTINF": 10.0
            }
        },
```
### `SCTE-35`
* SCTE-35 Cues are parsed and the data is included
```
        {
            "media": "seg70.ts",
            "start": 147.157,
            "end": 148.058,
            "duration": 0.901,
            "cue": "/DAlAAAAAAAAAAAAFAUAAABXf+//iNg15n4Ae97wAAECAQAAtBIorQ==",
            "cue_data": {
                "info_section": {
                    "table_id": "0xfc",
                    "section_syntax_indicator": false,
                    "private": false,
                    "sap_type": "0x3",
                    "sap_details": "No Sap Type",
                    "section_length": 37,
                    "protocol_version": 0,
                    "encrypted_packet": false,
                    "encryption_algorithm": 0,
                    "pts_adjustment_ticks": 0,
                    "pts_adjustment": 0.0,
                    "cw_index": "0x0",
                    "tier": "0x0",
                    "splice_command_length": 20,
                    "splice_command_type": 5,
                    "descriptor_loop_length": 0,
                    "crc": "0xb41228ad"
                },
                "command": {
                    "command_length": 20,
                    "command_type": 5,
                    "name": "Splice Insert",
                    "time_specified_flag": true,
                    "pts_time": 73231.536067,
                    "pts_time_ticks": 6590838246,
                    "break_auto_return": false,
                    "break_duration": 90.2,
                    "break_duration_ticks": 8118000,
                    "splice_event_id": 87,
                    "splice_event_cancel_indicator": false,
                    "out_of_network_indicator": true,
                    "program_splice_flag": true,
                    "duration_flag": true,
                    "splice_immediate_flag": false,
                    "unique_program_id": 1,
                    "avail_num": 2,
                    "avail_expected": 1
                },
                "descriptors": []
            },
            "tags": {
                "#EXT-X-SCTE35": {
                    "CUE-OUT": "YES",
                    "CUE": "/DAlAAAAAAAAAAAAFAUAAABXf+//iNg15n4Ae97wAAECAQAAtBIorQ=="
                },
                "#EXTINF": 0.901
            }
        },

....
```

###  __Master Playlists are also Supported__

```smalltalk
a@fumatica:~/m3u8fu$ pypy3  m3ufu.py ../threefive/master.m3u8 
{
    "headers": {
        "#EXTM3U": "",
        "#EXT-X-INDEPENDENT-SEGMENTS": "",
        "#EXT-X-VERSION": "7"
    },
    "media": [
        {
            "media": "media-4/stream.m3u8",
            "tags": {
                "#EXT-X-MEDIA": {
                    "AUTOSELECT": "YES",
                    "DEFAULT": "YES",
                    "LANGUAGE": "en",
                    "NAME": "CC1",
                    "GROUP-ID": "text",
                    "INSTREAM-ID": "CC1",
                    "TYPE": "CLOSED-CAPTIONS"
                },
                "#EXT-X-STREAM-INF": {
                    "CLOSED-CAPTIONS": "text",
                    "RESOLUTION": "768x432",
                    "CODECS": "avc1.4D401F,mp4a.40.2",
                    "BANDWIDTH": 2127786,
                    "AVERAGE-BANDWIDTH": 2030321
                }
            }
        },
        {
            "media": "media-1/stream.m3u8",
            "tags": {
                "#EXT-X-STREAM-INF": {
                    "CLOSED-CAPTIONS": "text",
                    "RESOLUTION": "416x234",
                    "CODECS": "avc1.4D400D,mp4a.40.2",
                    "BANDWIDTH": 410181,
                    "AVERAGE-BANDWIDTH": 393177
                }
            }
        },
        {
            "media": "media-2/stream.m3u8",
            "tags": {
                "#EXT-X-STREAM-INF": {
                    "CLOSED-CAPTIONS": "text",
                    "RESOLUTION": "416x234",
                    "CODECS": "avc1.4D400D,mp4a.40.2",
                    "BANDWIDTH": 727459,
                    "AVERAGE-BANDWIDTH": 698361
                }
            }
        },
        {
            "media": "media-3/stream.m3u8",
            "tags": {
                "#EXT-X-STREAM-INF": {
                    "CLOSED-CAPTIONS": "text",
                    "RESOLUTION": "640x360",
                    "CODECS": "avc1.4D401E,mp4a.40.2",
                    "BANDWIDTH": 1263349,
                    "AVERAGE-BANDWIDTH": 1210676
                }
            }
        },
```
* __Even Master Playlists of iframe Playlists are Supported__.
```
        {
            "media": "media-1/iframes.m3u8",
            "tags": {
                "#EXT-X-I-FRAME-STREAM-INF": {
                    "URI": "media-1/iframes.m3u8",
                    "RESOLUTION": "416x234",
                    "CODECS": "avc1.4D400D",
                    "BANDWIDTH": 360599,
                    "AVERAGE-BANDWIDTH": 64059
                }
            }
        },
        {
            "media": "media-2/iframes.m3u8",
            "tags": {
                "#EXT-X-I-FRAME-STREAM-INF": {
                    "URI": "media-2/iframes.m3u8",
                    "RESOLUTION": "416x234",
                    "CODECS": "avc1.4D400D",
                    "BANDWIDTH": 631048,
                    "AVERAGE-BANDWIDTH": 121087
                }
            }
        },
        {
            "media": "media-3/iframes.m3u8",
            "tags": {
                "#EXT-X-I-FRAME-STREAM-INF": {
                    "URI": "media-3/iframes.m3u8",
                    "RESOLUTION": "640x360",
                    "CODECS": "avc1.4D401E",
                    "BANDWIDTH": 1171948,
                    "AVERAGE-BANDWIDTH": 223837
                }
            }
        },
        {
            "media": "media-4/iframes.m3u8",
            "tags": {
                "#EXT-X-I-FRAME-STREAM-INF": {
                    "URI": "media-4/iframes.m3u8",
                    "RESOLUTION": "768x432",
                    "CODECS": "avc1.4D401F",
                    "BANDWIDTH": 1752287,
                    "AVERAGE-BANDWIDTH": 354946
                }
            }
        },
        {
            "media": "media-5/iframes.m3u8",
            "tags": {
                "#EXT-X-I-FRAME-STREAM-INF": {
                    "URI": "media-5/iframes.m3u8",
                    "RESOLUTION": "960x540",
                    "CODECS": "avc1.4D401F",
                    "BANDWIDTH": 2343896,
                    "AVERAGE-BANDWIDTH": 440896
                }
            }
        },
 
```
![image](https://user-images.githubusercontent.com/52701496/203175735-d2f7c6b9-f45a-4e2b-9c81-86babc28576e.png)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/futzu/m3u8fu",
    "name": "m3ufu",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "",
    "author": "Adrian",
    "author_email": "spam@iodisco.com",
    "download_url": "https://files.pythonhosted.org/packages/82/b0/2cab72569ecd5e7c2b7d11c039c6e134c3167d9d241b071d8fc1095bb033/m3ufu-0.0.87.tar.gz",
    "platform": null,
    "description": "[Requires](#requires) | [Install](#install) | [Usage](#usage) | [Output](#output) | [SCTE-35](#scte-35) | [AES Decrypt](#automatic-aes-decryption) | [Super Kabuki](https://github.com/futzu/threefive/blob/master/superkabuki.md)\n\n\n# M3uFu\nThe Most Advanced M3U8 Parser Available.\n## Latest Version `v0.0.87`  __Critical Update__\n* TagParser update to handle tags without values.\n\n### `Features:`\n* All HLS Tags are Supported.\n* Private / Custom Tags are Supported.\n* Master Playlists are Supported.\n* HTTP(S), Multicast,UDP, and File Source URIs are Supported.\n* Full 2022 SCTE-35 Support. \n* Base64, Bytes, and Hex formated SCTE-35 Cues are Supported.\n* Automatic Decryption of AES Encrypted Segments.\n* Desegmentation. Playlist Segments can be Reassembled into a Single Mpegts File.\n\n\n### `Requires`:\n* python3.6+ or pypy3\n\n### `Install`:\n```smalltalk\npython3 -mpip install  m3ufu\n\n         # and/or \n\npypy3 -mpip install m3ufu\n```\n\n### `Usage`:\n```lua\nusage: m3ufu [-h] [-i INPUT] [-o OUTFILE] [-v] [-d]\n\noptional arguments:\n\n -h, --help            show this help message and exit\n \n -i INPUT, --input INPUT\n                        Input source, like \"/home/a/vid.ts\" or \n                        \"udp://@235.35.3.5:3535\" or \"https://futzu.com/xaa.ts\"\n\n-o OUTFILE, --outfile OUTFILE\n                        download and reassemble segments and write to outfile.\n                        SCTE35 cues are written to sidecar.txt\n\n-v, --version         Show version\n\n-d, --debug           Enable debug output.\n\n\n```\n\n### `Automatic AES Decryption`\n* When m3ufu detects AES-128,  it automatically decrypts the segment\n  * This is used:\n     * to read PTS from the segment\n     * desegmenting a playlist and combining them into a single mpegts file\n\n### `Output`:\n* Returns JSON \n```smalltalk\n{\n    \"headers\": {\n        \"#EXTM3U\": \"\",\n        \"#EXT-X-VERSION\": \"3\",\n        \"#EXT-X-TARGETDURATION\": \"12\",\n        \"#EXT-X-MEDIA-SEQUENCE\": \"1\",\n        \"#EXT-X-PLAYLIST-TYPE\": \"VOD\"\n    },\n    \"media\": [\n        {\n            \"media\": \"file_60p_1_00001.ts\",\n            \"end\": 10.0,\n            \"duration\": 10.0,\n            \"tags\": {\n                \"#EXTINF\": 10.0\n            }\n        },\n```\n### `SCTE-35`\n* SCTE-35 Cues are parsed and the data is included\n```\n        {\n            \"media\": \"seg70.ts\",\n            \"start\": 147.157,\n            \"end\": 148.058,\n            \"duration\": 0.901,\n            \"cue\": \"/DAlAAAAAAAAAAAAFAUAAABXf+//iNg15n4Ae97wAAECAQAAtBIorQ==\",\n            \"cue_data\": {\n                \"info_section\": {\n                    \"table_id\": \"0xfc\",\n                    \"section_syntax_indicator\": false,\n                    \"private\": false,\n                    \"sap_type\": \"0x3\",\n                    \"sap_details\": \"No Sap Type\",\n                    \"section_length\": 37,\n                    \"protocol_version\": 0,\n                    \"encrypted_packet\": false,\n                    \"encryption_algorithm\": 0,\n                    \"pts_adjustment_ticks\": 0,\n                    \"pts_adjustment\": 0.0,\n                    \"cw_index\": \"0x0\",\n                    \"tier\": \"0x0\",\n                    \"splice_command_length\": 20,\n                    \"splice_command_type\": 5,\n                    \"descriptor_loop_length\": 0,\n                    \"crc\": \"0xb41228ad\"\n                },\n                \"command\": {\n                    \"command_length\": 20,\n                    \"command_type\": 5,\n                    \"name\": \"Splice Insert\",\n                    \"time_specified_flag\": true,\n                    \"pts_time\": 73231.536067,\n                    \"pts_time_ticks\": 6590838246,\n                    \"break_auto_return\": false,\n                    \"break_duration\": 90.2,\n                    \"break_duration_ticks\": 8118000,\n                    \"splice_event_id\": 87,\n                    \"splice_event_cancel_indicator\": false,\n                    \"out_of_network_indicator\": true,\n                    \"program_splice_flag\": true,\n                    \"duration_flag\": true,\n                    \"splice_immediate_flag\": false,\n                    \"unique_program_id\": 1,\n                    \"avail_num\": 2,\n                    \"avail_expected\": 1\n                },\n                \"descriptors\": []\n            },\n            \"tags\": {\n                \"#EXT-X-SCTE35\": {\n                    \"CUE-OUT\": \"YES\",\n                    \"CUE\": \"/DAlAAAAAAAAAAAAFAUAAABXf+//iNg15n4Ae97wAAECAQAAtBIorQ==\"\n                },\n                \"#EXTINF\": 0.901\n            }\n        },\n\n....\n```\n\n###  __Master Playlists are also Supported__\n\n```smalltalk\na@fumatica:~/m3u8fu$ pypy3  m3ufu.py ../threefive/master.m3u8 \n{\n    \"headers\": {\n        \"#EXTM3U\": \"\",\n        \"#EXT-X-INDEPENDENT-SEGMENTS\": \"\",\n        \"#EXT-X-VERSION\": \"7\"\n    },\n    \"media\": [\n        {\n            \"media\": \"media-4/stream.m3u8\",\n            \"tags\": {\n                \"#EXT-X-MEDIA\": {\n                    \"AUTOSELECT\": \"YES\",\n                    \"DEFAULT\": \"YES\",\n                    \"LANGUAGE\": \"en\",\n                    \"NAME\": \"CC1\",\n                    \"GROUP-ID\": \"text\",\n                    \"INSTREAM-ID\": \"CC1\",\n                    \"TYPE\": \"CLOSED-CAPTIONS\"\n                },\n                \"#EXT-X-STREAM-INF\": {\n                    \"CLOSED-CAPTIONS\": \"text\",\n                    \"RESOLUTION\": \"768x432\",\n                    \"CODECS\": \"avc1.4D401F,mp4a.40.2\",\n                    \"BANDWIDTH\": 2127786,\n                    \"AVERAGE-BANDWIDTH\": 2030321\n                }\n            }\n        },\n        {\n            \"media\": \"media-1/stream.m3u8\",\n            \"tags\": {\n                \"#EXT-X-STREAM-INF\": {\n                    \"CLOSED-CAPTIONS\": \"text\",\n                    \"RESOLUTION\": \"416x234\",\n                    \"CODECS\": \"avc1.4D400D,mp4a.40.2\",\n                    \"BANDWIDTH\": 410181,\n                    \"AVERAGE-BANDWIDTH\": 393177\n                }\n            }\n        },\n        {\n            \"media\": \"media-2/stream.m3u8\",\n            \"tags\": {\n                \"#EXT-X-STREAM-INF\": {\n                    \"CLOSED-CAPTIONS\": \"text\",\n                    \"RESOLUTION\": \"416x234\",\n                    \"CODECS\": \"avc1.4D400D,mp4a.40.2\",\n                    \"BANDWIDTH\": 727459,\n                    \"AVERAGE-BANDWIDTH\": 698361\n                }\n            }\n        },\n        {\n            \"media\": \"media-3/stream.m3u8\",\n            \"tags\": {\n                \"#EXT-X-STREAM-INF\": {\n                    \"CLOSED-CAPTIONS\": \"text\",\n                    \"RESOLUTION\": \"640x360\",\n                    \"CODECS\": \"avc1.4D401E,mp4a.40.2\",\n                    \"BANDWIDTH\": 1263349,\n                    \"AVERAGE-BANDWIDTH\": 1210676\n                }\n            }\n        },\n```\n* __Even Master Playlists of iframe Playlists are Supported__.\n```\n        {\n            \"media\": \"media-1/iframes.m3u8\",\n            \"tags\": {\n                \"#EXT-X-I-FRAME-STREAM-INF\": {\n                    \"URI\": \"media-1/iframes.m3u8\",\n                    \"RESOLUTION\": \"416x234\",\n                    \"CODECS\": \"avc1.4D400D\",\n                    \"BANDWIDTH\": 360599,\n                    \"AVERAGE-BANDWIDTH\": 64059\n                }\n            }\n        },\n        {\n            \"media\": \"media-2/iframes.m3u8\",\n            \"tags\": {\n                \"#EXT-X-I-FRAME-STREAM-INF\": {\n                    \"URI\": \"media-2/iframes.m3u8\",\n                    \"RESOLUTION\": \"416x234\",\n                    \"CODECS\": \"avc1.4D400D\",\n                    \"BANDWIDTH\": 631048,\n                    \"AVERAGE-BANDWIDTH\": 121087\n                }\n            }\n        },\n        {\n            \"media\": \"media-3/iframes.m3u8\",\n            \"tags\": {\n                \"#EXT-X-I-FRAME-STREAM-INF\": {\n                    \"URI\": \"media-3/iframes.m3u8\",\n                    \"RESOLUTION\": \"640x360\",\n                    \"CODECS\": \"avc1.4D401E\",\n                    \"BANDWIDTH\": 1171948,\n                    \"AVERAGE-BANDWIDTH\": 223837\n                }\n            }\n        },\n        {\n            \"media\": \"media-4/iframes.m3u8\",\n            \"tags\": {\n                \"#EXT-X-I-FRAME-STREAM-INF\": {\n                    \"URI\": \"media-4/iframes.m3u8\",\n                    \"RESOLUTION\": \"768x432\",\n                    \"CODECS\": \"avc1.4D401F\",\n                    \"BANDWIDTH\": 1752287,\n                    \"AVERAGE-BANDWIDTH\": 354946\n                }\n            }\n        },\n        {\n            \"media\": \"media-5/iframes.m3u8\",\n            \"tags\": {\n                \"#EXT-X-I-FRAME-STREAM-INF\": {\n                    \"URI\": \"media-5/iframes.m3u8\",\n                    \"RESOLUTION\": \"960x540\",\n                    \"CODECS\": \"avc1.4D401F\",\n                    \"BANDWIDTH\": 2343896,\n                    \"AVERAGE-BANDWIDTH\": 440896\n                }\n            }\n        },\n \n```\n![image](https://user-images.githubusercontent.com/52701496/203175735-d2f7c6b9-f45a-4e2b-9c81-86babc28576e.png)\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "M3U8 Parser with SCTE-35 Support",
    "version": "0.0.87",
    "project_urls": {
        "Homepage": "https://github.com/futzu/m3u8fu"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6668546c04b656ac36cd5d129051e017b3ffb978a0918c3266c3ead0df7879a3",
                "md5": "1ac2e74cf4776102d0034f991b7caff6",
                "sha256": "9db93e3959c966a8f628af59460c5099aa84af387b81312a8af8d979941a7749"
            },
            "downloads": -1,
            "filename": "m3ufu-0.0.87-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1ac2e74cf4776102d0034f991b7caff6",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 8770,
            "upload_time": "2024-01-23T05:37:18",
            "upload_time_iso_8601": "2024-01-23T05:37:18.408642Z",
            "url": "https://files.pythonhosted.org/packages/66/68/546c04b656ac36cd5d129051e017b3ffb978a0918c3266c3ead0df7879a3/m3ufu-0.0.87-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "82b02cab72569ecd5e7c2b7d11c039c6e134c3167d9d241b071d8fc1095bb033",
                "md5": "066ed92667a6dbade5abc93be4c1114f",
                "sha256": "713b24fdae6bcb13160e179801026ea9e86f67349eade1a8942ae98411b8359f"
            },
            "downloads": -1,
            "filename": "m3ufu-0.0.87.tar.gz",
            "has_sig": false,
            "md5_digest": "066ed92667a6dbade5abc93be4c1114f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 8682,
            "upload_time": "2024-01-23T05:37:20",
            "upload_time_iso_8601": "2024-01-23T05:37:20.261867Z",
            "url": "https://files.pythonhosted.org/packages/82/b0/2cab72569ecd5e7c2b7d11c039c6e134c3167d9d241b071d8fc1095bb033/m3ufu-0.0.87.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-23 05:37:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "futzu",
    "github_project": "m3u8fu",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "m3ufu"
}
        
Elapsed time: 0.20005s