Repository: streamlink/streamlink

Issue:
How to avoid "Input is not padded or padding is corrupt" error?
<!--
Thanks for reporting a bug!
USE THE TEMPLATE. Otherwise your bug report may be rejected.

First, see the contribution guidelines:
https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink

Also check the list of open and closed bug reports:
https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22bug%22

Please see the text preview to avoid unnecessary formatting errors.
-->


## Bug Report

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a bug report and I have read the contribution guidelines.


### Description

<!-- Explain the bug as thoroughly as you can. Don't leave out information which is necessary for us to reproduce and debug this issue. -->

Sometimes, on streams that involve some kind of decryption, I get a `streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of xxx`

Whenever this happens, streamlink completely stalls until it reaches the timeout value, and then it just quits. This is very frustrating as this is not reproducible, and I have no idea how it is going to happen or when it is going to happen. In some cases, I can be recording the same exact same stream in two different commands running at the same time, and one will quit and the other will keep recording. In the case of downloading a replay of a stream, I can just restart the download and streamlink always gets past the point where it crashed previously with no issue.

What I would like to know is how I can avoid this error. For example if the error comes up, how can I force streamlink to try redownload/redecrypt the segment?

### Expected / Actual behavior

Streamlink downloads the stream with no issues.

### Reproduction steps / Explicit stream URLs to test

<!-- How can we reproduce this? Please note the exact steps below using the list format supplied. If you need more steps please add them. -->

NA. The stream needs to have some sort of encryption. I have received this error across Fox Sports Go streams, ESPN+ streams, and live streams of Turner websites (TNT/TBS).

### Log output

<!--
TEXT LOG OUTPUT IS REQUIRED for a bug report!
Use the `--loglevel debug` parameter and avoid using parameters which suppress log output.
https://streamlink.github.io/cli.html#cmdoption-l

Make sure to **remove usernames and passwords**
You can copy the output to https://gist.github.com/ or paste it below.
-->

```
streamlink 'hlsvariant://https://turnerlive.akamaized.net/hls/live/572100/true/aes_slate/de/master.m3u8?hdnts=exp=1553034983~acl=/hls/live/572100/true/*!/hls/live/572100-b/true/*!/hls/live/630682/true/*!/hls/live/630682-b/true/*~id=c5c9ce531e437434c07dc7ff65b0ab94~hmac=112e16086c033e16ffcb3b487ff24f3f4f6626ccc2c57f0be36a60f30d269aee' best -o trutv.ts
[cli][info] Found matching plugin hls for URL hlsvariant://https://turnerlive.akamaized.net/hls/live/572100/true/aes_slate/de/master.m3u8?hdnts=exp=1553034983~acl=/hls/live/572100/true/*!/hls/live/572100-b/true/*!/hls/live/630682/true/*!/hls/live/630682-b/true/*~id=c5c9ce531e437434c07dc7ff65b0ab94~hmac=112e16086c033e16ffcb3b487ff24f3f4f6626ccc2c57f0be36a60f30d269aee
[cli][info] Available streams: 360p_alt2 (worst), 360p_alt, 360p, 480p_alt, 480p, 540p_alt, 540p, 720p_alt, 720p (best)
[cli][info] Opening stream: 720p (hls)                                                                                                                                              [download][trutv.ts] Written 763.8 MB (28m49s @ 424.4 KB/s)                                                                                                                                               Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/segmented.py", line 167, in run
    self.write(segment, result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 140, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 31, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 156

error: Error when reading from stream: Read timeout, exiting
[cli][info] Stream ended
[cli][info] Closing currently open stream...
```
How to avoid "Input is not padded or padding is corrupt" error?
<!--
Thanks for reporting a bug!
USE THE TEMPLATE. Otherwise your bug report may be rejected.

First, see the contribution guidelines:
https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink

Also check the list of open and closed bug reports:
https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22bug%22

Please see the text preview to avoid unnecessary formatting errors.
-->


## Bug Report

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a bug report and I have read the contribution guidelines.


### Description

<!-- Explain the bug as thoroughly as you can. Don't leave out information which is necessary for us to reproduce and debug this issue. -->

Sometimes, on streams that involve some kind of decryption, I get a `streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of xxx`

Whenever this happens, streamlink completely stalls until it reaches the timeout value, and then it just quits. This is very frustrating as this is not reproducible, and I have no idea how it is going to happen or when it is going to happen. In some cases, I can be recording the same exact same stream in two different commands running at the same time, and one will quit and the other will keep recording. In the case of downloading a replay of a stream, I can just restart the download and streamlink always gets past the point where it crashed previously with no issue.

What I would like to know is how I can avoid this error. For example if the error comes up, how can I force streamlink to try redownload/redecrypt the segment?

### Expected / Actual behavior

Streamlink downloads the stream with no issues.

### Reproduction steps / Explicit stream URLs to test

<!-- How can we reproduce this? Please note the exact steps below using the list format supplied. If you need more steps please add them. -->

NA. The stream needs to have some sort of encryption. I have received this error across Fox Sports Go streams, ESPN+ streams, and live streams of Turner websites (TNT/TBS).

### Log output

<!--
TEXT LOG OUTPUT IS REQUIRED for a bug report!
Use the `--loglevel debug` parameter and avoid using parameters which suppress log output.
https://streamlink.github.io/cli.html#cmdoption-l

Make sure to **remove usernames and passwords**
You can copy the output to https://gist.github.com/ or paste it below.
-->

```
streamlink 'hlsvariant://https://turnerlive.akamaized.net/hls/live/572100/true/aes_slate/de/master.m3u8?hdnts=exp=1553034983~acl=/hls/live/572100/true/*!/hls/live/572100-b/true/*!/hls/live/630682/true/*!/hls/live/630682-b/true/*~id=c5c9ce531e437434c07dc7ff65b0ab94~hmac=112e16086c033e16ffcb3b487ff24f3f4f6626ccc2c57f0be36a60f30d269aee' best -o trutv.ts
[cli][info] Found matching plugin hls for URL hlsvariant://https://turnerlive.akamaized.net/hls/live/572100/true/aes_slate/de/master.m3u8?hdnts=exp=1553034983~acl=/hls/live/572100/true/*!/hls/live/572100-b/true/*!/hls/live/630682/true/*!/hls/live/630682-b/true/*~id=c5c9ce531e437434c07dc7ff65b0ab94~hmac=112e16086c033e16ffcb3b487ff24f3f4f6626ccc2c57f0be36a60f30d269aee
[cli][info] Available streams: 360p_alt2 (worst), 360p_alt, 360p, 480p_alt, 480p, 540p_alt, 540p, 720p_alt, 720p (best)
[cli][info] Opening stream: 720p (hls)                                                                                                                                              [download][trutv.ts] Written 763.8 MB (28m49s @ 424.4 KB/s)                                                                                                                                               Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/segmented.py", line 167, in run
    self.write(segment, result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 140, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 31, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 156

error: Error when reading from stream: Read timeout, exiting
[cli][info] Stream ended
[cli][info] Closing currently open stream...
```


Discussion:
Any chance you can recreate this issue with debug logging enabled (`-l debug`)? 
I can try... to be honest the error rate is pretty low (maybe 1 in 25?) and like I said, I have no idea when it's going to show up. I'll just run streamlink on debug from now on though and update if it comes up!
Hey, I just now got back on this... but here's the log:

