Example #1
0
def add_theme_to_hashtable(threads, directory):
    """ Create a hashtable from the themes.

        Args:
            theads (int): How many threads to use.
            directory (None, str): If you don't pass a directory will select the default one

        Returns:
            None

    """
    from bw_plex.audfprint.audfprint import multiproc_add
    global HT
    HT = get_hashtable()

    a = analyzer()
    all_files = []

    for root, _, files in os.walk(directory or THEMES):
        for f in files:
            fp = os.path.join(root, f)
            # We need to check this since when themes are downloaded
            # They sometimes get a 0b files.
            if os.path.exists(fp) and os.path.getsize(fp):
                all_files.append(fp)

    def report(s):  # this shitty reporter they want sucks balls..
        pass  #print(s)

    LOG.debug('Creating hashtable, this might take a while..')

    multiproc_add(a, HT, iter(all_files), report, threads)
    if HT and HT.dirty:
        HT.save(FP_HASHES)
Example #2
0
def add_ref_frame(fp, t, tvdbid, timestamp, gui):
    import cv2

    if gui:
        from bw_plex.tools import play
        play(fp, key=tvdbid)
        return

    if fp.endswith(('.mp4', '.mkv', '.avi')) and timestamp:

        cap = cv2.VideoCapture(fp)
        ms = to_ms(timestamp)
        cap.set(cv2.CAP_PROP_POS_MSEC, ms)
        ret, frame = cap.read()
    else:
        # So its a image...
        frame = fp

    frames_hash = create_imghash(frame)
    frames_hex = ''.join(hex(i) for i in frames_hash.flatten())

    with session_scope() as se:
        try:
            se.query(Reference_Frame).filter_by(hex=frames_hex).one()
            click.echo('This frame already exist in the db')
        except NoResultFound:

            frm = Reference_Frame(hex=frames_hex, type=t, tvdbid=tvdbid)
            se.add(frm)
            LOG.debug('Added %s to Reference_Frame table hex %s tvdbid %s', fp,
                      frames_hex, tvdbid)
Example #3
0
def get_pms(url=None,
            token=None,
            username=None,
            password=None,
            servername=None,
            verify_ssl=None):  # pragma: no cover

    url = url or CONFIG['server'].get('url')
    token = token or CONFIG['server'].get('token')
    verify_ssl = verify_ssl or CONFIG['server'].get('verify_ssl', False)
    servername = servername or CONFIG['server'].get('name')

    if url and token:
        sess = requests.Session()
        if not verify_ssl:
            sess.verify = False
        PMS = PlexServer(url, token, sess)

    elif username and password and servername:
        acc = MyPlexAccount(username, password)
        PMS = acc.resource(servername).connect()

    assert PMS is not None, 'You need to add a url and token or username password and servername'

    LOG.debug('Getting server %s', PMS.friendlyName)

    return PMS
Example #4
0
def get_pms(url=None,
            token=None,
            username=None,
            password=None,
            servername=None,
            verify_ssl=None):
    from plexapi.myplex import MyPlexAccount
    from plexapi.server import PlexServer

    url = url or CONFIG.get('url')
    token = token or CONFIG.get('token')
    verify_ssl = verify_ssl or CONFIG.get('verify_ssl', False)

    if url and token:
        sess = requests.Session()
        if not verify_ssl:
            sess.verify = False
        PMS = PlexServer(url, token, sess)

    elif username and password and servername:
        acc = MyPlexAccount(username, password)
        PMS = acc.resource(servername).connect()

    LOG.debug('Getting server %s', PMS.friendlyName)

    return PMS
