def addTitle(audio_path, title):
    """Add metadata title to the audio file provided with audio_path 

    Arguments:
        audio_path {String} -- Path to the audio file
        title {String} -- The title that is going to be added to the audio file
    Return:
        Doesn't return anything
    """
    if os.path.exists(audio_path):
        if (title != "" or title != None):
            audio = MP3(audio_path, ID3=ID3)
            try:
                audio.add_tags()
            except error:
                logging.debug("ID3 Tag already exists for this audio file")

            try:
                audio.tags.add(TIT2(encoding=3, text=title))
                audio.save()
                logging.debug("Title  Added")
            except error:
                logging.debug("Error Adding Title to audio file")
        else:
            logging.debug("Title can't be null or empty")
    else:
        logging.debug("audio path is invalid")
Exemple #2
0
 def getDirectory(self):
     file = QFileDialog.getExistingDirectory(
         self, 'Choose Download Directory',
         self.getDownloadLocationConfig()[0])
     if file:
         self.lineEditDownloadDirectoryShow.setText(file)
         config = constructConfig(file)
         # print(config['conf'].get('download_dir'))
         generateConfigFile(config)
         logging.debug("Changed download directory to: {}".format(file))
Exemple #3
0
def startTheServers():
    logging.debug("Starting Daemon Server! Modes: {} {} {}".format(MEDIA_TYPE,MEDIA_QUALITY,DOWNLOAD_MODE))
    if mainThread.is_alive():
        return True
    
    if not mainThread.is_alive():
        #starting main thread
        mainThread.start()
    
    work_is_pending = True
    for worker in worker_thread_list:
        if not worker.is_alive():
            work_is_pending = False
    if not work_is_pending:
        #starting worker threads
        for t in worker_thread_list:
            t.start()
        return False
Exemple #4
0
 def run(self):
     while not self.stopped():
         try:
             url = self.task_queue.get(timeout=1)
         except queue.Empty:
             pass
         else:
             try:
                 if(MEDIA_TYPE == 'audio'):
                     start_audio_download(url)
                     task_queue.task_done()
                     logging.debug(self.thread_name+ " Completed")
                 elif(MEDIA_TYPE == 'video'):
                     if(MEDIA_QUALITY == 'normal'):
                         start_video_download(url)
                         task_queue.task_done()
                         logging.debug(self.thread_name+ " Completed")
                     elif(MEDIA_QUALITY == 'hq'):
                         start_high_quality_video_download(url)
                         task_queue.task_done()
                         logging.debug(self.thread_name+ " Completed")
                 if(task_queue.empty()):
                     logging.debug("No pending task in the queue")
             except Exception as e:
                 logging.debug("Error occured in daemon loop")
                 logging.debug(e)
Exemple #5
0
def sigint_handler(signum, frame):
    logging.debug('Shutting Threads down...')
    stopTheServers()
    sys.exit(0)
Exemple #6
0
 def closeEvent(self, event):
     stopTheServers()
     logging.debug("Closing GUI")
     event.accept()
Exemple #7
0
 def exit_app(self):
     logging.debug("Closing GUI")
     stopTheServers()
     sys.exit(0)
