Exemplo n.º 1
0
def merge_segments():
    try:
        if pil.run_at_finish:
            try:
                thread = threading.Thread(target=helpers.run_command,
                                          args=(pil.run_at_finish, ))
                thread.daemon = True
                thread.start()
                logger.binfo("Launched finish command: {:s}".format(
                    pil.run_at_finish))
            except Exception as e:
                logger.warn('Could not execute command: {:s}'.format(str(e)))

        live_mp4_file = '{}{}_{}_{}_{}_live.mp4'.format(
            pil.dl_path, pil.datetime_compat, pil.dl_user,
            pil.livestream_obj.get('id'), pil.epochtime)

        live_segments_path = os.path.normpath(
            pil.broadcast_downloader.output_dir)

        if pil.segments_json_thread_worker and pil.segments_json_thread_worker.is_alive(
        ):
            pil.segments_json_thread_worker.join()

        if pil.comment_thread_worker and pil.comment_thread_worker.is_alive():
            logger.info("Waiting for comment downloader to finish.")
            pil.comment_thread_worker.join()
        logger.info('Merging downloaded files into video.')
        try:
            pil.broadcast_downloader.stitch(
                live_mp4_file, cleartempfiles=pil.clear_temp_files)
            logger.info('Successfully merged downloaded files into video.')
            if pil.clear_temp_files:
                helpers.remove_temp_folder()
            helpers.remove_lock()
        except ValueError as e:
            logger.separator()
            logger.error('Could not merge downloaded files: {:s}'.format(
                str(e)))
            if os.listdir(live_segments_path):
                logger.separator()
                logger.binfo(
                    "Segment directory is not empty. Trying to merge again.")
                logger.separator()
                pil.assemble_arg = live_mp4_file.replace(
                    ".mp4", "_downloads.json")
                assembler.assemble(user_called=False)
            else:
                logger.separator()
                logger.error(
                    "Segment directory is empty. There is nothing to merge.")
                logger.separator()
            helpers.remove_lock()
        except Exception as e:
            logger.error('Could not merge downloaded files: {:s}'.format(
                str(e)))
            helpers.remove_lock()
    except KeyboardInterrupt:
        logger.binfo('Aborted merging process, no video was created.')
        helpers.remove_lock()
Exemplo n.º 2
0
def start():
    if pil.args.downloadfollowing:
        if not pil.dl_lives:
            logger.binfo("Livestream downloading is disabled either with an argument or in the config file.")
            logger.separator()
        if not pil.dl_replays:
            logger.binfo("Replay downloading is disabled either with an argument or in the config file.")
            logger.separator()
        if not helpers.command_exists("pyinstalive"):
            logger.error("PyInstaLive must be properly installed when using the -df argument.")
            logger.separator()
        else:
            dlfuncs.download_following()
    else:
        if not helpers.download_folder_has_lockfile():
            helpers.create_lock_user()
            checking_self = pil.dl_user == pil.ig_api.authenticated_user_name
            if dlfuncs.get_broadcasts_info():
                if pil.dl_lives:
                    if checking_self:
                        logger.warn("Login with a different account to download your own livestreams.")
                    elif pil.livestream_obj:
                        logger.info("Livestream available, starting download.")
                        dlfuncs.download_livestream()
                    else:
                        logger.info('There are no available livestreams.')
                else:
                    logger.binfo("Livestream downloading is disabled either with an argument or in the config file.")

                logger.separator()

                if pil.dl_replays:
                    if pil.replays_obj:
                        logger.info(
                            '{:s} available, beginning download.'.format("Replays" if len(
                                pil.replays_obj) > 1 else "Replay"))
                        dlfuncs.download_replays()
                    else:
                        logger.info('There are no available replays{:s}.'.format(" saved on your account" if checking_self else ""))
                else:
                    logger.binfo("Replay downloading is disabled either with an argument or in the config file.")

            helpers.remove_lock()
            logger.separator()
        else:
            logger.warn("Lock file is already present for this user, there is probably another download ongoing.")
            logger.warn("If this is not the case, manually delete the file '{:s}' and try again.".format(
                pil.dl_user + '.lock'))
            logger.separator()