Example #5
0
def edl_dict_to_metadata_file(path, eld):
    """Convert a .edl file to a ffmepg metadata file.
       This way we can add chapters to shows as this isnt suppored by plex

       Args:
            path (str): path to the edl we should use.

       Return
            path to metadata file.
    """
    # Should we check if this file has metadata/chapters so we dont overwrite it
    # Lets come back to this later.
    #if not os.path.isfile(path) and path.endswith('.edl'):
    #    return
    header = ';FFMETADATA1\ntitle=%s\nartist=Made by bw_plex\n\n' % os.path.splitext(os.path.basename(path))[0]

    chapter_template = """[CHAPTER]\nTIMEBASE=1/1000\nSTART=%s\nEND=%s\ntitle=%s\n\n"""

    meta_name = os.path.splitext(path)[0] + '.metadata'

    with open(meta_name, 'w') as mf:
        mf.write(header)
        for key, value in eld.items():
            mf.write(chapter_template % (float(value[0]) * 1000, float(value[1]) * 1000, key))

    LOG.debug('Created a metadatafile %s', meta_name)

    return meta_name
Example #6
0
def get_offset_end(vid, hashtable, check_if_missing=False):
    an = analyzer()
    match = matcher()

    # Or should we just check here?? untested.
    if vid not in hashtable.names and check_if_missing:
        an.ingest(vid, hashtable)

    start_time = -1
    end_time = -1

    t_hop = an.n_hop / float(an.target_sr)
    rslts, dur, nhash = match.match_file(an, hashtable, vid,
                                         1)  # The number does not matter...

    for (tophitid, nhashaligned, aligntime, nhashraw, rank, min_time,
         max_time) in rslts:
        #  print(tophitid, nhashaligned, aligntime, nhashraw, rank, min_time, max_time)
        end_time = max_time * t_hop
        start_time = min_time * t_hop
        LOG.debug(
            'Theme song started at %s (%s) in ended at %s (%s)' %
            (start_time, to_time(start_time), end_time, to_time(end_time)))
        return start_time, end_time

    LOG.debug('no result just returning -1')

    return start_time, end_time
Example #7
0
def download_subtitle(episode):
    import srt
    episode.reload()
    LOG.debug('Downloading subtitle from PMS')
    pms = episode._server
    to_dl = []
    all_subs = []

    for part in episode.iterParts():
        if part.subtitleStreams():
            for sub in part.subtitleStreams():
                if sub.key and sub.codec == 'srt':
                    to_dl.append(
                        pms.url('%s?download=1' % sub.key, includeToken=True))

    for dl_url in to_dl:
        r = requests.get(dl_url)
        r.raise_for_status()
        if r:
            try:
                a_sub = list(srt.parse(r.text))
                all_subs.append(a_sub)
            except ValueError:
                LOG.exception('Failed to parse subtitle')

    return all_subs
Example #8
0
def cli(debug, username, password, servername, url, token, config, verify_ssl):
    """ Entry point for the CLI."""
    global PMS
    global CONFIG

    if debug:
        LOG.setLevel(logging.DEBUG)
    else:
        LOG.setLevel(logging.INFO)

    if config and os.path.isfile(config):
        CONFIG = read_or_make(config)

    url = url or CONFIG.get('url')
    token = token or CONFIG.get('token')
    verify_ssl = verify_ssl or CONFIG.get('verify_ssl')

    if url and token or username and password:

        PMS = get_pms(url=url,
                      token=token,
                      username=username,
                      password=password,
                      servername=servername,
                      verify_ssl=verify_ssl)
Example #9
0
def download_subtitle(episode):

    episode.reload()
    LOG.debug('Downloading subtitle from PMS')
    pms = episode._server
    to_dl = []
    all_subs = []

    for part in episode.iterParts():
        if part.subtitleStreams():
            for sub in part.subtitleStreams():
                if sub.key and sub.codec in FILE_EXTENSION_TO_FORMAT_IDENTIFIER.values(
                ):
                    to_dl.append(
                        pms.url('%s?download=1' % sub.key, includeToken=True))

    for dl_url in to_dl:
        r = episode._server._session.get(dl_url)
        r.raise_for_status()
        if r:
            try:
                subt = [
                    sub
                    for sub in SSAFile.from_string(r.text, encoding=r.encoding)
                ]
                all_subs.append(subt)
            except (IOError, pysubs2.exceptions.UnknownFPSError,
                    pysubs2.exceptions.UnknownFormatIdentifierError,
                    pysubs2.exceptions.FormatAutodetectionError):
                LOG.exception('Failed to parse subtitle')

    return all_subs