def addPicture(audio_path, pafy_obj):
    """Add picture to the audio file provided with audio_path arguments
    Picture url will get retrived from the pafy object

    Arguments:
        audio_path {String} -- Path to the audio file to work with
        pafy_obj {Object} -- The pafy object of the current audio file
    Return:
        Doesn't return a value if operations are succeful but if it fail to fetch any image url 
        it return None and no operation is done with the audio file
    """
    if os.path.exists(audio_path)\
         and os.path.isfile(audio_path)\
              and audio_path.endswith('mp3'):
        if pafy_obj != None:
            audio = MP3(audio_path, ID3=ID3)

            # Download the cover image
            try:
                picture_url = None
                if (pafy_obj.bigthumbhd != None):
                    picture_url = pafy_obj.bigthumbhd
                    logging.debug("BigThumbHd")
                elif (pafy_obj.bigthumb != None):
                    picture_url = pafy_obj.bigthumb
                    logging.debug("BigThumb")
                elif (pafy_obj.thumb != None):
                    picture_url = pafy_obj.thumb
                    logging.debug("Thumb")
                else:
                    logging.debug("No thumbnail avaliable for the video")
                    return

                img = requests.get(picture_url)
                # extracting byte data from img response obj
                img = img.content
            except Exception as e:
                logging.debug("Error downloading cover art")
                logging.debug(e)

            # try adding id3 tags if not exists
            try:
                audio.add_tags()
            except error:
                logging.debug("ID3 Tag already exists for this audio file")

            # editing the id3 tag
            try:
                audio.tags.add(
                    APIC(mime='image/jpeg', type=3, desc=u'Cover', data=img))
                audio.save()
                logging.debug("Cover added")
            except error:
                logging.debug("Error adding coverart")
        else:
            logging.debug("Image path is invalid")
    else:
        logging.debug("audio path is invalid")
Exemple #9
0
#url = 'https://www.youtube.com/playlist?list=PLRiSVT9MWtYwyhhgVNnRDTpCRvF-t2lc8'
url = input("Enter a valid YouTube  Playlist Link:")
while not url.startswith('https://www.youtube.com/playlist?list'):
    url = input("Enter a valid YouTube  Playlist Link:")

av = ['a', 'v']
aud_or_vid = None
while not aud_or_vid in av:
    aud_or_vid = input("Download in audio or video (a/v)?")
song_list = SongListGenerator().generateList(url)

song_batchs_of_three = [
    song_list[i:i + 3] for i in range(0, len(song_list), 3)
]
# print(song_batchs_of_three)

# print(song_list)
if len(song_list) > 0:
    try:
        if aud_or_vid == av[0]:
            for batch_one in song_batchs_of_three:
                with concurrent.futures.ThreadPoolExecutor() as executor:
                    executor.map(start_audio_download, batch_one)
        elif aud_or_vid == av[1]:
            for batch_one in song_batchs_of_three:
                with concurrent.futures.ThreadPoolExecutor() as executor:
                    executor.map(start_video_download, batch_one)
    except Exception as e:
        logging.debug("Exception occured running threadpool executor")
        logging.debug(e)
Exemple #10
0
def cleanJunk():
    temp_dir = os.path.join(*conf.get('temp_dir'))
    try:
        shutil.rmtree(temp_dir)
    except Exception as e:
        logging.debug("Error occured cleaning temp_dir {}".format(temp_dir))