Exemplo n.º 3
0
def download_replays():
    try:
        try:
            logger.info('Amount of replays    : {:s}'.format(
                str(len(pil.replays_obj))))
            for replay_index, replay_obj in enumerate(pil.replays_obj):
                bc_dash_manifest = parseString(replay_obj.get(
                    'dash_manifest')).getElementsByTagName('Period')
                bc_duration_raw = bc_dash_manifest[0].getAttribute("duration")
                bc_minutes = (bc_duration_raw.split("H"))[1].split("M")[0]
                bc_seconds = ((
                    bc_duration_raw.split("M"))[1].split("S")[0]).split('.')[0]
                logger.info(
                    'Replay {:s} duration    : {:s} minutes and {:s} seconds'.
                    format(str(replay_index + 1), bc_minutes, bc_seconds))
        except Exception as e:
            logger.warn(
                "An error occurred while getting replay duration information: {:s}"
                .format(str(e)))
        logger.separator()
        logger.info("Downloading replays, press [CTRL+C] to abort.")
        logger.separator()
        for replay_index, replay_obj in enumerate(pil.replays_obj):
            exists = False
            pil.livestream_obj = replay_obj
            if Constants.PYTHON_VER[0][0] == '2':
                directories = (os.walk(pil.dl_path).next()[1])
            else:
                directories = (os.walk(pil.dl_path).__next__()[1])

            for directory in directories:
                if (str(replay_obj.get('id'))
                        in directory) and ("_live_" not in directory):
                    logger.binfo(
                        "Already downloaded a replay with ID '{:s}'.".format(
                            str(replay_obj.get('id'))))
                    exists = True
            if not exists:
                current = replay_index + 1
                logger.info(
                    "Downloading replay {:s} of {:s} with ID '{:s}'.".format(
                        str(current), str(len(pil.replays_obj)),
                        str(replay_obj.get('id'))))
                pil.live_folder_path = '{}{}_{}_{}_{}_replay_downloads'.format(
                    pil.dl_path, pil.datetime_compat, pil.dl_user,
                    pil.livestream_obj.get('id'), pil.epochtime)
                broadcast_downloader = replay.Downloader(
                    mpd=replay_obj.get('dash_manifest'),
                    output_dir=pil.live_folder_path,
                    user_agent=pil.ig_api.user_agent,
                    ffmpeg_binary=pil.ffmpeg_path)
                if pil.use_locks:
                    helpers.create_lock_folder()
                replay_mp4_file = '{}{}_{}_{}_{}_replay.mp4'.format(
                    pil.dl_path, pil.datetime_compat, pil.dl_user,
                    pil.livestream_obj.get('id'), pil.epochtime)

                comments_json_file = '{}{}_{}_{}_{}_replay_comments.json'.format(
                    pil.dl_path, pil.datetime_compat, pil.dl_user,
                    pil.livestream_obj.get('id'), pil.epochtime)

                pil.comment_thread_worker = threading.Thread(
                    target=get_replay_comments, args=(comments_json_file, ))

                broadcast_downloader.download(
                    replay_mp4_file, cleartempfiles=pil.clear_temp_files)
                if pil.clear_temp_files:
                    helpers.remove_temp_folder()
                if pil.dl_comments:
                    logger.info("Downloading replay comments.")
                    try:
                        get_replay_comments(comments_json_file)
                    except Exception as e:
                        logger.error(
                            'An error occurred while downloading comments: {:s}'
                            .format(str(e)))

                logger.info("Finished downloading replay {:s} of {:s}.".format(
                    str(current), str(len(pil.replays_obj))))
                helpers.remove_lock()

                if current != len(pil.replays_obj):
                    logger.separator()

        logger.separator()
        logger.info("Finished downloading all available replays.")
        helpers.remove_lock()
    except Exception as e:
        logger.error('Could not save replay: {:s}'.format(str(e)))
        helpers.remove_lock()
    except KeyboardInterrupt:
        logger.separator()
        logger.binfo('The download has been aborted by the user, exiting.')
        logger.separator()
        helpers.remove_temp_folder()
        helpers.remove_lock()
Exemplo n.º 4
0
def download_livestream():
    try:

        def print_status(sep=True):
            if pil.do_heartbeat:
                heartbeat_info = pil.ig_api.broadcast_heartbeat_and_viewercount(
                    pil.livestream_obj.get('id'))
            viewers = pil.livestream_obj.get('viewer_count', 0)
            if sep:
                logger.separator()
            else:
                logger.info('Username    : {:s}'.format(pil.dl_user))
            logger.info('Viewers     : {:s} watching'.format(str(
                int(viewers))))
            logger.info('Airing time : {:s}'.format(get_stream_duration(0)))
            if pil.do_heartbeat:
                logger.info('Status      : {:s}'.format(
                    heartbeat_info.get('broadcast_status').title()))
                return heartbeat_info.get('broadcast_status') not in [
                    'active', 'interrupted'
                ]
            else:
                return None

        mpd_url = (pil.livestream_obj.get('dash_manifest')
                   or pil.livestream_obj.get('dash_abr_playback_url')
                   or pil.livestream_obj.get('dash_playback_url'))

        pil.live_folder_path = '{}{}_{}_{}_{}_live_downloads'.format(
            pil.dl_path, pil.datetime_compat, pil.dl_user,
            pil.livestream_obj.get('id'), pil.epochtime)
        pil.broadcast_downloader = live.Downloader(
            mpd=mpd_url,
            output_dir=pil.live_folder_path,
            user_agent=pil.ig_api.user_agent,
            max_connection_error_retry=3,
            duplicate_etag_retry=30,
            callback_check=print_status,
            mpd_download_timeout=3,
            download_timeout=3,
            ffmpeg_binary=pil.ffmpeg_path)
    except Exception as e:
        logger.error('Could not start downloading livestream: {:s}'.format(
            str(e)))
        logger.separator()
        helpers.remove_lock()
    try:
        broadcast_owner = pil.livestream_obj.get('broadcast_owner',
                                                 {}).get('username')
        try:
            broadcast_guest = pil.livestream_obj.get('cobroadcasters',
                                                     {})[0].get('username')
        except Exception:
            broadcast_guest = None
        if broadcast_owner != pil.dl_user:
            logger.binfo(
                'This livestream is a dual-live, the owner is "{}".'.format(
                    broadcast_owner))
            broadcast_guest = None
        if broadcast_guest:
            logger.binfo(
                'This livestream is a dual-live, the current guest is "{}".'.
                format(broadcast_guest))
            pil.has_guest = broadcast_guest
        logger.separator()
        print_status(False)
        logger.separator()
        helpers.create_lock_folder()
        pil.segments_json_thread_worker = threading.Thread(
            target=helpers.generate_json_segments)
        pil.segments_json_thread_worker.start()
        logger.info('Downloading livestream, press [CTRL+C] to abort.')

        if pil.run_at_start:
            try:
                thread = threading.Thread(target=helpers.run_command,
                                          args=(pil.run_at_start, ))
                thread.daemon = True
                thread.start()
                logger.binfo("Launched start command: {:s}".format(
                    pil.run_at_start))
            except Exception as e:
                logger.warn('Could not launch command: {:s}'.format(str(e)))

        if pil.dl_comments:
            try:
                comments_json_file = '{}{}_{}_{}_{}_live_comments.json'.format(
                    pil.dl_path, pil.datetime_compat, pil.dl_user,
                    pil.livestream_obj.get('id'), pil.epochtime)
                pil.comment_thread_worker = threading.Thread(
                    target=get_live_comments, args=(comments_json_file, ))
                pil.comment_thread_worker.start()
            except Exception as e:
                logger.error(
                    'An error occurred while downloading comments: {:s}'.
                    format(str(e)))
        pil.broadcast_downloader.run()
        logger.separator()
        logger.info("The livestream has been ended by the user.")
        logger.separator()
        logger.info('Airtime duration  : {}'.format(get_stream_duration(0)))
        logger.info('Download duration : {}'.format(get_stream_duration(1)))
        logger.info('Missing (approx.) : {}'.format(get_stream_duration(2)))
        logger.separator()
        merge_segments()
    except KeyboardInterrupt:
        logger.separator()
        logger.binfo('The download has been aborted.')
        logger.separator()
        logger.info('Airtime duration  : {}'.format(get_stream_duration(0)))
        logger.info('Download duration : {}'.format(get_stream_duration(1)))
        logger.info('Missing (approx.) : {}'.format(get_stream_duration(2)))
        logger.separator()
        if not pil.broadcast_downloader.is_aborted:
            pil.broadcast_downloader.stop()
            merge_segments()