```
airbears2-10-142-27-169:streams isaac$ streamlink --http-cookie "access_token=eyJhbGciOiJIUzI1NiJ9.eyJpcGlkIjoiaWFwUmVjZWlwdERldmljZTpEZXZpY2U6Nzk0YmFlMTAtYTdjYy0xMWU4LWFmYWYtODMxYTg4NTMxM2Y3OjNlMGY2YWQwLTE4ZTAtNDQzOS04MzYwLWUyODlhYzMyMGZiZiIsImNsaWVudElkIjoiZm94c3BvcnRzZ28tdjEuMC4wIiwicGNfbWF4X3JhdGluZ19tb3ZpZSI6IiIsImNvbnRleHQiOnt9LCJ2ZXJpZmljYXRpb25MZXZlbCI6MCwiZXhwIjoxNTQzMTc5NDQ0LCJ0eXBlIjoiVXNlciIsImlhdCI6MTU0MDU4NzQ0NywidXNlcmlkIjoiMzExMjU2ZTAtZDIzZC00NGVhLWIxMTAtZDdmOWQ1MzcxZmRjLTM1NjQzNS0xZjlmMjdlNDBiOWQzMWVjNTg1M2MyYjk3MmQ0ZjhmYzFiZDNhZDEzIiwidmVyc2lvbiI6InYxLjAiLCJwY19tYXhfcmF0aW5nX3R2IjoiIn0.pME0fTZZSG4YW49EoAW9litm_IciS1mDdKva1Z8z1rQ" --http-cookie "Authorization=eyJraWQiOiJ2MS4wIiwiYWxnIjoiSFMyNTYifQ.eyJpcGlkIjoiaWFwUmVjZWlwdERldmljZTpEZXZpY2U6NGRmNDBhODAtMzhhMS0xMWU5LThhN2UtNTlhOThjYzY4NTg2OmYwMTRjYmNmLWZiNDEtNDE4MC1hMmNkLWM5Mjk5MTAzMDQxYyIsImNsaWVudElkIjoic2Vzc2lvbi1zZXJ2aWNlLXYxLjAiLCJjb250ZXh0Ijp7ImlkIjoiMzZiMmJlNjAtNmRkYi0xMWU5LTk0ODAtMGEzNDBhMmM3MTE0IiwidHlwZSI6IlJFR0lTVEVSRUQiLCJpcF9hZGRyZXNzIjoiMTM2LjE1Mi4xNDMuMjUiLCJkZXZpY2UiOnsiaWQiOiJleUpoYkdjaU9pSklVekkxTmlKOS5leUpwY0dsa0lqb2lhV0Z3VW1WalpXbHdkRVJsZG1salpUcEVaWFpwWTJVNk5HUm1OREJoT0RBdE16aGhNUzB4TVdVNUxUaGhOMlV0TlRsaE9UaGpZelk0TlRnMk9tWXdNVFJqWW1ObUxXWmlOREV0TkRFNE1DMWhNbU5rTFdNNU1qazVNVEF6TURReFl5SXNJbU5zYVdWdWRFbGtJam9pWm05NGMzQnZjblJ6WjI4dGRqRXVNQzR3SWl3aWNHTmZiV0Y0WDNKaGRHbHVaMTl0YjNacFpTSTZJaUlzSW1OdmJuUmxlSFFpT250OUxDSjJaWEpwWm1sallYUnBiMjVNWlhabGJDSTZNQ3dpWlhod0lqb3hOVFUzTXpRME1qZzBMQ0owZVhCbElqb2lWWE5sY2lJc0ltbGhkQ0k2TVRVMU5EYzFNakk0Tnl3aWRYTmxjbWxrSWpvaU16RXhNalUyWlRBdFpESXpaQzAwTkdWaExXSXhNVEF0WkRkbU9XUTFNemN4Wm1SakxUTTFOalF6TlMweFpqbG1NamRsTkRCaU9XUXpNV1ZqTlRnMU0yTXlZamszTW1RMFpqaG1ZekZpWkROaFpERXpJaXdpZG1WeWMybHZiaUk2SW5ZeExqQWlMQ0p3WTE5dFlYaGZjbUYwYVc1blgzUjJJam9pSW4wLjBBSHRjdUdTNlFLQkozbV9OQlBhbTV1cFZuSTRpcFdsUnhKXzFYdU1GMXMiLCJwbGF0Zm9ybSI6IndlYiJ9LCJ1c2VyIjp7ImlkIjoiMzExMjU2ZTAtZDIzZC00NGVhLWIxMTAtZDdmOWQ1MzcxZmRjLTM1NjQzNS0xZjlmMjdlNDBiOWQzMWVjNTg1M2MyYjk3MmQ0ZjhmYzFiZDNhZDEzIiwiaXBpZCI6ImlhcFJlY2VpcHREZXZpY2U6RGV2aWNlOjRkZjQwYTgwLTM4YTEtMTFlOS04YTdlLTU5YTk4Y2M2ODU4NjpmMDE0Y2JjZi1mYjQxLTQxODAtYTJjZC1jOTI5OTEwMzA0MWMiLCJiaWxsaW5nX2xvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiMDcwNDAifSwicmVnaXN0cmF0aW9uIjp7ImF1dGhfcHJvdmlkZXIiOiJWZXJpem9uIiwiZW50aXRsZW1lbnRzIjpbImZveGRlcCIsImZiYy1mb3giLCJ5ZXMiLCJmY3MiLCJmczEiLCJmczIiXSwiZXhwaXJlc19vbiI6IjIwMTktMDUtMjFUMDA6MTI6MzQuMDAwKzAwMDAifX0sImdlbmVyYXRlZF9vbiI6IjIwMTktMDUtMDNUMTk6Mzk6NDkuNDQ2KzAwMDAiLCJ1cGRhdGVkX29uIjoiMjAxOS0wNS0wM1QxOTozOTo0OS40NDYrMDAwMCIsImV4cGlyZXNfb24iOiIyMDE5LTA1LTAzVDIzOjM5OjQ5LjQ0NiswMDAwIiwiYXZhaWxhYmxlX2NvbnRlbnQiOnsibmF0aW9uYWwiOnsiY2FsbF9zaWducyI6WyJCR1RFTk8yIiwiQkdURU5PMyIsIkJHVEVOTzQiLCJCSUdURU4iLCJGUzEiLCJGUzIiLCJGWERFUCIsIkZDU0EiLCJGQ1NDIiwiRkNTUCJdfSwiZ2VvIjp7ImxvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiOTQ3MjAiLCJjb3VudHJ5X2NvZGUiOiJ1cyJ9LCJyc25fY2hhbm5lbF9ncm91cHMiOlsiIl0sInJzbl9jYWxsX3NpZ25zIjpbIiJdLCJhZmZpbGlhdGVfY2FsbF9zaWducyI6WyJLVFZVIl19LCJob21lIjp7ImxvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiMDcwNDAifSwicnNuX2NoYW5uZWxfZ3JvdXBzIjpbInllcyJdLCJyc25fY2FsbF9zaWducyI6WyJZRVMiXSwiYWZmaWxpYXRlX2NhbGxfc2lnbnMiOlsiV05ZVyJdLCJ0ZWFtcyI6W3siaWQiOiJhNTM4ZmZhZi0yODc4LTQ2MDEtOGQ4Yy01OTg1NzNhYTMwMWEiLCJuYW1lIjoiQnJvb2tseW4gTmV0cyIsInNwb3J0IjoiTkJBIn0seyJpZCI6IjM1MDNhZTUxLWJiM2YtNDc3My1hODE4LWIzNWFiYjc3NjJiMyIsIm5hbWUiOiJOZXcgWW9yayBZYW5rZWVzIiwic3BvcnQiOiJNTEIifV19fSwicGFydG5lciI6eyJuYW1lIjoiZm94c3BvcnRzIn19LCJpcEFkZHJlc3MiOiIxMzYuMTUyLjE0My4yNSIsImV4cCI6MTU1NjkyNjc4OSwidHlwZSI6IlVzZXIiLCJ1c2VyaWQiOiIzMTEyNTZlMC1kMjNkLTQ0ZWEtYjExMC1kN2Y5ZDUzNzFmZGMtMzU2NDM1LTFmOWYyN2U0MGI5ZDMxZWM1ODUzYzJiOTcyZDRmOGZjMWJkM2FkMTMiLCJpYXQiOjE1NTY5MTIzODksInZlcnNpb24iOiJ2MS4wIn0.qxPYSK5Kk8u1Eufdlns-k9YZ4npIgVHcZd4L4rI1pVk" --hls-segment-timeout 1000 --hls-timeout 1000 "hlsvariant://http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8" best --hls-live-restart -l debug -o mainz.ts
[cli][debug] OS:         macOS 10.14.4
[cli][debug] Python:     3.7.0
[cli][debug] Streamlink: 1.0.0
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.53.0)
[cli][info] Found matching plugin hls for URL hlsvariant://http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8
[plugin.hls][debug] URL=http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8; params={}
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: 224p (worst), 288p, 360p, 504p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] Segments in this playlist are encrypted
[stream.hls][debug] First Sequence: 0; Last Sequence: 1187
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 0; End Sequence: None
[stream.hls][debug] Adding segment 0 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 1 to queue
[stream.hls][debug] Adding segment 2 to queue
[stream.hls][debug] Adding segment 3 to queue
[stream.hls][debug] Adding segment 4 to queue
[stream.hls][debug] Adding segment 5 to queue
[stream.hls][debug] Adding segment 6 to queue
[stream.hls][debug] Adding segment 7 to queue
[stream.hls][debug] Adding segment 8 to queue
[stream.hls][debug] Adding segment 9 to queue
[stream.hls][debug] Adding segment 10 to queue
[stream.hls][debug] Adding segment 11 to queue
[stream.hls][debug] Adding segment 12 to queue
[stream.hls][debug] Adding segment 13 to queue
[stream.hls][debug] Adding segment 14 to queue
[stream.hls][debug] Adding segment 15 to queue
[stream.hls][debug] Adding segment 16 to queue
[stream.hls][debug] Adding segment 17 to queue
[stream.hls][debug] Adding segment 18 to queue
[stream.hls][debug] Adding segment 19 to queue
[stream.hls][debug] Adding segment 20 to queue
[stream.hls][debug] Adding segment 21 to queue
[stream.hls][debug] Download of segment 0 complete
[cli][debug] Checking file output
[stream.hls][debug] Adding segment 22 to queue
File mainz.ts already exists! Overwrite it? [y/N] [stream.hls][debug] Download of segment 1 complete
[stream.hls][debug] Adding segment 23 to queue
[stream.hls][debug] Download of segment 2 complete

...

[download][mainz.ts] Written 1.49 GB (3m55s @ 1.5 MB/s)[stream.hls][debug] Adding segment 727 to queue
                                                                                                                [stream.hls][debug] Download of segment 706 complete
[stream.hls][debug] Adding segment 728 to queue
[download][mainz.ts] Written 1.50 GB (3m56s @ 1.4 MB/s)                                                                                                                [stream.hls][debug] Download of segment 707 complete
[download][mainz.ts] Written 1.50 GB (3m58s @ 1.6 MB/s)[stream.hls][debug] Adding segment 729 to queue
                                                                                                                [stream.hls][debug] Download of segment 708 complete
[stream.hls][debug] Adding segment 730 to queue
[download][mainz.ts] Written 1.50 GB (3m59s @ 1.6 MB/s)                                                                                                                [stream.hls][debug] Download of segment 709 complete
[stream.hls][debug] Adding segment 731 to queue
[download][mainz.ts] Written 1.50 GB (4m1s @ 1.7 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 710 complete
[stream.hls][debug] Adding segment 732 to queue
[download][mainz.ts] Written 1.51 GB (4m2s @ 1.6 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 711 complete
[stream.hls][debug] Adding segment 733 to queue
[download][mainz.ts] Written 1.51 GB (4m4s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 712 complete
[stream.hls][debug] Adding segment 734 to queue
[download][mainz.ts] Written 1.51 GB (4m5s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 713 complete
[stream.hls][debug] Adding segment 735 to queue
[download][mainz.ts] Written 1.51 GB (4m6s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 714 complete
[stream.hls][debug] Adding segment 736 to queue
[download][mainz.ts] Written 1.51 GB (4m8s @ 1.4 MB/s)                                                                                                                 [stream.hls][debug] Cutting off 12 bytes of garbage before decrypting
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/segmented.py", line 167, in run
    self.write(segment, result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 140, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 31, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 225

^C[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
Interrupted! Exiting...
[cli][info] Closing currently open stream...
```
@beardypig  just noticed this is the exact same issue as reported here https://github.com/streamlink/streamlink/issues/2631