def start_high_quality_video_download(url):
    """ This function download both video and audio separately
        and combine them to produce 1080p video.

        Arguments:
            url {string} -- The url of the video from youtube
    """
    logging.debug("Initiating - {}".format(
        start_high_quality_video_download.__name__))
    # making temp directory if not exist
    # this folder will be used to temporary storing video and audio files
    # those temporary files will be deleted once combine operatoin is successfull
    if not os.path.exists(TEMP_DIR):
        try:
            logging.debug("Making Directory: {}".format(TEMP_DIR))
            os.makedirs(TEMP_DIR)
        except Exception as e:
            logging.debug(
                "Error occured in making Directory: {}".format(TEMP_DIR))
            logging.debug(e)

    if not os.path.exists(DOWN_DIR_VIDEO):
        try:
            logging.debug("Making Directory: {}".format(DOWN_DIR_VIDEO))
            os.makedirs(DOWN_DIR_VIDEO)
        except Exception as e:
            logging.debug(
                "Error occured in making Directory: {}".format(DOWN_DIR_VIDEO))
            logging.debug(e)

    # downloaing only video
    timeout = 5
    video = None
    while video == None and timeout > 0:
        try:
            video = get_pafy_stream_obj(url, format='VIDEO', only_video=True)
            time.sleep(1)
        except OSError:
            logging.debug("Video is not available in Youtube.")
            logging.debug("Link: " + url)
            break
        timeout -= 1

    if video is not None:
        # slugifying title
        slugify_video_title = TitleSlugify().slugify_for_windows(
            video.title + '.' + video.extension)
        temp_path_to_download_video = os.path.join(TEMP_DIR,
                                                   slugify_video_title)

        output_path = os.path.join(DOWN_DIR_VIDEO, slugify_video_title)
        if not os.path.exists(output_path):
            try:
                logging.debug("Downloading HQ Video: " +
                              TitleSlugify().slugify_for_windows(video.title))
                video.download(filepath=temp_path_to_download_video)
            except Exception as e:
                logging.debug(
                    "Exception occured at high_quality_video_download video downloader"
                )
                logging.debug(e)
                # this need to be checked
                return

            # downloading only audio
            timeout = 5
            audio = None
            while audio == None and timeout > 0:
                try:
                    audio = get_pafy_stream_obj(url, format='AUDIO')
                    time.sleep(1)
                except OSError:
                    logging.debug("Video is not availble in Youtube.")
                    logging.debug("Link: " + url)
                    break
                timeout -= 1
            # if audio is not avilable
            # then video is also not available
            if audio is not None:
                # slugifying title
                slugify_audio_title = TitleSlugify().slugify_for_windows(
                    audio.title + '.' + audio.extension)
                # setting download location
                temp_path_to_download_audio = os.path.join(
                    TEMP_DIR, slugify_audio_title)

                try:
                    logging.debug(
                        "Downloading HQ Audio: " +
                        TitleSlugify().slugify_for_windows(audio.title))
                    audio.download(filepath=temp_path_to_download_audio)
                except Exception as e:
                    logging.debug(
                        "Exception occured at high_quality_video_download audio downloader"
                    )
                    logging.debug(e)

                # combining both video and audio
                cmd = [
                    str(FFMPEG_LOCATION), FFMPEG_LOG, FFMPEG_LOG_LEVEL, '-i',
                    temp_path_to_download_video, '-i',
                    temp_path_to_download_audio, '-c', 'copy', '-strict',
                    'experimental', output_path
                ]

                # running command with subprocess
                try:
                    logging.debug(
                        "Combining HQ Audio and Video: " +
                        TitleSlugify().slugify_for_windows(audio.title))
                    logging.debug("Saving to: " +
                                  os.path.abspath(DOWN_DIR_VIDEO))
                    subprocess.run(cmd, shell=True)
                    logging.debug("DOWNLOADED=> " + slugify_video_title)
                    notifyAboutTheService("Downloaded", slugify_video_title)

                except Exception as e:
                    notifyAboutTheService("Error Downloading",
                                          slugify_video_title)
                    logging.debug(
                        "Errore occured during runing combining ffmpeg command"
                    )
                    logging.debug(e)
                finally:
                    try:
                        os.remove(temp_path_to_download_audio)
                        os.remove(temp_path_to_download_video)
                    except Exception as e:
                        logging.debug(
                            "Unable to remove temporary files in temp folder({})"
                            .format(TEMP_DIR))
                        logging.debug(e)
        else:
            logging.debug("File Already Exists! Path: " + output_path)
    else:
        logging.debug(
            "Unable to find the video file at this time. Timeout!! Try again later."
        )
def get_pafy_stream_obj(url, format=None, only_video=False):
    """This function return stream object from pafy

    Arguments:
            url {string} -- The url of the video from youtube

    Returns:
            Stream_Obj -- This is a object of Stream class from pafy
    """
    try:
        obj = pafy.new(url)
        # returning only the pafy obj if format is not given
        if format == None:
            return obj

        stream_obj = None
        # returning format specified in the parameter
        if format == 'AUDIO':
            logging.debug("Getting audio pafy stream_object")
            stream_obj = obj.getbestaudio(preftype='m4a')
        if format == 'VIDEO':
            if only_video:
                # get only video at 1080p
                # stream_obj = obj.getbestvideo(preftype='mp4')

                ## iterating from backward as best streams are there and
                ## slecting best 1920x1080p mp4 stream
                logging.debug("Getting HQ video pafy stream_object")
                for stream in obj.videostreams[::-1]:
                    if stream.extension == 'mp4':
                        if stream.dimensions[0] == 1920 and stream.dimensions[
                                1] == 1080:
                            stream_obj = stream
                            break
            else:
                # get best will return both audio and obj normaly at 640p
                logging.debug("Getting normal-video pafy stream_object")
                stream_obj = obj.getbest(preftype='mp4')
        return stream_obj

    except OSError as e:
        logging.debug("OSError in new pafy")
        logging.debug(e)
        raise OSError
    except Exception as e:
        logging.debug("Error occured in new pafy")
        logging.debug(e)
        return None
def start_audio_download(url):
    """This is a function to download audio file as m4a form pafy streamobj and also convert them to mp3

    Arguments:
            url {string} -- The url of the video from yoututbe
    """
    logging.debug("Initiating - {}".format(start_audio_download.__name__))
    # trying to get stream obj from pafy
    # until the object is received witout an errore
    # the while loop keeps reqesting pafy
    # if video is not available in youtube
    # gives OSError and breaks the loop
    timeout = 5
    stream_obj = None
    pafy_obj = None
    while (stream_obj == None and timeout > 0):
        try:
            pafy_obj = get_pafy_stream_obj(url)
            time.sleep(1)
            timeout -= 1
        except OSError:
            logging.debug("Video is not available in Youtube.")
            logging.debug("Link: " + url)
            break
        except Exception as e:
            logging.debug("Error occured in new pafy")
            logging.debug(e)
            # sys.exit()
    if pafy_obj is not None:
        # getting audio streams from pafy_obj
        stream_obj = pafy_obj.getbestaudio(preftype='m4a')
        # slugifying title
        slugify_audio_title = TitleSlugify().slugify_for_windows(
            stream_obj.title + '.' + stream_obj.extension)
        path_to_download = os.path.join(DOWN_DIR_AUDIO, slugify_audio_title)

        #checking if the file already exists
        if not os.path.exists(path_to_download) and not os.path.exists(
                path_to_download.replace('.m4a', '.mp3')):
            #starting download
            try:
                if not os.path.exists(DOWN_DIR_AUDIO):
                    try:
                        logging.debug(
                            "Making Directory: {}".format(DOWN_DIR_AUDIO))
                        os.makedirs(DOWN_DIR_AUDIO)
                        # os.mkdir(DOWN_DIR_AUDIO)
                    except Exception as e:
                        logging.debug(
                            "Error occured in making Directory: {}".format(
                                DOWN_DIR_AUDIO))
                        logging.debug(e)

                logging.debug(
                    "Downloading Audio: " +
                    TitleSlugify().slugify_for_windows(stream_obj.title))
                # intiate the download
                stream_obj.download(filepath=path_to_download)
                logging.debug("Saving to: " + os.path.abspath(DOWN_DIR_AUDIO))

                #converting to mp3
                cmd = [
                    str(FFMPEG_LOCATION), FFMPEG_LOG, FFMPEG_LOG_LEVEL, '-i',
                    path_to_download, '-vn', '-ab', '128k', '-ar', '44100',
                    '-y',
                    os.path.join(DOWN_DIR_AUDIO,
                                 slugify_audio_title.replace('.m4a', '.mp3'))
                ]
                # logging.debug(" ".join(cmd))
                try:
                    logging.debug("Converting m4a to mp3")
                    subprocess.run(cmd, shell=True)
                    logging.debug("DOWNLOADED=> " +
                                  slugify_audio_title.replace("m4a", "mp3"))
                    # adding unicode title from stream obj
                    addTitle(path_to_download.replace('m4a', 'mp3'),
                             stream_obj.title)
                    addPicture(path_to_download.replace('m4a', 'mp3'),
                               pafy_obj)
                    notifyAboutTheService(
                        "Downloaded",
                        slugify_audio_title.replace("m4a", "mp3"))
                except Exception as e:
                    notifyAboutTheService(
                        "Error Downloading",
                        slugify_audio_title.replace("m4a", "mp3"))
                    logging.debug("Errore occured in converting file")
                    logging.debug(e)

                try:
                    # subprocess.run(['rm',path_to_download])
                    logging.debug("Removing m4a file")
                    os.remove(path_to_download)
                except Exception as e:
                    logging.debug("Errore removing actual file")
                    logging.debug(e)

            except Exception as e:
                logging.debug("Unable to download. Error occured")
                logging.debug(e)
        else:
            logging.debug("File Already Exists! Path: " + path_to_download)
    else:
        logging.debug(
            "Unable to find the audio file at this time. Timeout!! Try again later or Try updating 'youtube-dl'dependency."
        )
def start_video_download(url):
    """This function download 640p quality normal video.

     Arguments:
            url {string} -- The url of the video from youtube
    """
    logging.debug("Initiating - {}".format(start_video_download.__name__))

    timeout = 5
    stream_obj = None
    while (stream_obj == None and timeout > 0):
        try:
            stream_obj = get_pafy_stream_obj(url, format='VIDEO')
            time.sleep(1)
            timeout -= 1
        except OSError:
            logging.debug("Video is not available in Youtube.")
            logging.debug("Link: " + url)
            break
        except Exception as e:
            logging.debug("Error occured in new pafy")
            logging.debug(e)

    if stream_obj is not None:
        # slugify title
        slugify_video_title = TitleSlugify().slugify_for_windows(
            stream_obj.title + '.' + stream_obj.extension)
        path_to_download = os.path.join(DOWN_DIR_VIDEO, slugify_video_title)

        if not os.path.exists(path_to_download):
            #starting download
            try:
                if not os.path.exists(DOWN_DIR_VIDEO):
                    try:
                        logging.debug(
                            "Making Directory: {}".format(DOWN_DIR_VIDEO))
                        os.makedirs(DOWN_DIR_VIDEO)
                        # os.mkdir(DOWN_DIR_VIDEO)
                    except Exception as e:
                        logging.debug(
                            "Error occured in making Directory: {}".format(
                                TEMP_DIR))
                        logging.debug(e)
                logging.debug(
                    "Downloading Video: " +
                    TitleSlugify().slugify_for_windows(stream_obj.title))
                logging.debug("Saving to: " + os.path.abspath(DOWN_DIR_VIDEO))
                stream_obj.download(filepath=path_to_download)
                logging.debug("DOWNLOADED=> " + slugify_video_title)
                notifyAboutTheService("Downloded", slugify_video_title)
            except Exception as e:
                notifyAboutTheService("Error Downloading", slugify_video_title)
                logging.debug("Unable to download. Error occured")
                logging.debug(e)
        else:
            logging.debug("File Already Exists! Path: " + path_to_download)
    else:
        logging.debug(
            "Unable to find the video file at this time. Timeout!! Try again later."
        )
    )
    # parser.add_argument('-a','--audio',action='store_true',help='Download in audio format.')
    args = parser.parse_args()

    if args.link:
        # logging.debug('link provide   '+args.link)
        if args.link.startswith('https://www.youtube.com/watch?v='):
            if args.video:
                if args.highquality:
                    start_high_quality_video_download(args.link)
                else:
                    start_video_download(args.link)
            else:
                start_audio_download(args.link)
        else:
            logging.debug("Link provided is not valid")
    else:
        url = pyperclip.paste() if len(pyperclip.paste()) > 10 \
        and pyperclip.paste().startswith('https://www.youtube.com/watch?v=') else None
        if url != None:
            if args.video:
                if args.highquality:
                    start_high_quality_video_download(url)
                else:
                    start_video_download(url)
            else:
                start_audio_download(url)
        else:
            logging.debug('No link found in the clipboard')
            sys.exit()