Example #10
0
def get_pms(url=None,
            token=None,
            username=None,
            password=None,
            servername=None,
            verify_ssl=None):  # pragma: no cover

    url = url or CONFIG['server'].get('url')
    token = token or CONFIG['server'].get('token')
    verify_ssl = verify_ssl or CONFIG['server'].get('verify_ssl', False)
    servername = servername or CONFIG['server'].get('name')

    if url and token:
        url = url.rstrip('/')
        sess = requests.Session()
        if not verify_ssl:
            # Disable the urllib3 warning as the user
            # has choosen to not verify the http request.
            # why the f**k isnt this default?
            requests.packages.urllib3.disable_warnings()
            sess.verify = False
        PMS = PlexServer(url, token, sess)

    elif username and password and servername:
        acc = MyPlexAccount(username, password)
        PMS = acc.resource(servername).connect()

    assert PMS is not None, 'You need to add a url and token or username password and servername'

    LOG.debug('Getting server %s', PMS.friendlyName)

    return PMS
Example #11
0
def convert_and_trim_to_mp3(afile,
                            fs=8000,
                            trim=None,
                            outfile=None):  # pragma: no cover
    if outfile is None:
        tmp = tempfile.NamedTemporaryFile(mode='r+b',
                                          prefix='offset_',
                                          suffix='.mp3')
        tmp_name = tmp.name
        tmp.close()
        outfile = tmp_name

    if os.name == 'nt' and '://' not in afile:
        q_file = '"%s"' % afile
    else:
        q_file = afile

    cmd = [
        'ffmpeg', '-i', q_file, '-ss', '0', '-t',
        str(trim), '-codec:a', 'libmp3lame', '-qscale:a', '6', outfile
    ]

    LOG.debug('calling ffmepg with %s' % ' '.join(cmd))

    if os.name == 'nt':
        cmd = '%s' % ' '.join(cmd)

    psox = subprocess.Popen(cmd, stderr=subprocess.PIPE)

    o, e = psox.communicate()
    if not psox.returncode == 0:
        print(e)
        raise Exception("FFMpeg failed")

    return outfile
Example #12
0
 def get_themes(self):
     d = defaultdict(list)
     for n in self.names:
         try:
             rk = os.path.basename(n).split('__')[1]
             d[int(rk)].append(n)
         except (IndexError, TypeError):
             LOG.exception('Some crap happend with', n)
     return d
Example #13
0
    def match_event(event):
        val = radio.value_selected

        h = ImageHash(create_imghash(CURR_FRAME))

        with session_scope() as se:
            rf = Reference_Frame(hex=str(h), type=val, tvdbid=KEY)
            LOG.debug('Added %s %s from %s in %s', str(h), val, POS, first)
            se.add(rf)
Example #14
0
    def load(self, name=None):
        if name is None:
            self.__filename = name

        self.load_pkl(name)
        LOG.debug('Files in the hashtable')
        for n in self.names:
            LOG.debug(n)

        return self
Example #15
0
def download_theme(media, ht, theme_source=None, url=None):
    if media.TYPE == 'show':
        name = media.title
        rk = media.ratingKey
        _theme = media.theme
    else:
        name = media.grandparentTitle
        rk = media.grandparentRatingKey
        _theme = media.grandparentTheme
        if _theme is None:
            _theme = media.show().theme

    pms = media._server

    if theme_source is None:
        theme_source = CONFIG['tv'].get('theme_source', 'all')

    if theme_source == 'youtube':
        theme = search_for_theme_youtube(name, rk, THEMES, url=url)

    elif theme_source == 'tvtunes':
        theme = search_tunes(name, rk, url=url)
        theme = list(itertools.chain.from_iterable(theme.values()))

    elif theme_source == 'plex' and _theme is not None:
        theme = pms.url(_theme, includeToken=True)
        LOG.debug('Downloading theme via plex %s', theme)

    elif theme_source == 'all':
        theme = []
        st = search_tunes(name, rk, url=url)
        st_res = list(itertools.chain.from_iterable(st.values()))
        theme.extend(st_res)

        if _theme is not None:
            theme.append(pms.url(_theme, includeToken=True))

        theme.append(search_for_theme_youtube(name, rk, THEMES, url=url))

    if not isinstance(theme, list):
        theme = [theme]

    final = []
    for th in theme:
        LOG.debug('Download theme using source %s', th)
        # Filename is just added so we can pass a url to convert_and_trim
        th = convert_and_trim(th,
                              fs=11025,
                              theme=True,
                              filename='%s__%s__%s' %
                              (name, rk, int(time.time())))
        analyzer().ingest(ht, th)
        final.append(th)

    return final
Example #16
0
 def inner(*args, **kwargs):
     try:
         if kwargs:
             return func(*args, **kwargs)
         else:
             return func(*args)
     except:
         err = "There was an exception in "
         err += func.__name__
         LOG.exception(err)
         raise
Example #17
0
def manually_correct_theme(name, url, type, rk, just_theme,
                           remove_old_theme):  # pragma: no cover
    """Set the correct fingerprint of the show in the hashes.db and
       process the eps of that show in the db against the new theme fingerprint.

       Args:
            name (str): name of the show
            url (str): the youtube/tvtunes url or filepath to the correct theme.
            type (str): What source to use for themes.
            rk (str): ratingkey of that show. Pass auto if your lazy.
            just_theme (bool): just add the theme song not reprocess stuff.
            remove_old_theme (bool): Removes all the old themes of this show

       Returns:
            None
    """
    global HT
    HT = get_hashtable()

    # Assist for the lazy bastards..
    if rk == 'auto':
        items = PMS.search(name)
        items = [i for i in items if i and i.TYPE == 'show']
        items = choose('Select correct show', items, lambda x: '%s %s' %
                       (x.title, x.TYPE))
        if items:
            rk = items[0].ratingKey

    if remove_old_theme:
        themes = HT.get_theme(items[0])
        for th in themes:
            LOG.debug('Removing %s from the hashtable', th)
            HT.remove(th)

    # Download the themes depending on the manual option or config file.
    download_theme(items[0], HT, theme_source=type, url=url)
    to_pp = []

    if just_theme:
        return

    if rk:
        with session_scope() as se:
            # Find all episodes of this show.
            item = se.query(Processed).filter_by(grandparentRatingKey=rk)

            for i in item:
                to_pp.append(PMS.fetchItem(i.ratingKey))
                # Prob should have used edit, but we do this so we can use process_to_db.
                se.delete(i)

        for media in to_pp:
            process_to_db(media)
Example #18
0
    def get_theme(self, media):
        if media.TYPE == 'show':
            name = media.title
            rk = media.ratingKey
        else:
            rk = media.grandparentRatingKey
            name = media.grandparentTitle

        d = self.get_themes().get(rk, [])
        LOG.debug('%s has %s themes', name, len(d))

        return d