If it helps. Just got this error again on cnngo. I was trying to save some episodes of a program.

> [cli][debug] OS:         Windows 7
> [cli][debug] Python:     3.6.6
> [cli][debug] Streamlink: 1.2.0+22.g6ac9ee0
> [cli][debug] Requests(2.22.0), Socks(1.7.1), Websocket(0.56.0)
> [cli][info] Found matching plugin hls for URL https://phls-vod.cdn.turner.com/cnnngtv/cnn/hls/2019/09/22/urn:ngtv-show:119744/index.m3u8?hdnts=exp=1570445287~acl=/cnnngtv/cnn/hls/2019/*~id=fe3ad43531e3cd8b66ff7118c70b8913~hmac=015a4876ea09d0833904f5bcedd0a06c3bca515a42fa40c1a1d267d39df7094d
> [plugin.hls][debug] URL=https://phls-vod.cdn.turner.com/cnnngtv/cnn/hls/2019/09/22/urn:ngtv-show:119744/index.m3u8?hdnts=exp=1570445287~acl=/cnnngtv/cnn/hls/2019/*~id=fe3ad43531e3cd8b66ff7118c70b8913~hmac=015a4876ea09d0833904f5bcedd0a06c3bca515a42fa40c1a1d267d39df7094d; params={}
> [cli][info] Available streams: 70k (worst), 360p_alt, 360p (best), 540p_alt, 540p, 720p
> [cli][info] Opening stream: 360p (hls)
> [stream.hls][debug] Reloading playlist
> [stream.hls][debug] Segments in this playlist are encrypted
> [stream.hls][debug] First Sequence: 1; Last Sequence: 377
> [stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 1; End Sequence: 377
> [stream.hls][debug] Adding segment 1 to queue
> [cli][debug] Pre-buffering 8192 bytes
> [stream.hls][debug] Adding segment 2 to queue
> [stream.hls][debug] Adding segment 3 to queue
> [stream.hls][debug] Adding segment 4 to queue
> [stream.hls][debug] Adding segment 5 to queue
> [stream.hls][debug] Adding segment 6 to queue
> [stream.hls][debug] Adding segment 7 to queue
> [stream.hls][debug] Adding segment 8 to queue
> [stream.hls][debug] Adding segment 9 to queue
> [stream.hls][debug] Adding segment 10 to queue
> [stream.hls][debug] Adding segment 11 to queue
> [stream.hls][debug] Adding segment 12 to queue
> [stream.hls][debug] Adding segment 13 to queue
> [stream.hls][debug] Adding segment 14 to queue
> [stream.hls][debug] Adding segment 15 to queue
> [stream.hls][debug] Adding segment 16 to queue
> [stream.hls][debug] Adding segment 17 to queue
> [stream.hls][debug] Adding segment 18 to queue
> [stream.hls][debug] Adding segment 19 to queue
> [stream.hls][debug] Adding segment 20 to queue
> [stream.hls][debug] Adding segment 21 to queue
> [stream.hls][debug] Adding segment 22 to queue
> [stream.hls][debug] Download of segment 1 complete
> [cli][debug] Checking file output
> [cli][debug] Writing stream to output
> [stream.hls][debug] Adding segment 23 to queue
> [stream.hls][debug] Download of segment 2 complete
> [stream.hls][debug] Adding segment 24 to queue
> Exception in thread Thread-HLSStreamWriter:
> Traceback (most recent call last):
>   File "threading.py", line 916, in _bootstrap_inner
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
>     self.write(segment, result)
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 141, in write
>     self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 31, in pkcs7_decode
>     raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
> streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 99
> 
> error: Error when reading from stream: Read timeout, exiting
> [stream.segmented][debug] Closing worker thread
> [stream.segmented][debug] Closing writer thread
> [cli][info] Stream ended
> [cli][info] Closing currently open stream...

A couple of streams worked. Another (this one above), didn't. Exactly same platform. This error is very random, but it seems like it may pop up across various different sites. 
I'll chime in here and say that I'm seeing the SAME EXACT thing.

Please don't close this as "too difficult to reproduce".  This is a CORE FUNCTION of streamlink, and it is not woking.  closing as too difficult to reproduce is dodging a major issue.

What streamlink needs to do if it can't (for some reason) download a queued packet is retry the packet.  It's what every single player in the world does, why can't streamlink as well?
@sou7611 It's been open for a year, what exactly is your concern of it being closed? The other was closed because it's a duplicate of this issue. Regarding the functionality, if it's so easy to deal with please submit a PR to add the functionality that will address this. These are also on old versions of Streamlink. If it's still happening to you provide debug output and reproduction steps to actually try and solve the problem since based on the tone of your comment it's happening regularly.

An issue that has been reported 4 times in a year is an edge case, if someone wants to work on it they will, otherwise complaining doesn't exactly motivate people to solve a problem that 99.9% of users are not encountering. This is a free open source project, no one is getting paid to work on this, so keep that in mind. People work on whatever aspects they want as little or as much as they want, it's that simple.
Trying to reproduce it to capture said logs.  It happens on a wide variety of services but actually capturing it in action, that's another story.

Like a problem with your car not showing up at the mechanics shop, trying to make this happen on purpose is proving challenging.

Somehow it's clearly getting a packet that's not defined, which screws up the decoding, as it's trying to decode data that's null in length.
FWIW, I'd also suggest the following alteration, if it's desired to not call the decrypt if the data is null, that way you know in the logs if it was triggered :

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

Interesting, something is up with padding as well ... there's a function that cuts off garbage at the end (if the packet isn't an even length of 16) but that apparently either doesn't fix, further damages the packet, or it's just bad to begin with:

