Quasolaris / NewPipePlaylistExtractor

Download your NewPipe created playlists as mp3, wav or other codec and listen to it offline. It is also possible to export the playlists as CSV, M3U8 or other text formats.
GNU General Public License v3.0
17 stars 3 forks source link
converter download-manager downloader extract m3u8 m3u8-playlist markdown mp3 mp3wav mp4 newpipe playlist playlist-downloader playlist-manager python youtube

NewPipe Playlist Extractor

NewPipe Playlist Extractor


This Python script extracts playlists made with the NewPipe app and allows you to download them as audio-files.

When you create a playlist in NewPipe it is not saved as a YouTube playlist and can therefore not be downloaded via a playlist-link. This script allows you to extract the list of videos you have in a playlist and download them as audio files.

Buy Me A Coffe!

Stargazers over time

Note: To use script on Windows or Andriod please see instructions below

Note: MacOS users, you can follow the Linux guide

Table of Contents

  1. Features
  2. Codecs
  3. Dependencies
  4. Usage
  5. Linux
  6. Windows
  7. Android
  8. Errors and Troubleshooting

Features

Codecs

The script supports the following codecs:

Dependencies

Usage

The playlists get saved into the /Script/Playlists folder

Linux

Install the dependencies and you are good to go.

Windows

To use the script on Windows you have to do a few extra steps:

Android

For a step-by-step installation guide for Android click here.

Errors and Troubleshooting

get_throttling_function_name: could not find match for multiple

This is an error due to YouTube changing stuff, either to update or simply to attack Pytube, NewPipe and other clients/downloaders.

First: Check if Pytube has an update, maybe the Pytube team already fixed it.

If no update was published or the error still persists, follow these steps:

  1. Go to the pytube package folder (normally: \~/.local/lib/python3.9/site-packages/pytube or use pip list -v to find it if that doesn't work)

  2. Open the cipher.py file in an editor of your choice (nano -c cipher.py the -c flag displays the line number where your cursor is)

  3. Comment out the following lines: 272 and 273

  4. Paste the following regex beneath the lines you just commented out (Make sure the white spaces are correct, it is Python after all):

    r'a\.[a-zA-Z]\s*&&\s*\([a-z]\s*=\s*a\.get\("n"\)\)\s*&&.*?\|\|\s*([a-z]+)',
    r'\([a-z]\s*=\s*([a-zA-Z0-9$]+)(\[\d+\])\([a-z]\)',
  5. Now go to line 290 (or 288 if you deleted the regex lines instead of commenting them out) with CTRL+_ in nano you can jump to a specific line.

  6. Comment the following line out:

    nfunc=function_match.group(1)),
  7. Right underneath the now commented out line, place the following:

    nfunc=re.escape(function_match.group(1))),

    The file sector you changed should now look like this:

    
    function_patterns = [
        # https://github.com/ytdl-org/youtube-dl/issues/29326#issuecomment-865985377
        # https://github.com/yt-dlp/yt-dlp/commit/48416bc4a8f1d5ff07d5977659cb8ece7640dcd8
        # var Bpa = [iha];
        # ...
        # a.C && (b = a.get("n")) && (b = Bpa[0](b), a.set("n", b),
        # Bpa.length || iha("")) }};
        # In the above case, `iha` is the relevant function name
        #r'a\.[a-zA-Z]\s*&&\s*\([a-z]\s*=\s*a\.get\("n"\)\)\s*&&\s*'
        #r'\([a-z]\s*=\s*([a-zA-Z0-9$]{3})(\[\d+\])?\([a-z]\)',
        r'a\.[a-zA-Z]\s*&&\s*\([a-z]\s*=\s*a\.get\("n"\)\)\s*&&.*?\|\|\s*([a-z]+)',
        r'\([a-z]\s*=\s*([a-zA-Z0-9$]+)(\[\d+\])\([a-z]\)',
    ]
    logger.debug('Finding throttling function name')
    for pattern in function_patterns:
        regex = re.compile(pattern)
        function_match = regex.search(js)
        if function_match:
            logger.debug("finished regex search, matched: %s", pattern)
            if len(function_match.groups()) == 1:
                return function_match.group(1)
            idx = function_match.group(2)
            if idx:
                idx = idx.strip("[]")
                array = re.search(
                    r'var {nfunc}\s*=\s*(\[.+?\]);'.format(
                        #nfunc=function_match.group(1)),
                        nfunc=re.escape(function_match.group(1))),
                    js
                )
                if array:
                    array = array.group(1).strip("[]").split(",")
                    array = [x.strip() for x in array]
                    return array[int(idx)]
    
    raise RegexMatchError(
        caller="get_throttling_function_name", pattern="multiple"
8. Save and close the file
9. You should now be able to download your playlists again

### AttributeError: 'NoneType' object has no attribute 'span'

This is an error due to YouTube changing stuff, either to update or simply to attack Pytube, NewPipe and other clients/downloader. See https://github.com/pytube/pytube/issues/1499#issuecomment-1473022893 for the issue and the fix.

1. First: Check if Pytube has an update, maybe the Pytube team already fixed it. If no update was published or the error still persists, follow these steps:
2. Go to the pytube package folder (normally: \~/.local/lib/python3.9/site-packages/pytube or use `pip list -v` to find it if that doesn't work).
3. Modify {path to pip packages}/pytube/cipher.py:
    transform_plan_raw = find_object_from_startpoint(raw_code, match.span()[1] - 1)

to 
    transform_plan_raw = js


4. Save the file.
5. Try again.