Example #19
0
def manually_correct_theme(name, url, type, rk, just_theme):
    """Set the correct fingerprint of the show in the hashes.db and
       process the eps of that show in the db against the new theme fingerprint.

       Args:
            name (str): name of the show
            url (str): the youtube url to the correct theme.
            rk (str): ratingkey of that show. Pass auto if your lazy.
            just_theme (bool): just add the theme song.

       Returns:
            None
    """
    global HT
    HT = get_hashtable()

    # Assist for the lazy bastards..
    if rk == 'auto':
        items = PMS.search(name)
        items = [i for i in items if i and i.TYPE == 'show']
        items = choose('Select correct show', items, lambda x: '%s %s' %
                       (x.title, x.TYPE))
        if items:
            rk = items[0].ratingKey

    # I dont think think themes be removed anymore as one show can now have several themes
    # also it dont remove the files in THEMES, this is intended!.
    themes = HT.get_theme(items[0])
    for th in themes:
        LOG.debug('Removing %s from the hashtable', th)
        HT.remove(th)

    # Download the themes depending on the manual option or config file.
    theme_path = download_theme(items[0], HT, theme_source=type, url=url)

    to_pp = []
    # THis should be removed, if you just want to download the theme. use find theme.
    if just_theme:
        return

    if rk:
        with session_scope() as se:
            # Find all episodes of this show.
            item = se.query(Preprocessed).filter_by(grandparentRatingKey=rk)

            for i in item:
                to_pp.append(PMS.fetchItem(i.ratingKey))
                # Prob should have edit, but we do this so we can use process_to_db.
                se.delete(i)

        for media in to_pp:
            process_to_db(media)
Example #20
0
def load_themes():
    LOG.debug('Loading themes')
    items = os.listdir(THEMES)

    for i in items:
        fp = os.path.join(THEMES, i)
        LOG.debug(fp)
        if fp:
            try:
                show_rating = i.split('__')[1].split('.')[0]
                SHOWS[int(show_rating)] = fp
            except IndexError:
                pass
Example #21
0
 def inner():
     try:
         func()
     except plexapi.exceptions.BadRequest:
         try:
             LOG.info(
                 'Failed to reach the client directly, trying via server.'
             )
             correct_client.proxyThroughServer()
             func()
         except:  # pragma: no cover
             correct_client.proxyThroughServer(value=False)
             raise
Example #22
0
def write_chapters_to_file(path, input_edl=None, replace=True, cleanup=True):
    """Use ffmpeg to add chapters to a videofile.mf_file


       Args:
            path(str): path to the video file we should add chapters to
            input_edl (str): path the the edl.
            replace (bool): Default True
            cleanup(bool): Default False, remove the .metadatafile
                           after chapters has been added.

       Return:
            path


    """
    if input_edl is None:
        input_edl = has_edl(path)

    mf_file = edl_to_metadata_file(input_edl)
    mf_file = str(mf_file)

    outfile, ext = os.path.splitext(path)
    outfile = outfile + '__bw_plex_meta' + ext

    cmd = [
        'ffmpeg', '-i', path, '-i', mf_file, '-map_metadata', '1', '-codec',
        'copy', outfile
    ]

    proc = subprocess.Popen(cmd)
    code = proc.wait()
    if code != 0:
        LOG.debug('Failed to write_chapters_to_file %s', code)

    # Try to replace the orginal with the one with have added
    # chapters too.
    if replace:
        for i in range(3):
            try:
                shutil.move(outfile, path)
                break
            except OSError:
                time.sleep(1)

    if cleanup:
        os.remove(mf_file)
        LOG.debug('Deleted %s', mf_file)

    return path
Example #23
0
        def jump(item, sessionkey, sec=None, action=None):  # pragma: no cover

            if sec is None:
                sec = best_time(item)

            if action:
                POOL.apply_async(client_action, args=(sec, sessionkey, action))
                return

            if sessionkey not in JUMP_LIST:
                LOG.debug('Called jump with %s %s %s %s', item.prettyname,
                          sessionkey, sec, action)
                JUMP_LIST.append(sessionkey)
                POOL.apply_async(client_action, args=(sec, sessionkey, action))