stream.hls][debug] Cutting off 15 bytes of garbage before decrypting
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "threading.py", line 916, in _bootstrap_inner
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
    self.write(segment, result)
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 158, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 34, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 38

This also crashes the stream.  It may queue more packets, but it never writes anything past this point.
So here's a question ... does anyone know the history behind the padding%16 cutoff?  It's been in the code since livestreamer in 2014 :

https://github.com/chrippa/livestreamer/commit/c38a543c726f9b207a80836edb09f9ae696f0871

Near as I can tell, you don't get garbage unless you have a corrupted segment, and since a corrupted segment won't decode, you get a null decrypted_chunk, which then crashes the stream.

So far, this seems to maintain the stream without causing errors :

            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

FYI, been running a bunch of repeated capture tests against foxsportsgo, currently the following code block for handling encyrypted chunks seems to be most stable ... this basically just throws out any packet with padded garbage (I've not found a single instance in testing where a packet with padded gargbage truncated to the nearest /16 in size was not corrupted).

            decrypted_chunk = 0
			
            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

I currently get this on maybe 1/8 of my download attempts from Crunchyroll with a valid login. Will start running with debug logging enabled, I've seen it three times so far. If I stream the same content again it usually works the next time. The streams are 1080p usually around 1.5GB in total size, if that means anything.
```
[stream.hls][debug] Adding segment 357 to queue
[stream.hls][debug] Download of segment 336 complete
[stream.hls][debug] Adding segment 358 to queue
[stream.hls][debug] Download of segment 337 complete
[stream.hls][debug] Adding segment 359 to queue
[stream.hls][debug] Download of segment 338 complete
[stream.hls][debug] Adding segment 360 to queue
[stream.hls][debug] Download of segment 339 complete
[stream.hls][debug] Adding segment 361 to queue
[stream.hls][debug] Cutting off 8 bytes of garbage before decrypting
error: Error when reading from stream: Read timeout, exiting
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[cli][info] Closing currently open stream...

Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "threading.py", line 916, in _bootstrap_inner
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
    self.write(segment, result)
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\hls.py", line 157, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\hls.py", line 34, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 196
```
Could you please give #3446 a try and see whether this fixes the input padding issue?
I encountered the exact same bug with the `pluzz` plugin:
```
$ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
[cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
[cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls-multi)
[cli][info] Starting player: /usr/bin/vlc
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
    self.write(segment, result)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 135, in write
    return self._write(sequence, *args, **kwargs)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 166, in _write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 33, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 187
```

I'll try the patch from #3446 but as the issue does not occur consistently, it's hard to know if the issue is really fixed.
I tried #3446 and the issue still happens:
```
$ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
[cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
[cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls-multi)
[cli][info] Starting player: /usr/bin/vlc
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/ffmpeg-355394-340
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
    self.write(segment, result)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 124, in write
    return self._write(sequence, *args, **kwargs)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 147, in _write
    self.reader.buffer.write(unpad(decrypted_chunk, AES.block_size, style="pkcs7"))
  File "/home/adema/.local/lib/python3.9/site-packages/Crypto/Util/Padding.py", line 90, in unpad
    raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.
```

@bastimeyer I am happy to test anything else you can think of :+1: 
If it helps, in the original hls.py. I fixed it completely on my system by
simply commenting out the truncation, and if garbage_len was set, setting
the chunk to a value of 0 prior to checking for garbage. This
basically makes it skip the packet entirely if there's garbage, and keep
going otherwise.

It's a very minimal change, taking advantage of the logic flow already in
place.

The padding error, when it occurs, is triggered by the decryptor.decrypt
command, trying to decrypt a corrupted packet.

Haven't seen any issues at all in captured .ts streams, and it completely
eliminated the padding error.

            data = res.content
            # If the input data is not a multiple of 16, cut off any garbage
            garbage_len = len(data) % 16

            #if garbage_len:
            #    log.debug("Cutting off {0} bytes of garbage "
            #              "before decrypting", garbage_len)
            #    decrypted_chunk = decryptor.decrypt(data[:-garbage_len])

            decrypted_chunk = 0

            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded
garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in
length", sequence.num)


On Thu, Jan 21, 2021 at 2:02 PM Élie ROUDNINSKI <notifications@github.com>
wrote:

> I tried #3446 <https://github.com/streamlink/streamlink/pull/3446> and
> the issue still happens:
>
> $ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
>
> [cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
>
> [cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
>
> [cli][info] Opening stream: 720p (hls-multi)
>
> [cli][info] Starting player: /usr/bin/vlc
>
> [stream.ffmpegmux][error] Pipe copy aborted: /tmp/ffmpeg-355394-340
>
> Exception in thread Thread-HLSStreamWriter:
>
> Traceback (most recent call last):
>
>   File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
>
>     self.run()
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
>
>     self.write(segment, result)
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 124, in write
>
>     return self._write(sequence, *args, **kwargs)
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 147, in _write
>
>     self.reader.buffer.write(unpad(decrypted_chunk, AES.block_size, style="pkcs7"))
>
>   File "/home/adema/.local/lib/python3.9/site-packages/Crypto/Util/Padding.py", line 90, in unpad
>
>     raise ValueError("Padding is incorrect.")
>
> ValueError: Padding is incorrect.
>
>
> @bastimeyer <https://github.com/bastimeyer> I am happy to test anything
> else you can think of 👍
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/streamlink/streamlink/issues/2365#issuecomment-764867882>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABNBVNHSZ4VGA6JA2V4O763S3B25BANCNFSM4G7VONSQ>
> .
>

Would this solution just remove the offending segment from the stream, so those 5, 6, 10, etc. seconds would not be recorded?
I believe so, but I've not seen it cause any issues in recorded video, so
the question is... is that a bad thing?

If we can't record them due to corruption, it may not be an actual loss
with error checks, re-requests, etc.

On Thu, Jan 21, 2021, 5:31 PM ischmidt20 <notifications@github.com> wrote:

> Would this solution just remove the offending segment from the stream, so
> those 5, 6, 10, etc. segments would not be recorded?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/streamlink/streamlink/issues/2365#issuecomment-764983399>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABNBVNHUSSMSYYLJNHUV6BLS3CTL3ANCNFSM4G7VONSQ>
> .
>

> Would this solution just remove the offending segment from the stream

Yes, it would remove these segments and would thus get rid of the error, but that's not the solution we're looking for here.

> ValueError: Padding is incorrect.

https://github.com/Legrandin/pycryptodome/blob/v3.9.9/lib/Crypto/Util/Padding.py#L87-L90
Is there any other idea floating around that I could try?
I think I may have stumbled across the cause of this (or one of them, anyway): it seems that Python's requests/urllib3 libraries do not signal any kind of error if the server closes the connection mid-way through a file (i.e. it does not verify that it received as many bytes as it should have, using the Content-Length header).

The padding is corrupt because it's not padding, it's arbitrary data where the download was truncated.

urllib3 does have an optional keyword argument enforce_content_length=True that can be specified. However, I can't see any way in requests to get that passed on to urllib3.

This has apparently been reported in psf/requests#4956 years ago but there is no developer response in that issue.
Closing since this is an upstream error.
Though the ultimate code bug is upstream, that doesn't mean it's not a real problem for streamlink users, and a workaround wouldn't bring real value to them.
Let's reopen for visibility. However, it is a bug/issue in Streamlink's dependencies, and unfortunately there's no clean way of fixing this here.

----

https://github.com/psf/requests/issues/4956#issuecomment-573325001
> **The fix**
> I think urllib3 should just make `enforce_content_length=True` by default.
> ...
> If urllib3 makes that change, then Requests can simply bump their minimum required urllib3 version to whatever release includes the change, and be done.
> Failing that, Requests should pass `enforce_content_length=True` explicitly.

- https://github.com/psf/requests/blob/v2.25.1/requests/adapters.py#L394
- https://github.com/urllib3/urllib3/blob/1.26.5/src/urllib3/response.py#L185-L187

Since `requests.adapters.HTTPAdapter.send` doesn't allow for custom parameters to be set for `urllib3.response.HTTPResponse`, this means all that could be done in Streamlink is patching out request's import of urllib3's HTTPResponse. This needs to be done in `streamlink.plugin.api.http_session`. Since I haven't run into this issue yet, I can't test this myself.
Any chance you can recreate this issue with debug logging enabled (`-l debug`)? 
I can try... to be honest the error rate is pretty low (maybe 1 in 25?) and like I said, I have no idea when it's going to show up. I'll just run streamlink on debug from now on though and update if it comes up!
Hey, I just now got back on this... but here's the log:

```
airbears2-10-142-27-169:streams isaac$ streamlink --http-cookie "access_token=eyJhbGciOiJIUzI1NiJ9.eyJpcGlkIjoiaWFwUmVjZWlwdERldmljZTpEZXZpY2U6Nzk0YmFlMTAtYTdjYy0xMWU4LWFmYWYtODMxYTg4NTMxM2Y3OjNlMGY2YWQwLTE4ZTAtNDQzOS04MzYwLWUyODlhYzMyMGZiZiIsImNsaWVudElkIjoiZm94c3BvcnRzZ28tdjEuMC4wIiwicGNfbWF4X3JhdGluZ19tb3ZpZSI6IiIsImNvbnRleHQiOnt9LCJ2ZXJpZmljYXRpb25MZXZlbCI6MCwiZXhwIjoxNTQzMTc5NDQ0LCJ0eXBlIjoiVXNlciIsImlhdCI6MTU0MDU4NzQ0NywidXNlcmlkIjoiMzExMjU2ZTAtZDIzZC00NGVhLWIxMTAtZDdmOWQ1MzcxZmRjLTM1NjQzNS0xZjlmMjdlNDBiOWQzMWVjNTg1M2MyYjk3MmQ0ZjhmYzFiZDNhZDEzIiwidmVyc2lvbiI6InYxLjAiLCJwY19tYXhfcmF0aW5nX3R2IjoiIn0.pME0fTZZSG4YW49EoAW9litm_IciS1mDdKva1Z8z1rQ" --http-cookie "Authorization=eyJraWQiOiJ2MS4wIiwiYWxnIjoiSFMyNTYifQ.eyJpcGlkIjoiaWFwUmVjZWlwdERldmljZTpEZXZpY2U6NGRmNDBhODAtMzhhMS0xMWU5LThhN2UtNTlhOThjYzY4NTg2OmYwMTRjYmNmLWZiNDEtNDE4MC1hMmNkLWM5Mjk5MTAzMDQxYyIsImNsaWVudElkIjoic2Vzc2lvbi1zZXJ2aWNlLXYxLjAiLCJjb250ZXh0Ijp7ImlkIjoiMzZiMmJlNjAtNmRkYi0xMWU5LTk0ODAtMGEzNDBhMmM3MTE0IiwidHlwZSI6IlJFR0lTVEVSRUQiLCJpcF9hZGRyZXNzIjoiMTM2LjE1Mi4xNDMuMjUiLCJkZXZpY2UiOnsiaWQiOiJleUpoYkdjaU9pSklVekkxTmlKOS5leUpwY0dsa0lqb2lhV0Z3VW1WalpXbHdkRVJsZG1salpUcEVaWFpwWTJVNk5HUm1OREJoT0RBdE16aGhNUzB4TVdVNUxUaGhOMlV0TlRsaE9UaGpZelk0TlRnMk9tWXdNVFJqWW1ObUxXWmlOREV0TkRFNE1DMWhNbU5rTFdNNU1qazVNVEF6TURReFl5SXNJbU5zYVdWdWRFbGtJam9pWm05NGMzQnZjblJ6WjI4dGRqRXVNQzR3SWl3aWNHTmZiV0Y0WDNKaGRHbHVaMTl0YjNacFpTSTZJaUlzSW1OdmJuUmxlSFFpT250OUxDSjJaWEpwWm1sallYUnBiMjVNWlhabGJDSTZNQ3dpWlhod0lqb3hOVFUzTXpRME1qZzBMQ0owZVhCbElqb2lWWE5sY2lJc0ltbGhkQ0k2TVRVMU5EYzFNakk0Tnl3aWRYTmxjbWxrSWpvaU16RXhNalUyWlRBdFpESXpaQzAwTkdWaExXSXhNVEF0WkRkbU9XUTFNemN4Wm1SakxUTTFOalF6TlMweFpqbG1NamRsTkRCaU9XUXpNV1ZqTlRnMU0yTXlZamszTW1RMFpqaG1ZekZpWkROaFpERXpJaXdpZG1WeWMybHZiaUk2SW5ZeExqQWlMQ0p3WTE5dFlYaGZjbUYwYVc1blgzUjJJam9pSW4wLjBBSHRjdUdTNlFLQkozbV9OQlBhbTV1cFZuSTRpcFdsUnhKXzFYdU1GMXMiLCJwbGF0Zm9ybSI6IndlYiJ9LCJ1c2VyIjp7ImlkIjoiMzExMjU2ZTAtZDIzZC00NGVhLWIxMTAtZDdmOWQ1MzcxZmRjLTM1NjQzNS0xZjlmMjdlNDBiOWQzMWVjNTg1M2MyYjk3MmQ0ZjhmYzFiZDNhZDEzIiwiaXBpZCI6ImlhcFJlY2VpcHREZXZpY2U6RGV2aWNlOjRkZjQwYTgwLTM4YTEtMTFlOS04YTdlLTU5YTk4Y2M2ODU4NjpmMDE0Y2JjZi1mYjQxLTQxODAtYTJjZC1jOTI5OTEwMzA0MWMiLCJiaWxsaW5nX2xvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiMDcwNDAifSwicmVnaXN0cmF0aW9uIjp7ImF1dGhfcHJvdmlkZXIiOiJWZXJpem9uIiwiZW50aXRsZW1lbnRzIjpbImZveGRlcCIsImZiYy1mb3giLCJ5ZXMiLCJmY3MiLCJmczEiLCJmczIiXSwiZXhwaXJlc19vbiI6IjIwMTktMDUtMjFUMDA6MTI6MzQuMDAwKzAwMDAifX0sImdlbmVyYXRlZF9vbiI6IjIwMTktMDUtMDNUMTk6Mzk6NDkuNDQ2KzAwMDAiLCJ1cGRhdGVkX29uIjoiMjAxOS0wNS0wM1QxOTozOTo0OS40NDYrMDAwMCIsImV4cGlyZXNfb24iOiIyMDE5LTA1LTAzVDIzOjM5OjQ5LjQ0NiswMDAwIiwiYXZhaWxhYmxlX2NvbnRlbnQiOnsibmF0aW9uYWwiOnsiY2FsbF9zaWducyI6WyJCR1RFTk8yIiwiQkdURU5PMyIsIkJHVEVOTzQiLCJCSUdURU4iLCJGUzEiLCJGUzIiLCJGWERFUCIsIkZDU0EiLCJGQ1NDIiwiRkNTUCJdfSwiZ2VvIjp7ImxvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiOTQ3MjAiLCJjb3VudHJ5X2NvZGUiOiJ1cyJ9LCJyc25fY2hhbm5lbF9ncm91cHMiOlsiIl0sInJzbl9jYWxsX3NpZ25zIjpbIiJdLCJhZmZpbGlhdGVfY2FsbF9zaWducyI6WyJLVFZVIl19LCJob21lIjp7ImxvY2F0aW9uIjp7InR5cGUiOiJaSVBfQ09ERSIsInppcF9jb2RlIjoiMDcwNDAifSwicnNuX2NoYW5uZWxfZ3JvdXBzIjpbInllcyJdLCJyc25fY2FsbF9zaWducyI6WyJZRVMiXSwiYWZmaWxpYXRlX2NhbGxfc2lnbnMiOlsiV05ZVyJdLCJ0ZWFtcyI6W3siaWQiOiJhNTM4ZmZhZi0yODc4LTQ2MDEtOGQ4Yy01OTg1NzNhYTMwMWEiLCJuYW1lIjoiQnJvb2tseW4gTmV0cyIsInNwb3J0IjoiTkJBIn0seyJpZCI6IjM1MDNhZTUxLWJiM2YtNDc3My1hODE4LWIzNWFiYjc3NjJiMyIsIm5hbWUiOiJOZXcgWW9yayBZYW5rZWVzIiwic3BvcnQiOiJNTEIifV19fSwicGFydG5lciI6eyJuYW1lIjoiZm94c3BvcnRzIn19LCJpcEFkZHJlc3MiOiIxMzYuMTUyLjE0My4yNSIsImV4cCI6MTU1NjkyNjc4OSwidHlwZSI6IlVzZXIiLCJ1c2VyaWQiOiIzMTEyNTZlMC1kMjNkLTQ0ZWEtYjExMC1kN2Y5ZDUzNzFmZGMtMzU2NDM1LTFmOWYyN2U0MGI5ZDMxZWM1ODUzYzJiOTcyZDRmOGZjMWJkM2FkMTMiLCJpYXQiOjE1NTY5MTIzODksInZlcnNpb24iOiJ2MS4wIn0.qxPYSK5Kk8u1Eufdlns-k9YZ4npIgVHcZd4L4rI1pVk" --hls-segment-timeout 1000 --hls-timeout 1000 "hlsvariant://http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8" best --hls-live-restart -l debug -o mainz.ts
[cli][debug] OS:         macOS 10.14.4
[cli][debug] Python:     3.7.0
[cli][debug] Streamlink: 1.0.0
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.53.0)
[cli][info] Found matching plugin hls for URL hlsvariant://http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8
[plugin.hls][debug] URL=http://hlslinear-akc.med2.foxsportsgo.com/hdnts=exp=1556998824~acl=/*~id=311256e0-d23d-44ea-b110-d7f9d5371fdc-356435-1f9f27e40b9d31ec5853c2b972d4f8fc1bd3ad13~hmac=8e7c413013dfec70bab90a3c0d9f5d7b80f074d5a2a70d33da97432074ab03ab/d52f3708ed1c7f367d4012b845a2683b/ls01/foxsports/FOX_SPORTS_2_DUAL_ORIGIN/vod/2019/05/03/73755261/FSG_20190503_FSV_Mainz_05_vs._RB_Leipzig_73755261/master_wired_web_ads.m3u8; params={}
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: 224p (worst), 288p, 360p, 504p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] Segments in this playlist are encrypted
[stream.hls][debug] First Sequence: 0; Last Sequence: 1187
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 0; End Sequence: None
[stream.hls][debug] Adding segment 0 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 1 to queue
[stream.hls][debug] Adding segment 2 to queue
[stream.hls][debug] Adding segment 3 to queue
[stream.hls][debug] Adding segment 4 to queue
[stream.hls][debug] Adding segment 5 to queue
[stream.hls][debug] Adding segment 6 to queue
[stream.hls][debug] Adding segment 7 to queue
[stream.hls][debug] Adding segment 8 to queue
[stream.hls][debug] Adding segment 9 to queue
[stream.hls][debug] Adding segment 10 to queue
[stream.hls][debug] Adding segment 11 to queue
[stream.hls][debug] Adding segment 12 to queue
[stream.hls][debug] Adding segment 13 to queue
[stream.hls][debug] Adding segment 14 to queue
[stream.hls][debug] Adding segment 15 to queue
[stream.hls][debug] Adding segment 16 to queue
[stream.hls][debug] Adding segment 17 to queue
[stream.hls][debug] Adding segment 18 to queue
[stream.hls][debug] Adding segment 19 to queue
[stream.hls][debug] Adding segment 20 to queue
[stream.hls][debug] Adding segment 21 to queue
[stream.hls][debug] Download of segment 0 complete
[cli][debug] Checking file output
[stream.hls][debug] Adding segment 22 to queue
File mainz.ts already exists! Overwrite it? [y/N] [stream.hls][debug] Download of segment 1 complete
[stream.hls][debug] Adding segment 23 to queue
[stream.hls][debug] Download of segment 2 complete

...

[download][mainz.ts] Written 1.49 GB (3m55s @ 1.5 MB/s)[stream.hls][debug] Adding segment 727 to queue
                                                                                                                [stream.hls][debug] Download of segment 706 complete
[stream.hls][debug] Adding segment 728 to queue
[download][mainz.ts] Written 1.50 GB (3m56s @ 1.4 MB/s)                                                                                                                [stream.hls][debug] Download of segment 707 complete
[download][mainz.ts] Written 1.50 GB (3m58s @ 1.6 MB/s)[stream.hls][debug] Adding segment 729 to queue
                                                                                                                [stream.hls][debug] Download of segment 708 complete
[stream.hls][debug] Adding segment 730 to queue
[download][mainz.ts] Written 1.50 GB (3m59s @ 1.6 MB/s)                                                                                                                [stream.hls][debug] Download of segment 709 complete
[stream.hls][debug] Adding segment 731 to queue
[download][mainz.ts] Written 1.50 GB (4m1s @ 1.7 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 710 complete
[stream.hls][debug] Adding segment 732 to queue
[download][mainz.ts] Written 1.51 GB (4m2s @ 1.6 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 711 complete
[stream.hls][debug] Adding segment 733 to queue
[download][mainz.ts] Written 1.51 GB (4m4s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 712 complete
[stream.hls][debug] Adding segment 734 to queue
[download][mainz.ts] Written 1.51 GB (4m5s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 713 complete
[stream.hls][debug] Adding segment 735 to queue
[download][mainz.ts] Written 1.51 GB (4m6s @ 1.5 MB/s)                                                                                                                 [stream.hls][debug] Download of segment 714 complete
[stream.hls][debug] Adding segment 736 to queue
[download][mainz.ts] Written 1.51 GB (4m8s @ 1.4 MB/s)                                                                                                                 [stream.hls][debug] Cutting off 12 bytes of garbage before decrypting
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/segmented.py", line 167, in run
    self.write(segment, result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 140, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/streamlink/stream/hls.py", line 31, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 225

^C[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
Interrupted! Exiting...
[cli][info] Closing currently open stream...
```
@beardypig  just noticed this is the exact same issue as reported here https://github.com/streamlink/streamlink/issues/2631

If it helps. Just got this error again on cnngo. I was trying to save some episodes of a program.

> [cli][debug] OS:         Windows 7
> [cli][debug] Python:     3.6.6
> [cli][debug] Streamlink: 1.2.0+22.g6ac9ee0
> [cli][debug] Requests(2.22.0), Socks(1.7.1), Websocket(0.56.0)
> [cli][info] Found matching plugin hls for URL https://phls-vod.cdn.turner.com/cnnngtv/cnn/hls/2019/09/22/urn:ngtv-show:119744/index.m3u8?hdnts=exp=1570445287~acl=/cnnngtv/cnn/hls/2019/*~id=fe3ad43531e3cd8b66ff7118c70b8913~hmac=015a4876ea09d0833904f5bcedd0a06c3bca515a42fa40c1a1d267d39df7094d
> [plugin.hls][debug] URL=https://phls-vod.cdn.turner.com/cnnngtv/cnn/hls/2019/09/22/urn:ngtv-show:119744/index.m3u8?hdnts=exp=1570445287~acl=/cnnngtv/cnn/hls/2019/*~id=fe3ad43531e3cd8b66ff7118c70b8913~hmac=015a4876ea09d0833904f5bcedd0a06c3bca515a42fa40c1a1d267d39df7094d; params={}
> [cli][info] Available streams: 70k (worst), 360p_alt, 360p (best), 540p_alt, 540p, 720p
> [cli][info] Opening stream: 360p (hls)
> [stream.hls][debug] Reloading playlist
> [stream.hls][debug] Segments in this playlist are encrypted
> [stream.hls][debug] First Sequence: 1; Last Sequence: 377
> [stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 1; End Sequence: 377
> [stream.hls][debug] Adding segment 1 to queue
> [cli][debug] Pre-buffering 8192 bytes
> [stream.hls][debug] Adding segment 2 to queue
> [stream.hls][debug] Adding segment 3 to queue
> [stream.hls][debug] Adding segment 4 to queue
> [stream.hls][debug] Adding segment 5 to queue
> [stream.hls][debug] Adding segment 6 to queue
> [stream.hls][debug] Adding segment 7 to queue
> [stream.hls][debug] Adding segment 8 to queue
> [stream.hls][debug] Adding segment 9 to queue
> [stream.hls][debug] Adding segment 10 to queue
> [stream.hls][debug] Adding segment 11 to queue
> [stream.hls][debug] Adding segment 12 to queue
> [stream.hls][debug] Adding segment 13 to queue
> [stream.hls][debug] Adding segment 14 to queue
> [stream.hls][debug] Adding segment 15 to queue
> [stream.hls][debug] Adding segment 16 to queue
> [stream.hls][debug] Adding segment 17 to queue
> [stream.hls][debug] Adding segment 18 to queue
> [stream.hls][debug] Adding segment 19 to queue
> [stream.hls][debug] Adding segment 20 to queue
> [stream.hls][debug] Adding segment 21 to queue
> [stream.hls][debug] Adding segment 22 to queue
> [stream.hls][debug] Download of segment 1 complete
> [cli][debug] Checking file output
> [cli][debug] Writing stream to output
> [stream.hls][debug] Adding segment 23 to queue
> [stream.hls][debug] Download of segment 2 complete
> [stream.hls][debug] Adding segment 24 to queue
> Exception in thread Thread-HLSStreamWriter:
> Traceback (most recent call last):
>   File "threading.py", line 916, in _bootstrap_inner
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
>     self.write(segment, result)
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 141, in write
>     self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
>   File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 31, in pkcs7_decode
>     raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
> streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 99
> 
> error: Error when reading from stream: Read timeout, exiting
> [stream.segmented][debug] Closing worker thread
> [stream.segmented][debug] Closing writer thread
> [cli][info] Stream ended
> [cli][info] Closing currently open stream...

A couple of streams worked. Another (this one above), didn't. Exactly same platform. This error is very random, but it seems like it may pop up across various different sites. 
I'll chime in here and say that I'm seeing the SAME EXACT thing.

Please don't close this as "too difficult to reproduce".  This is a CORE FUNCTION of streamlink, and it is not woking.  closing as too difficult to reproduce is dodging a major issue.

What streamlink needs to do if it can't (for some reason) download a queued packet is retry the packet.  It's what every single player in the world does, why can't streamlink as well?
@sou7611 It's been open for a year, what exactly is your concern of it being closed? The other was closed because it's a duplicate of this issue. Regarding the functionality, if it's so easy to deal with please submit a PR to add the functionality that will address this. These are also on old versions of Streamlink. If it's still happening to you provide debug output and reproduction steps to actually try and solve the problem since based on the tone of your comment it's happening regularly.

An issue that has been reported 4 times in a year is an edge case, if someone wants to work on it they will, otherwise complaining doesn't exactly motivate people to solve a problem that 99.9% of users are not encountering. This is a free open source project, no one is getting paid to work on this, so keep that in mind. People work on whatever aspects they want as little or as much as they want, it's that simple.
Trying to reproduce it to capture said logs.  It happens on a wide variety of services but actually capturing it in action, that's another story.

Like a problem with your car not showing up at the mechanics shop, trying to make this happen on purpose is proving challenging.

Somehow it's clearly getting a packet that's not defined, which screws up the decoding, as it's trying to decode data that's null in length.
FWIW, I'd also suggest the following alteration, if it's desired to not call the decrypt if the data is null, that way you know in the logs if it was triggered :

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

Interesting, something is up with padding as well ... there's a function that cuts off garbage at the end (if the packet isn't an even length of 16) but that apparently either doesn't fix, further damages the packet, or it's just bad to begin with:

stream.hls][debug] Cutting off 15 bytes of garbage before decrypting
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "threading.py", line 916, in _bootstrap_inner
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
    self.write(segment, result)
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 158, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "C:\Program Files (x86)\Streamlink\pkgs\streamlink\stream\hls.py", line 34, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 38

This also crashes the stream.  It may queue more packets, but it never writes anything past this point.
So here's a question ... does anyone know the history behind the padding%16 cutoff?  It's been in the code since livestreamer in 2014 :

https://github.com/chrippa/livestreamer/commit/c38a543c726f9b207a80836edb09f9ae696f0871

Near as I can tell, you don't get garbage unless you have a corrupted segment, and since a corrupted segment won't decode, you get a null decrypted_chunk, which then crashes the stream.

So far, this seems to maintain the stream without causing errors :

            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

FYI, been running a bunch of repeated capture tests against foxsportsgo, currently the following code block for handling encyrypted chunks seems to be most stable ... this basically just throws out any packet with padded garbage (I've not found a single instance in testing where a packet with padded gargbage truncated to the nearest /16 in size was not corrupted).

            decrypted_chunk = 0
			
            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in length", sequence.num)

I currently get this on maybe 1/8 of my download attempts from Crunchyroll with a valid login. Will start running with debug logging enabled, I've seen it three times so far. If I stream the same content again it usually works the next time. The streams are 1080p usually around 1.5GB in total size, if that means anything.
```
[stream.hls][debug] Adding segment 357 to queue
[stream.hls][debug] Download of segment 336 complete
[stream.hls][debug] Adding segment 358 to queue
[stream.hls][debug] Download of segment 337 complete
[stream.hls][debug] Adding segment 359 to queue
[stream.hls][debug] Download of segment 338 complete
[stream.hls][debug] Adding segment 360 to queue
[stream.hls][debug] Download of segment 339 complete
[stream.hls][debug] Adding segment 361 to queue
[stream.hls][debug] Cutting off 8 bytes of garbage before decrypting
error: Error when reading from stream: Read timeout, exiting
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[cli][info] Closing currently open stream...

Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "threading.py", line 916, in _bootstrap_inner
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\segmented.py", line 167, in run
    self.write(segment, result)
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\hls.py", line 157, in write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "C:\Users\kg\AppData\Local\Streamlink\pkgs\streamlink\stream\hls.py", line 34, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 196
```
Could you please give #3446 a try and see whether this fixes the input padding issue?
I encountered the exact same bug with the `pluzz` plugin:
```
$ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
[cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
[cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls-multi)
[cli][info] Starting player: /usr/bin/vlc
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
    self.write(segment, result)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 135, in write
    return self._write(sequence, *args, **kwargs)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 166, in _write
    self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 33, in pkcs7_decode
    raise StreamError("Input is not padded or padding is corrupt, got padding size of {0}".format(val))
streamlink.exceptions.StreamError: Input is not padded or padding is corrupt, got padding size of 187
```

I'll try the patch from #3446 but as the issue does not occur consistently, it's hard to know if the issue is really fixed.
I tried #3446 and the issue still happens:
```
$ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
[cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
[cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
[cli][info] Opening stream: 720p (hls-multi)
[cli][info] Starting player: /usr/bin/vlc
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/ffmpeg-355394-340
Exception in thread Thread-HLSStreamWriter:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
    self.write(segment, result)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 124, in write
    return self._write(sequence, *args, **kwargs)
  File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 147, in _write
    self.reader.buffer.write(unpad(decrypted_chunk, AES.block_size, style="pkcs7"))
  File "/home/adema/.local/lib/python3.9/site-packages/Crypto/Util/Padding.py", line 90, in unpad
    raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.
```

@bastimeyer I am happy to test anything else you can think of :+1: 
If it helps, in the original hls.py. I fixed it completely on my system by
simply commenting out the truncation, and if garbage_len was set, setting
the chunk to a value of 0 prior to checking for garbage. This
basically makes it skip the packet entirely if there's garbage, and keep
going otherwise.

It's a very minimal change, taking advantage of the logic flow already in
place.

The padding error, when it occurs, is triggered by the decryptor.decrypt
command, trying to decrypt a corrupted packet.

Haven't seen any issues at all in captured .ts streams, and it completely
eliminated the padding error.

            data = res.content
            # If the input data is not a multiple of 16, cut off any garbage
            garbage_len = len(data) % 16

            #if garbage_len:
            #    log.debug("Cutting off {0} bytes of garbage "
            #              "before decrypting", garbage_len)
            #    decrypted_chunk = decryptor.decrypt(data[:-garbage_len])

            decrypted_chunk = 0

            if garbage_len:
                log.error("Segment {0} is damaged with {0} bytes of padded
garbage ", sequence.num, garbage_len)
            else:
                decrypted_chunk = decryptor.decrypt(data)

            if decrypted_chunk:
                self.reader.buffer.write(pkcs7_decode(decrypted_chunk))
            else:
                log.error("Download of segment {0} was zero bytes in
length", sequence.num)


On Thu, Jan 21, 2021 at 2:02 PM Élie ROUDNINSKI <notifications@github.com>
wrote:

> I tried #3446 <https://github.com/streamlink/streamlink/pull/3446> and
> the issue still happens:
>
> $ DISPLAY=:0 streamlink --hls-audio-select '*' --ffmpeg-copyts --mux-subtitles https://www.france.tv/france-2/direct.html best
>
> [cli][info] Found matching plugin pluzz for URL https://www.france.tv/france-2/direct.html
>
> [cli][info] Available streams: 144p (worst), 216p, 360p, 540p, 720p (best)
>
> [cli][info] Opening stream: 720p (hls-multi)
>
> [cli][info] Starting player: /usr/bin/vlc
>
> [stream.ffmpegmux][error] Pipe copy aborted: /tmp/ffmpeg-355394-340
>
> Exception in thread Thread-HLSStreamWriter:
>
> Traceback (most recent call last):
>
>   File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
>
>     self.run()
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/segmented.py", line 189, in run
>
>     self.write(segment, result)
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 124, in write
>
>     return self._write(sequence, *args, **kwargs)
>
>   File "/home/adema/.local/lib/python3.9/site-packages/streamlink/stream/hls.py", line 147, in _write
>
>     self.reader.buffer.write(unpad(decrypted_chunk, AES.block_size, style="pkcs7"))
>
>   File "/home/adema/.local/lib/python3.9/site-packages/Crypto/Util/Padding.py", line 90, in unpad
>
>     raise ValueError("Padding is incorrect.")
>
> ValueError: Padding is incorrect.
>
>
> @bastimeyer <https://github.com/bastimeyer> I am happy to test anything
> else you can think of 👍
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/streamlink/streamlink/issues/2365#issuecomment-764867882>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABNBVNHSZ4VGA6JA2V4O763S3B25BANCNFSM4G7VONSQ>
> .
>

Would this solution just remove the offending segment from the stream, so those 5, 6, 10, etc. seconds would not be recorded?
I believe so, but I've not seen it cause any issues in recorded video, so
the question is... is that a bad thing?

If we can't record them due to corruption, it may not be an actual loss
with error checks, re-requests, etc.

On Thu, Jan 21, 2021, 5:31 PM ischmidt20 <notifications@github.com> wrote:

> Would this solution just remove the offending segment from the stream, so
> those 5, 6, 10, etc. segments would not be recorded?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/streamlink/streamlink/issues/2365#issuecomment-764983399>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABNBVNHUSSMSYYLJNHUV6BLS3CTL3ANCNFSM4G7VONSQ>
> .
>

> Would this solution just remove the offending segment from the stream

Yes, it would remove these segments and would thus get rid of the error, but that's not the solution we're looking for here.

> ValueError: Padding is incorrect.

https://github.com/Legrandin/pycryptodome/blob/v3.9.9/lib/Crypto/Util/Padding.py#L87-L90
Is there any other idea floating around that I could try?
I think I may have stumbled across the cause of this (or one of them, anyway): it seems that Python's requests/urllib3 libraries do not signal any kind of error if the server closes the connection mid-way through a file (i.e. it does not verify that it received as many bytes as it should have, using the Content-Length header).

The padding is corrupt because it's not padding, it's arbitrary data where the download was truncated.

urllib3 does have an optional keyword argument enforce_content_length=True that can be specified. However, I can't see any way in requests to get that passed on to urllib3.

This has apparently been reported in psf/requests#4956 years ago but there is no developer response in that issue.
Closing since this is an upstream error.
Though the ultimate code bug is upstream, that doesn't mean it's not a real problem for streamlink users, and a workaround wouldn't bring real value to them.
Let's reopen for visibility. However, it is a bug/issue in Streamlink's dependencies, and unfortunately there's no clean way of fixing this here.

----

https://github.com/psf/requests/issues/4956#issuecomment-573325001
> **The fix**
> I think urllib3 should just make `enforce_content_length=True` by default.
> ...
> If urllib3 makes that change, then Requests can simply bump their minimum required urllib3 version to whatever release includes the change, and be done.
> Failing that, Requests should pass `enforce_content_length=True` explicitly.

- https://github.com/psf/requests/blob/v2.25.1/requests/adapters.py#L394
- https://github.com/urllib3/urllib3/blob/1.26.5/src/urllib3/response.py#L185-L187

Since `requests.adapters.HTTPAdapter.send` doesn't allow for custom parameters to be set for `urllib3.response.HTTPResponse`, this means all that could be done in Streamlink is patching out request's import of urllib3's HTTPResponse. This needs to be done in `streamlink.plugin.api.http_session`. Since I haven't run into this issue yet, I can't test this myself.

Resolving patch:
diff --git a/src/streamlink/plugin/api/http_session.py b/src/streamlink/plugin/api/http_session.py
--- a/src/streamlink/plugin/api/http_session.py
+++ b/src/streamlink/plugin/api/http_session.py
@@ -1,5 +1,7 @@
 import time
 
+import requests.adapters
+import urllib3
 from requests import Session
 
 from streamlink.exceptions import PluginError
@@ -7,16 +9,39 @@
 from streamlink.plugin.api import useragents
 from streamlink.utils import parse_json, parse_xml
 
-try:
-    from requests.packages import urllib3
 
+try:
     # We tell urllib3 to disable warnings about unverified HTTPS requests,
     # because in some plugins we have to do unverified requests intentionally.
     urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
-except (ImportError, AttributeError):
+except AttributeError:
     pass
 
-__all__ = ["HTTPSession"]
+
+class _HTTPResponse(urllib3.response.HTTPResponse):
+    def __init__(self, *args, **kwargs):
+        # Always enforce content length validation!
+        # This fixes a bug in requests which doesn't raise errors on HTTP responses where
+        # the "Content-Length" header doesn't match the response's body length.
+        # https://github.com/psf/requests/issues/4956#issuecomment-573325001
+        #
+        # Summary:
+        # This bug is related to urllib3.response.HTTPResponse.stream() which calls urllib3.response.HTTPResponse.read() as
+        # a wrapper for http.client.HTTPResponse.read(amt=...), where no http.client.IncompleteRead exception gets raised
+        # due to "backwards compatiblity" of an old bug if a specific amount is attempted to be read on an incomplete response.
+        #
+        # urllib3.response.HTTPResponse.read() however has an additional check implemented via the enforce_content_length
+        # parameter, but it doesn't check by default and requests doesn't set the parameter for enabling it either.
+        #
+        # Fix this by overriding urllib3.response.HTTPResponse's constructor and always setting enforce_content_length to True,
+        # as there is no way to make requests set this parameter on its own.
+        kwargs.update({"enforce_content_length": True})
+        super().__init__(*args, **kwargs)
+
+
+# override all urllib3.response.HTTPResponse references in requests.adapters.HTTPAdapter.send
+urllib3.connectionpool.HTTPConnectionPool.ResponseCls = _HTTPResponse
+requests.adapters.HTTPResponse = _HTTPResponse
 
 
 def _parse_keyvalue_list(val):
@@ -150,3 +175,6 @@ def request(self, method, url, *args, **kwargs):
             res = schema.validate(res.text, name="response text", exception=PluginError)
 
         return res
+
+
+__all__ = ["HTTPSession"]


Test patch: