Example #1
0
def test_ioerror_load():
    # Non existent
    with pytest.raises(IOError):
        core.load("filedoesnotexist.txt")
    # Non file
    with pytest.raises(IOError):
        core.load(os.path.abspath(os.path.curdir))
def test_ioerror_load():
    # Non existent
    with pytest.raises(IOError):
        core.load("filedoesnotexist.txt")
    # Non file
    with pytest.raises(IOError):
        core.load(os.path.abspath(os.path.curdir))
Example #3
0
def set_mp3_tags(c, path, dry=False, verbose=False):
    """
    Add title, album, artists tags, set album image, write table of contents to podcast episode mp3 file.
    The ToC should be readable by Apple Podcasts.
    """
    full_path = _get_episode_mp3_full_path(path)

    # check that hugo template for new episode page is already exists
    # so we can parse table of contents from there
    episode_num = int(re.match(r".*rt_podcast(\d*)\.mp3", path).group(1))
    episode_page_path = f"/srv/hugo/content/posts/podcast-{episode_num}.md"
    if not os.path.exists(episode_page_path):
        print(
            "Error:",
            f'New episode page "{episode_page_path}" does not exists',
            file=sys.stderr,
        )
        sys.exit(1)

    # remove both ID3 v1.x and v2.x tags.
    remove_version = id3.ID3_ANY_VERSION
    id3.Tag.remove(full_path, remove_version)

    episode_file = core.load(full_path)
    # using ID3v2.3 tags, because using newer ID3v2.4 version leads to problems with Apple Podcasts and Telegram
    # (they will stop showing chapters with long titles at all, see https://github.com/radio-t/radio-t-site/issues/209)
    episode_file.initTag(version=id3.ID3_V2_3)

    tag = episode_file.tag

    try:
        print("Creating new album meta tags: title, cover, artists, etc...")

        set_mp3_album_tags(dict(c.tags), tag, episode_num)

        print(
            "Parsing episode articles from markdown template for the episode page in `/hugo/content/posts/`..."
        )

        toc = parse_table_of_contents_from_md(episode_page_path,
                                              c.toc.first_mp3_chapter_name,
                                              c.toc.max_episode_hours)

        print("Generating table of contents...")

        set_mp3_table_of_contests(tag, toc)

    except Exception as exc:
        print("Error:", str(exc), file=sys.stderr)
        sys.exit(1)

    if not dry:
        tag.save(encoding="utf8")
        print("New mp3 tags are saved.")

    if verbose:
        print("\n")
        print_album_meta(tag)
        print_toc(tag)
def get_item_quality(item):
    preset = None
    if item.format == u'MP3':
        audio_file = core.load(item.path)
        lt = audio_file.info.lame_tag
        if not audio_file or not audio_file.info.lame_tag:
            pass
        elif lt.has_key('preset'):
            preset = lt['preset']
    return {"preset": preset,
            "bitrate": item.bitrate,
            "format": item.format}
Example #5
0
def print_mp3_tags(c, path):
    """
    Print title, album, artist, ToC and other mp3 tags (relevant for Radio-T) from podcast episode file.
    """
    full_path = _get_episode_mp3_full_path(path)

    episode_file = core.load(full_path)

    tag = episode_file.tag
    if not isinstance(tag, id3.Tag):
        print("Error: only ID3 tags can be extracted currently.",
              file=sys.stderr)
        sys.exit(1)

    print_album_meta(tag)
    print_toc(tag)
Example #6
0
def main(mp3file, chaptersfile):
    total_length = int(core.load(mp3file).info.time_secs * 1000)
    chapters = []
    n = 0

    tag = Tag()
    tag.parse(mp3file)
    for i in open(chaptersfile, 'r').readlines():
        chapter_time = to_millisecs(i[0:12])
        chapter_title = u'{}'.format(i[13:]).rstrip()
        chapters.append([[chapter_time, 0], chapter_title, 'ch_' + str(n)])
        if n > 0: chapters[n - 1][0][1] = chapter_time
        n += 1
    chapters[n - 1][0][1] = total_length
    for times, title, id in chapters:
        chapter_frame = tag.chapters.set(id, tuple(times))
        chapter_frame.sub_frames.setTextFrame(b"TIT2", title)
    tag.table_of_contents.set('toc', child_ids=[e[2] for e in chapters])
    show_chapters(tag)
    tag.save()
Example #7
0
    def handleFile(self, f, *args, **kwargs):
        '''Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        '''
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(ex)
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
Example #8
0
    def handleFile(self, f, *args, **kwargs):
        '''Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        '''
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(ex)
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
Example #9
0
def add_chapters(tag, fname):
    chaps = parse_chapters_file(fname)
    audioFile = core.load(fname)
    total_length = audioFile.info.time_secs * 1000
    chaps_ = []
    for i, chap in enumerate(chaps):
        if i < (len(chaps) - 1):
            chaps_.append(((chap[0], chaps[i + 1][0]), chap[1]))
    chaps_.append(((chaps[-1][0], total_length), chaps[-1][1]))
    index = 0
    child_ids = []
    for chap in chaps_:
        element_id = "ch{}".format(index)
        times, title = chap
        new_chap = tag.chapters.set(element_id, times)
        new_chap.sub_frames.setTextFrame("TIT2", u"{}".format(title))
        child_ids.append(element_id)
        index += 1
    tag.table_of_contents.set("toc", child_ids=child_ids)
    list_chaps(tag)
    tag.save()
Example #10
0
    def handleFile(self, f, *args, **kwargs):
        '''Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        '''
        self.audio_file = None

        mtype = utils.guessMimetype(f)
        if mtype is None or not (mtype.startswith("audio/") or
                                 mtype.startswith("application/")):
            return

        self._num_loaded += 1
        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(ex)
        else:
            if not self.audio_file:
                printError("Unsupported file type: %s" % f)
Example #11
0
    def handleFile(self, f, *args, **kwargs):
        """Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        """

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(str(ex))
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
        elif self._dir_images is not None:
            mt = guessMimetype(f)
            if mt and mt.startswith("image/"):
                self._dir_images.append(f)
Example #12
0
def add_chapters(fname, chaps):
    tag = Tag()
    tag.parse(fname)
    audioFile = core.load(fname)
    total_length = audioFile.info.time_secs * 1000
    tag.setTextFrame(b"TLEN", str(int(total_length)))
    for i, chap in enumerate(chaps):
        if i < (len(chaps) - 1):
            chap.end = chaps[i + 1].start

    chaps[-1].end = total_length

    index = 0
    child_ids = []
    for chap in chaps:
        element_id = "ch{}".format(index).encode()
        print("Adding chapter {} at {}".format(chap.title, chap.start))
        new_chap = tag.chapters.set(element_id, (chap.start, chap.end))
        new_chap.sub_frames.setTextFrame(b"TIT2", u"{}".format(chap.title))
        child_ids.append(element_id)
        index += 1
    tag.table_of_contents.set(b"toc", child_ids=child_ids)
    list_chaps(tag)
    tag.save()
    def handleFile(self, f, *args, **kwargs):
        """Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        """
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(str(ex))
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
        elif self._dir_images is not None:
            mt = guessMimetype(f)
            if mt and mt.startswith("image/"):
                self._dir_images.append(f)
Example #14
0
def test_none_load():
    # File mimetypes that are not supported return None
    assert_equal(core.load(__file__), None)
def test_none_load():
    # File mimetypes that are not supported return None
    assert core.load(__file__) == None