Example #24
0
def client_jump_to(offset=None, sessionkey=None):
    """Seek the client to the offset.

       Args:
            offset(int): Default None
            sessionkey(int): So we made sure we control the correct client.

       Returns:
            None
    """
    global JUMP_LIST
    LOG.debug('Called jump with %s %s %s', offset, to_time(offset), sessionkey)

    if offset == -1:
        return

    conf_clients = CONFIG.get('clients', [])
    conf_users = CONFIG.get('users', [])

    for media in PMS.sessions():
        # Find the client.. This client does not have the correct address
        # or 'protocolCapabilities' so we have to get the correct one.
        # or we can proxy thru the server..
        if sessionkey and int(sessionkey) == media.sessionKey:
            client = media.players[0]
            user = media.usernames[0]
            # LOG.debug('client %s %s', client.title, (media.viewOffset / 1000))

            # Check that this client is allowed.
            if conf_clients and client.title not in conf_clients:
                LOG.debug('Client %s is not whitelisted', client.title)
                return

            # Check that this user is allowed.
            if conf_users and user not in conf_users:
                LOG.debug('User %s is not whitelisted', user)
                return

            # To stop processing. from func task if we have used to much time..
            # This will not work if/when credits etc are added. Need a better way.
            # if offset <= media.viewOffset / 1000:
            #    LOG.debug('Didnt jump because of offset')
            #    return

            # This does not work on plex web since the f****r returns
            # the local url..
            client = PMS.client(client.title).connect()
            client.proxyThroughServer()
            client.seekTo(int(offset * 1000))
            LOG.debug('Jumped %s %s to %s %s', user, client.title, offset,
                      media._prettyfilename())

            # Some clients needs some time..
            # time.sleep(0.2)
            # client.play()
            JUMP_LIST.remove(sessionkey)
            #time.sleep(1)

            return
Example #25
0
def set_manual_theme_time(showname, season, episode, type, start,
                          end):  # pragma: no cover
    """Set a manual start and end time for a theme.

       Args:
           showname(str): name of the show you want to find
           season(int): season number fx 1
           episode(int): episode number 1
           type(str): theme, credit # Still TODO Stuff for credits
           start(int, str): This can be in seconds or MM:SS format
           start(int, str): This can be in seconds or MM:SS format

       Returns:
            None
    """
    LOG.debug('Trying to set manual time')
    result = PMS.search(showname)

    if result:

        items = choose('Select show', result, 'title')
        show = items[0]
        ep = show.episode(season=season, episode=episode)

        if ep:
            with session_scope() as se:
                item = se.query(Processed).filter_by(
                    ratingKey=ep.ratingKey).one()
                start = to_sec(start)
                end = to_sec(end)

                if type == 'ffmpeg':
                    item.correct_ffmpeg = end

                elif type == 'theme':
                    if start:
                        item.correct_time_start = start

                    if end:
                        item.correct_time_end = end
                elif type == 'credits':
                    if start:
                        item.correct_credits_start = start

                    if end:
                        item.correct_credits_end = end

                LOG.debug('Set correct_time %s for %s to start %s end %s',
                          type, ep._prettyfilename(), start, end)
Example #26
0
def manually_correct_theme(name, url, type, rk, just_theme):
    """Set the correct fingerprint of the show in the hashes.db and
       process the eps of that show in the db against the new theme fingerprint.

       Args:
            name (str): name of the show
            url (str): the youtube url to the correct theme.
            rk (str): ratingkey of that show. Pass auto if your lazy.
            just_theme (bool): just add the theme song.

       Returns:
            None
    """
    global HT
    HT = get_hashtable()

    # Assist for the lazy bastards..
    if rk == 'auto':
        item = PMS.search(name)
        item = choose('Select correct show', item, lambda x: '%s %s' % (x.title, x.TYPE))
        if item:
            rk = item[0].ratingKey

    theme_path = search_for_theme_youtube(name, rk=rk, url=url, save_path=THEMES)

    for fp in HT.names:
        if os.path.basename(fp).lower() == name.lower() and os.path.exists(fp):
            LOG.debug('Removing %s from the hashtable', fp)
            HT.remove(fp)

    analyzer().ingest(HT, theme_path)
    # HT.save(FP_HASHES)
    to_pp = []

    if just_theme:
        return

    if rk:
        with session_scope() as se:
            item = se.query(Preprocessed).filter_by(grandparentRatingKey=rk)

            for i in item:
                to_pp.append(PMS.fetchItem(i.ratingKey))
                # Prob should have edit, but we do this so we can use process_to_db.
                se.delete(i)

        for media in to_pp:
            process_to_db(media)
Example #27
0
def create_edl_from_db(t, save_path):
    with session_scope() as se:
        db_items = se.query(Processed).all()
        for item in db_items:
            # Maybe remove this later?
            if save_path:
                loc = edl.create_edl_path(
                    os.path.join(save_path, os.path.basename(item.location)))
            else:
                loc = item.location

            try:
                t = edl.write_edl(loc, edl.db_to_edl(item, edl.TYPES[t]))
                click.echo('Wrote %s' % t)
            except:
                LOG.exception('Failed to write edl.')
Example #28
0
def users_pms(pms, user):  # pragma: no cover
    """Login on your server using the users access credentials."""
    from plexapi.exceptions import NotFound
    LOG.debug('Logging in on PMS as %s', user)
    acc = pms._server.myPlexAccount()
    try:
        usr = acc.user(user)
    except NotFound:
        # We fail to find the correct user if the passed user is the owner..
        # We we simply return the owner pms as we already have that.
        # TODO this might be a issue, see if we cant handle this another way using plexapi.
        LOG.debug('returning org pms')
        return pms
    token = usr.get_token(pms.machineIdentifier)
    users_pms = PlexServer(pms._baseurl, token)
    return users_pms
Example #29
0
def write_chapters_to_file(path, input_edl=None, replace=True, cleanup=True):
    """Use ffmpeg to add chapters to a videofile.mf_file


       Args:
            path(str): path to the video file we should add chapters to
            input_edl (str): path the the edl.
            replace (bool): Default True
            cleanup(bool): Default False, remove the .metadatafile
                           after chapters has been added.

       Return:
            path


    """

    if 'https://' or 'http://' in path:
        LOG.debug(
            "Can't add chapters to as we dont have access to the file on the file system"
        )

    mf_file = edl_dict_to_metadata_file(path, input_edl)
    mf_file = str(mf_file)

    outfile, ext = os.path.splitext(path)
    outfile = outfile + '__bw_plex_meta' + ext

    cmd = [
        'ffmpeg', '-i', path, '-i', mf_file, '-map_metadata', '1', '-codec',
        'copy', outfile
    ]

    proc = subprocess.Popen(cmd,
                            stderr=subprocess.PIPE,
                            stdout=subprocess.PIPE)
    code = proc.wait()
    if code != 0:
        LOG.debug('Failed to write_chapters_to_file %s', code)

    # Try to replace the orginal with the one with have added
    # chapters too.
    if replace:
        for _ in range(3):
            try:
                shutil.move(outfile, path)
                break
            except OSError:
                time.sleep(1)

    if cleanup:
        os.remove(mf_file)
        LOG.debug('Deleted %s', mf_file)

    LOG.debug('writing chapters to file using command %s', ' '.join(cmd))

    return path
Example #30
0
 def inner():
     try:
         func()
     except (plexapi.exceptions.BadRequest,
             requests.exceptions.ConnectionError,
             requests.exceptions.Timeout,
             requests.exceptions.TooManyRedirects,
             requests.exceptions.HTTPError):
         try:
             LOG.info(
                 'Failed to reach the client directly, trying via server.'
             )
             correct_client.proxyThroughServer()
             func()
         except:  # pragma: no cover
             correct_client.proxyThroughServer(value=False)
             raise