Пример #1
0
  def write_metadata(self, filename, force=False):

    # MP4 needs these attributes as TXXX.
    for value in ('original album', 'original_artist', 'original_year'):
      self.txxx[value.upper().replace('_', ' ')] = value

    track = self.track

    log.debug("Writing metadata for: %s", filename)

    if os.path.exists(filename) is False:
      log.warn("Couldn't find MP4 file!: %s", filename)
      return None

    self.tags = mutagen.mp4.MP4(filename)

    if not force and self.is_up_to_date():
      log.debug('Up to date: "%s"' % filename)
      return None

    # Clear out any old data.
    self.tags.clear()

    # Basics first.
    for atom, key in self.attributes.items():

      if hasattr(track, key):
        value = getattr(track, key, None)

        log.debug("Trying: key: %s (%s)", key, value)

        if isinstance(value, str):
          value = value.encode('utf-8')

        # 'tmpo' needs to be a list of integers.
        if key == 'bpm' and value is not None:
          value = [int(value)]

        if value is not None:
          self.tags[atom] = value

    # Hack alert.. not sure how better to "detect" this.
    if track.genre:
      for genre in list(track.genre):
        if genre in self.gapless:
          self.tags["pgap"] = True

    if track.compilation:
      self.tags["cpil"] = True

    if track.tracknumber and track.tracktotal:
      self.tags["trkn"] = [(track.tracknumber, track.tracktotal)]

    elif track.tracknumber:
      self.tags["trkn"] = [(track.tracknumber, 0)]

    # Convert RG tags into iTunes SoundCheck
    # TODO: Find what tags aacgain uses as well.
    if track.replaygain_album_gain:
      self.tags['----:com.apple.iTunes:iTunNORM'] = replay_gain_to_soundcheck(track.replaygain_album_gain, track.replaygain_album_peak)

    elif track.replaygain_track_gain:
      self.tags['----:com.apple.iTunes:iTunNORM'] = replay_gain_to_soundcheck(track.replaygain_track_gain, track.replaygain_track_peak)

    #
    if track.discnumber and track.disctotal:
      try:
        self.tags["disk"] = [(track.discnumber, track.disctotal)]
      except ValueError:
        pass

    elif track.disctotal:
      self.tags["disk"] = [(track.disctotal, track.disctotal)]

    # Artwork time..
    if track.cover_file and os.path.exists(track.cover_file):

      with open(track.cover_file, 'rb') as fh:

        if track.cover_file.endswith(".png"):
          self.tags["covr"] = [ MP4Cover(fh.read(), MP4Cover.FORMAT_PNG) ]
        elif track.cover_file.endswith(".jpg"):
          self.tags["covr"] = [ MP4Cover(fh.read(), MP4Cover.FORMAT_JPEG) ]

    # Always add the check & time stamp for next time.
    if track.checksum:
      self.tags['----:com.sully.flac2mp4:checksum'] = str(track.checksum)

    self.tags['----:com.sully.flac2mp4:flacmtime'] = str(track.mtime)

    # Convert all user defined tags.
    for tag, attribute in self.txxx.items():

      if getattr(track, attribute, None):
        self.tags['----:com.apple.iTunes:' + tag] = getattr(track, attribute).encode('utf-8')

    try:
      self.tags.save(filename)
    except Exception as e:
      log.warn("Couldn't save file %s: %s", filename, e)
Пример #2
0
    def writeTags(self, mp4Path, artwork=True, thumbnail=False):
        self.log.info("Tagging file: %s." % mp4Path)
        ext = os.path.splitext(mp4Path)[1][1:]
        if ext not in valid_output_extensions:
            self.log.error("File is not the correct format.")
            sys.exit()
        try:
            MP4(mp4Path).delete()
        except IOError:
            self.log.debug(
                "Unable to clear original tags, attempting to proceed.")

        video = MP4(mp4Path)
        video["\xa9nam"] = self.title  # Movie title
        video["desc"] = self.shortdescription  # Short description
        video["ldes"] = self.description  # Long description
        video["\xa9day"] = self.date  # Year
        video["stik"] = [9]  # Movie iTunes category
        if self.HD is not None:
            video["hdvd"] = self.HD
        if self.genre is not None:
            genre = None
            for g in self.genre:
                if genre is None:
                    genre = g['name']
                    break
                #else:
                #genre += ", " + g['name']
            video["\xa9gen"] = genre  # Genre(s)
        video[
            "----:com.apple.iTunes:iTunMOVI"] = self.xml  # XML - see xmlTags method
        rating = self.rating()
        if rating is not None:
            video["----:com.apple.iTunes:iTunEXTC"] = rating

        if artwork:
            path = self.getArtwork(mp4Path)
            if path is not None:
                cover = open(path, 'rb').read()
                if path.endswith('png'):
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_PNG)
                                     ]  # png poster
                else:
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_JPEG)
                                     ]  # jpeg poster
        if self.original:
            video["\xa9too"] = "MDH:" + os.path.basename(self.original)
        else:
            video["\xa9too"] = "MDH:" + os.path.basename(mp4Path)

        for i in range(3):
            try:
                self.log.info("Trying to write tags.")
                video.save()
                self.log.info("Tags written successfully.")
                break
            except IOError as e:
                self.log.info("Exception: %s" % e)
                self.log.exception(
                    "There was a problem writing the tags. Retrying.")
                time.sleep(5)
Пример #3
0
    def run(self, info):
        filename = info['filepath']
        temp_filename = prepend_extension(filename, 'temp')

        if not info.get('thumbnails'):
            self.to_screen('There aren\'t any thumbnails to embed')
            return [], info

        idx = next((-i for i, t in enumerate(info['thumbnails'][::-1], 1)
                    if t.get('filepath')), None)
        if idx is None:
            self.to_screen('There are no thumbnails on disk')
            return [], info
        thumbnail_filename = info['thumbnails'][idx]['filepath']
        if not os.path.exists(encodeFilename(thumbnail_filename)):
            self.report_warning(
                'Skipping embedding the thumbnail because the file is missing.'
            )
            return [], info

        # Correct extension for WebP file with wrong extension (see #25687, #25717)
        convertor = FFmpegThumbnailsConvertorPP(self._downloader)
        convertor.fixup_webp(info, idx)

        original_thumbnail = thumbnail_filename = info['thumbnails'][idx][
            'filepath']

        # Convert unsupported thumbnail formats (see #25687, #25717)
        # PNG is preferred since JPEG is lossy
        thumbnail_ext = os.path.splitext(thumbnail_filename)[1][1:]
        if info['ext'] not in ('mkv',
                               'mka') and thumbnail_ext not in ('jpg', 'jpeg',
                                                                'png'):
            thumbnail_filename = convertor.convert_thumbnail(
                thumbnail_filename, 'png')
            thumbnail_ext = 'png'

        mtime = os.stat(encodeFilename(filename)).st_mtime

        success = True
        if info['ext'] == 'mp3':
            options = [
                '-c', 'copy', '-map', '0:0', '-map', '1:0', '-write_id3v1',
                '1', '-id3v2_version', '3', '-metadata:s:v',
                'title="Album cover"', '-metadata:s:v',
                'comment="Cover (front)"'
            ]

            self._report_run('ffmpeg', filename)
            self.run_ffmpeg_multiple_files([filename, thumbnail_filename],
                                           temp_filename, options)

        elif info['ext'] in ['mkv', 'mka']:
            options = list(self.stream_copy_opts())

            mimetype = f'image/{thumbnail_ext.replace("jpg", "jpeg")}'
            old_stream, new_stream = self.get_stream_number(
                filename, ('tags', 'mimetype'), mimetype)
            if old_stream is not None:
                options.extend(['-map', '-0:%d' % old_stream])
                new_stream -= 1
            options.extend([
                '-attach', thumbnail_filename,
                '-metadata:s:%d' % new_stream,
                'mimetype=%s' % mimetype,
                '-metadata:s:%d' % new_stream,
                'filename=cover.%s' % thumbnail_ext
            ])

            self._report_run('ffmpeg', filename)
            self.run_ffmpeg(filename, temp_filename, options)

        elif info['ext'] in ['m4a', 'mp4', 'mov']:
            prefer_atomicparsley = 'embed-thumbnail-atomicparsley' in self.get_param(
                'compat_opts', [])
            # Method 1: Use mutagen
            if not mutagen or prefer_atomicparsley:
                success = False
            else:
                try:
                    self._report_run('mutagen', filename)
                    meta = MP4(filename)
                    # NOTE: the 'covr' atom is a non-standard MPEG-4 atom,
                    # Apple iTunes 'M4A' files include the 'moov.udta.meta.ilst' atom.
                    f = {
                        'jpeg': MP4Cover.FORMAT_JPEG,
                        'png': MP4Cover.FORMAT_PNG
                    }[imghdr.what(thumbnail_filename)]
                    with open(thumbnail_filename, 'rb') as thumbfile:
                        thumb_data = thumbfile.read()
                    meta.tags['covr'] = [
                        MP4Cover(data=thumb_data, imageformat=f)
                    ]
                    meta.save()
                    temp_filename = filename
                except Exception as err:
                    self.report_warning('unable to embed using mutagen; %s' %
                                        error_to_compat_str(err))
                    success = False

            # Method 2: Use AtomicParsley
            if not success:
                success = True
                atomicparsley = next(
                    (x for x in ['AtomicParsley', 'atomicparsley']
                     if check_executable(x, ['-v'])), None)
                if atomicparsley is None:
                    self.to_screen(
                        'Neither mutagen nor AtomicParsley was found. Falling back to ffmpeg'
                    )
                    success = False
                else:
                    if not prefer_atomicparsley:
                        self.to_screen(
                            'mutagen was not found. Falling back to AtomicParsley'
                        )
                    cmd = [
                        encodeFilename(atomicparsley, True),
                        encodeFilename(filename, True),
                        encodeArgument('--artwork'),
                        encodeFilename(thumbnail_filename, True),
                        encodeArgument('-o'),
                        encodeFilename(temp_filename, True)
                    ]
                    cmd += [
                        encodeArgument(o)
                        for o in self._configuration_args('AtomicParsley')
                    ]

                    self._report_run('atomicparsley', filename)
                    self.write_debug('AtomicParsley command line: %s' %
                                     shell_quote(cmd))
                    p = Popen(cmd,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
                    stdout, stderr = p.communicate_or_kill()
                    if p.returncode != 0:
                        msg = stderr.decode('utf-8', 'replace').strip()
                        self.report_warning(
                            f'Unable to embed thumbnails using AtomicParsley; {msg}'
                        )
                    # for formats that don't support thumbnails (like 3gp) AtomicParsley
                    # won't create to the temporary file
                    if b'No changes' in stdout:
                        self.report_warning(
                            'The file format doesn\'t support embedding a thumbnail'
                        )
                        success = False

            # Method 3: Use ffmpeg+ffprobe
            # Thumbnails attached using this method doesn't show up as cover in some cases
            # See https://github.com/yt-dlp/yt-dlp/issues/2125, https://github.com/yt-dlp/yt-dlp/issues/411
            if not success:
                success = True
                try:
                    options = [*self.stream_copy_opts(), '-map', '1']

                    old_stream, new_stream = self.get_stream_number(
                        filename, ('disposition', 'attached_pic'), 1)
                    if old_stream is not None:
                        options.extend(['-map', '-0:%d' % old_stream])
                        new_stream -= 1
                    options.extend(
                        ['-disposition:%s' % new_stream, 'attached_pic'])

                    self._report_run('ffmpeg', filename)
                    self.run_ffmpeg_multiple_files(
                        [filename, thumbnail_filename], temp_filename, options)
                except PostProcessingError as err:
                    success = False
                    raise EmbedThumbnailPPError(
                        f'Unable to embed using ffprobe & ffmpeg; {err}')

        elif info['ext'] in ['ogg', 'opus', 'flac']:
            if not mutagen:
                raise EmbedThumbnailPPError(
                    'module mutagen was not found. Please install using `python -m pip install mutagen`'
                )

            self._report_run('mutagen', filename)
            f = {
                'opus': OggOpus,
                'flac': FLAC,
                'ogg': OggVorbis
            }[info['ext']](filename)

            pic = Picture()
            pic.mime = 'image/%s' % imghdr.what(thumbnail_filename)
            with open(thumbnail_filename, 'rb') as thumbfile:
                pic.data = thumbfile.read()
            pic.type = 3  # front cover
            res = self._get_thumbnail_resolution(thumbnail_filename,
                                                 info['thumbnails'][idx])
            if res is not None:
                pic.width, pic.height = res

            if info['ext'] == 'flac':
                f.add_picture(pic)
            else:
                # https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
                f['METADATA_BLOCK_PICTURE'] = base64.b64encode(
                    pic.write()).decode('ascii')
            f.save()
            temp_filename = filename

        else:
            raise EmbedThumbnailPPError(
                'Supported filetypes for thumbnail embedding are: mp3, mkv/mka, ogg/opus/flac, m4a/mp4/mov'
            )

        if success and temp_filename != filename:
            os.replace(temp_filename, filename)

        self.try_utime(filename, mtime, mtime)
        converted = original_thumbnail != thumbnail_filename
        self._delete_downloaded_files(
            thumbnail_filename
            if converted or not self._already_have_thumbnail else None,
            original_thumbnail
            if converted and not self._already_have_thumbnail else None,
            info=info)
        return [], info
Пример #4
0
def applyData(filePath):
	global data, artwork
	tagged_file= MP4(filePath)
	genres=[]
	if 'genres' in data:
		for genre in data['genres']:
			genres.append(genre['name'])
		tagged_file['\xa9gen'] = genres
	if 'overview' in data:
		tagged_file['ldes'] = data['overview']
		tagged_file['desc'] = data['overview']
	if 'title' in data:
		tagged_file['\xa9alb'] = data['title']
		tagged_file['aART'] = data['title']
		tagged_file['\xa9nam'] = data['title']
	elif 'original_title' in data:
		tagged_file['\xa9alb'] = data['original_title']
		tagged_file['aART'] = data['original_title']
		tagged_file['\xa9nam'] = data['original_title']

	if 'season_number' in data:
		tagged_file['tvsn'] = [data['season_number']]
	if 'episode_number' in data:
		tagged_file['tves'] = [data['episode_number']]
	if artwork != "":
		
		with open(artwork, "rb") as f:
			tagged_file["covr"] = [
				MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG)
			]
	if 'air_date' in data:
		tagged_file['\xa9day'] = data['air_date'][:4]
	if 'name' in data:
		tagged_file['\xa9nam'] = data['name']
	if 'original_name' in data:
		tagged_file['tvsh'] = data['original_name']
		tagged_file['\xa9alb'] = data['original_name']
		tagged_file['\xa9ART'] = data['original_name']
		tagged_file['aART'] = data['original_name']
	if 'release_date' in data:
		tagged_file['\xa9day'] = data['release_date'][:4]
	vid = cv2.VideoCapture(filePath)
	width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)

	if width > 1919 and width < 3839:
		tagged_file['hdvd'] = [2]
	elif width < 1919 and width > 1279:
		tagged_file['hdvd'] = [1]
	elif width > 3839:
		tagged_file['hdvd'] = [3]
	else:
		tagged_file['hdvd'] = [0]

	if isTV:
		cast_crew_data = getCastandCrew(data['id'], "tv")
	else:
		cast_crew_data = getCastandCrew(data['id'], "movie")
	cast = []
	directors = []
	screenwriters = []
	producers = []
	producer_re = re.compile("Producer$")
	for cast_member in cast_crew_data['cast']:
		cast.append(cast_member['name'])

	for crew_members in cast_crew_data['crew']:
		if crew_members['job'] == "Director":
			directors.append(crew_members['name'])
		if crew_members['department'] == "Writing":
			screenwriters.append(crew_members['name'])
		if producer_re.search(crew_members['job']):
			producers.append(crew_members['name'])

	xml_str = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
	xml_str += "<plist version=\"1.0\">\n"
	xml_str += "<dict>"
	xml_str += generateXML(cast, "cast")
	xml_str += generateXML(directors, "directors")
	xml_str += generateXML(screenwriters, "screenwriters")
	xml_str += generateXML(producers, "producers")
	xml_str += "</dict>"
	xml_str += "</plist>"

	tagged_file['----:com.apple.iTunes:iTunMOVI'] = str.encode(xml_str)

	rating = getClassification(data['id'])
	tagged_file['----:com.apple.iTunes:iTunEXTC'] = str.encode(
		"b'mpaa|" + rating + "|300|")

	if isTV:
		tagged_file['stik'] = [10]
	else:
		tagged_file['stik'] = [9]
	tagged_file.save()
Пример #5
0
def downloadSong(web_url,baseFolder,file,performance,username):
    # Construct full path to filename
    filename = baseFolder + file

    # If the file already exists, skip it
    if path.exists(filename):
        print(f"ALREADY EXISTS - {filename}")
        return 0

    # Print filename
    print(f"Downloading {filename}")

    try:
        # Print out the web_url for debugging purposes
        # TODO: Convert to debug message?
        #print(web_url)
        # The web_url returns an HTML page that contains the link to the content we wish to download
        with request.urlopen(web_url) as url:
            # First get the HTML for the web_url
            htmlstr = str(url.read())
            #print(htmlstr)
            # Next, parse out the actual media_url, which is in the content field of the "twitter:player:stream" object
            # We need to strip out the "amp;" values and convert the "+" value to URL-friendly value
            media_url = unquote(re.search('twitter:player:stream.*?content=".*?"',htmlstr).group(0).split('"')[2]).replace("amp;","").replace("+","%2B")
            #print(media_url)
            # Print out the media_url for debugging purposes
            # TODO: Convert this to a debug message?
            #print(media_url)

            # Open the file in binary write mode and write the data from the media_url
            f = open(filename,'w+b')
            f.write(request.urlopen(media_url).read())
            f.close()
    except Exception as e:
        print("FAILED TO DOWNLOAD!!!!!!!!!!!!!!")
        if "'NoneType' object has no attribute 'group'" in str(e):
            print("Recording not available - attempting to play in order to make it available")
            media_url = unquote(re.search('twitter:player" content=".*?"',htmlstr).group(0).split('"')[2]).replace("amp;","").replace("+","%2B")
            # webbrowser registration does not seem to be needed
            #webbrowser.register('chrome',None,webbrowser.BackgroundBrowser("C://Program Files (x86)//Google//Chrome//Application//chrome.exe"))
            #webbrowser.get('chrome').open(media_url)
            webbrowser.open(media_url)
            #print(f"NEED TO PLAY: {media_url}")
        else:
            print(str(e))
        print("-----")
        #if (not "HTTP Error 504" in str(e)) and (not "HTTP Error 410" in str(e)) and (not "'NoneType' object has no attribute 'group'" in str(e)):
            #raise
        return 1

    try:
        # Calculate necessary dates
        createdat = performance["created_at"]
        perfdate = datetime.strptime(createdat[0:10],"%Y-%m-%d")
        # Set the album date to the start of the week on which the song was created
        albumdate = (perfdate - timedelta(days=perfdate.weekday())).strftime("%Y-%m-%d")
        albumyear = createdat[0:4]
        # Write the tags for the M4A file
        af = MP4(filename)
        af["\xa9nam"] = performance["fixed_title"]
        af["\xa9ART"] = performance["performers"]
        # Set Album Artist to the username we searched for
        af["aART"] = username
        # Android seems to have a bug where wrong art is displayed if "Album" tag is empty so set it to "Smule" followed by current date
        af["\xa9alb"] = f"Smule - {albumdate}"
        af["\xa9day"] = f"{albumyear}"
        af["purd"] = createdat
        af["\xa9cmt"] = f"Performed on {createdat}"

        # Write the JPEG to the M4A file as album cover. Ignore any errors reading the image
        try:
            pic_url = performance['display_pic_url']
            img = MP4Cover(request.urlopen(pic_url).read(), imageformat=MP4Cover.FORMAT_JPEG)
            af["covr"] = [img]
        except:
            pass
        # Save the updated tags to the file
        af.save()
    except Exception as e:
        print("FAILED TO UPDATE TAGS!!!")
        print(str(e))
        return 0

    # Print pic URL for debugging purposes
    # print(pic_url)
    return 0
Пример #6
0
 def test_cmp_bytes(self):
     self.assertReallyEqual(MP4Cover(b'woooo'), b"woooo")
     self.assertReallyNotEqual(MP4Cover(b'woooo'), b"foo")
     if PY2:
         self.assertReallyEqual(MP4Cover(b'woooo'), u"woooo")
         self.assertReallyNotEqual(MP4Cover(b'woooo'), u"foo")
Пример #7
0
    def process_a_file(self, input_path, output_dir):
        au_id = input_path.name

        if not au_id.isdigit():
            print(f'unexpected file: {input_path}')
            return

        au_id = int(au_id)

        file_kind = File(input_path)

        if isinstance(file_kind, MP4):
            suffix = '.m4a'
        elif isinstance(file_kind, FLAC):
            suffix = '.flac'
        elif file_kind is None:
            raise TypeError('unknown file kind')
        else:
            raise TypeError(
                f'unsupport file kind {file_kind.__class__.__name__}')

        audio_info = self.audio_cache.get(au_id)
        filename = f'{spilt_artist_str(audio_info["author"])[0]} - {audio_info["title"]}{suffix}'

        output_path = output_dir / filename

        if not self.overwrite and output_path.is_file():
            print(f'{filename} exists, skipped')
            return

        print(f'processing: {filename}')

        shutil.copyfile(input_path, output_path)

        album_id = audio_info['pgc_info']['pgc_menu']['menuId']
        album_info = self.album_cache.get(album_id)
        album_cover_url = album_info['menusRespones']['coverUrl']

        album_au_ids = list(map(lambda x: x['id'], album_info['songsList']))
        track_id = album_au_ids.index(au_id)
        assert album_cover_url == album_info['songsList'][track_id][
            'cover_url']

        album_cover_path = self.cover_cache.get(album_cover_url)
        if album_cover_path.suffix == '.jpg':
            image_format = AtomDataType.JPEG
        elif album_cover_path.suffix == '.png':
            image_format = AtomDataType.PNG
        else:
            raise TypeError(
                f'Unsupport format: {album_cover_path.suffix}, Only support jpg and png.'
            )

        with album_cover_path.open('rb') as fp:
            cover_image = fp.read()

        audio_file = File(output_path)

        if isinstance(audio_file, MP4):
            tags = {
                '\xa9nam':
                audio_info['title'],
                '\xa9alb':
                album_info['menusRespones']['title'],
                '\xa9ART':
                format_artist_list(spilt_artist_str(audio_info['author'])),
                '\xa9day':
                str(
                    get_year_from_timestamp(
                        album_info['menusRespones']['pbtime'])),
                'aART':
                format_artist_list(
                    spilt_artist_str(album_info['menusRespones']['mbnames'])),
                'trkn':
                [(track_id + 1, album_info['menusRespones']['songNum'])],
                'disk': [(1, 1)],
                'covr': [MP4Cover(cover_image, imageformat=image_format)],
            }
        elif isinstance(audio_file, FLAC):
            tags = {
                'ALBUM':
                album_info['menusRespones']['title'],
                'ARTIST':
                format_artist_list(spilt_artist_str(audio_info['author'])),
                'ALBUMARTIST':
                format_artist_list(
                    spilt_artist_str(album_info['menusRespones']['mbnames'])),
                'DATE':
                str(
                    get_year_from_timestamp(
                        album_info['menusRespones']['pbtime'])),
                'TITLE':
                audio_info['title'],
                'DISCNUMBER':
                '1',
                'DISCTOTAL':
                '1',
                'TRACKTOTAL':
                str(album_info['menusRespones']['songNum']),
                'TRACKNUMBER':
                str(track_id + 1),
            }

            picture = Picture()
            picture.data = cover_image
            picture.type = PictureType.COVER_FRONT

            audio_file.add_picture(picture)

        audio_file.update(tags)
        audio_file.save()
Пример #8
0
    def writeTags(self, mp4Path, artwork=True, thumbnail=False):
        self.log.debug("Tagging file %s" % mp4Path)
        if MkvtoMp4(self.settings).validSource(mp4Path) == True:
            video = MP4(mp4Path)
            try:
                video.delete()
            except IOError:
                self.log.debug(
                    "Unable to clear original tags, attempting to proceed")

            video["\xa9nam"] = self.title  # Movie title
            #video["desc"] = self.shortdescription  # Short description
            #video["ldes"] = self.description  # Long description
            video["\xa9day"] = self.date  # Year
            #video["stik"] = [9]  # Movie iTunes category
            if self.HD is not None:
                video["hdvd"] = self.HD
            #if self.genre is not None:
            #    genre = None
            #    for g in self.genre:
            #        if genre is None:
            #            genre = g['name']
            #            break
            #        # else:
            #            # genre += ", " + g['name']
            #    video["\xa9gen"] = genre  # Genre(s)
            #video["----:com.apple.iTunes:iTunMOVI"] = self.xml  # XML - see xmlTags method
            #rating = self.rating()
            #if rating is not None:
            #    video["----:com.apple.iTunes:iTunEXTC"] = rating

            if artwork:
                path = self.getArtwork(mp4Path)
                if path is not None:
                    cover = open(path, 'rb').read()
                    if path.endswith('png'):
                        video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_PNG)
                                         ]  # png poster
                    else:
                        video["covr"] = [
                            MP4Cover(cover, MP4Cover.FORMAT_JPEG)
                        ]  # jpeg poster

            #if self.original:
            #    video["\xa9too"] = ("meks-ffmpeg movie [%s-%s]" % (self.provider, self.providerid))
            #else:
            #    video["\xa9too"] = ("meks-ffmpeg movie [%s-%s]" % (self.provider, self.providerid))
            video = metadata_stamper.stamp_encoder(
                video=video,
                save=False,
                stamp=("movie [%s-%s]" % (self.provider, self.providerid)))

            for i in range(3):
                try:
                    self.log.debug("Trying to write tags")
                    video.save()
                    self.log.info("Tags written successfully")
                    return True
                except IOError as e:
                    self.log.exception(
                        "There was a problem writing the tags. Retrying")
                    time.sleep(5)
        else:
            self.log.error("The file is invalid")
        raise IOError
Пример #9
0
videoquality = int(args.quality)
title = args.songtitle
album = args.songalbum
artist = args.songartist
artistalbum = args.songartistalbum
date = args.songdate
genre = args.songgenre
picture = args.songartwork
tracknumber = (trackn, 0)


audio = MP4(filename)
audio["\xa9nam"] = [title]
audio["\xa9alb"] = [album]
audio["\xa9ART"] = [artist]
audio["aART"] = [artistalbum]
audio["\xa9day"] = [date]
if genre:
    audio["\xa9gen"] = [genre]
if tracknumber == 0:
    audio["trkn"] = [tracknumber]
audio["hdvd"] = [videoquality]
audio["stik"] = [6]
with open(picture, "rb") as f:
    audio["covr"] = [
        MP4Cover(f.read(), MP4Cover.FORMAT_JPEG)
    ]
#audio["\xa9lyr"] = [syncedlyrics]
audio.pprint()
audio.save()
Пример #10
0
def pandora_downloader():
    """Download songs from Pandora, Woop Woop."""
    # playlist path
    playlist_path = os.sep.join([
        ROOT_FOLDER,
        re.sub(r'[<>\*:\\/"|?]', "", request.form["station"]) + ".m3u",
    ])

    # build the song's path - remove any invalid characters
    relative_song_path = FILE_TEMPLATE.format(
        station=re.sub(r'[<>\*:\\/"|?]', "", request.form["station"]),
        artist=re.sub(r'[<>\*:\\/"|?]', "", request.form["artist"]),
        album=re.sub(r'[<>\*:\\/"|?]', "", request.form["album"]),
        title=re.sub(r'[<>\*:\\/"|?]', "", request.form["title"]),
    )

    song_path = os.sep.join([ROOT_FOLDER, relative_song_path])

    # check to see if the file has been downloaded before!
    if os.path.exists(song_path):
        print("Song found already")
        return jsonify(status="alreadyDownloaded")
    else:
        print("Downloading {!r}".format(request.form["title"]))

        # create the directories if they don't exist
        if not os.path.isdir(os.path.split(song_path)[0]):
            os.makedirs(os.path.split(song_path)[0])

        # download the song
        try:
            urllib.urlretrieve(request.form["url"], song_path)
        except BaseException:
            print("Something went wrong... skipping this song!")
            return jsonify(status="failed")

        # open the song with mutagen so we can tag it
        # and put the album art in it
        try:
            song = MP4(song_path)
        except BaseException:
            print("Something went wrong... skipping this song!")
            return jsonify(status="failed")

        # set the tags
        song["\xa9nam"] = [request.form["title"]]
        song["\xa9ART"] = [request.form["artist"]]
        song["\xa9alb"] = [request.form["album"]]

        # download the album art and put it in the file
        album_art_request = urllib.urlopen(request.form["albumArt"])
        album_art = MP4Cover(album_art_request.read())
        album_art_request.close()
        song["covr"] = [album_art]
        song.save()

        # append the song in the playlist
        with open(playlist_path, "a+") as playlist:
            playlist.write((relative_song_path + "\n"))

        print("Download Complete!")
        return jsonify(status="success")
from mutagen import File

# filename = "/Users/mgermaine93/Desktop/Test-Music/01 Dragonfly.m4a"
# album_art = "/Users/mgermaine93/Desktop/looking_wolf_artwork.jpg"
filename = "/Users/mgermaine93/Desktop/Test-Music/01 Living In The Country.m4a"
album_art = "/Users/mgermaine93/Desktop/Album-Art/0image.jpg"

try:
    track = MP4(filename)
    tags = track.tags
    tags['covr']
    print("Track already has album artwork")
except KeyError:
    print("Track does not currently have album artwork")
    track = MP4(filename)

    # Thanks to: https://stackoverflow.com/questions/37897801/embedding-album-cover-in-mp4-file-using-mutagen
    with open(album_art, "rb") as f:
        track.tags["covr"] = [
            MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG)
        ]
    track.save()
    print("artwork saved")

    # Alternate way:
    # covr = []
    # artworkfile = open(album_art, "rb").read()
    # covr.append(M4ACover(artworkfile, M4ACover.FORMAT_JPEG))
    # track.tags['covr'] = covr
    # track.save()
Пример #12
0
    def TagTrack(self, folder, export=''):
        '''
            'Tag' a song's trackdata with the infomation given in folder

            Call once all download tasks is finished

            Suppports MP3,M4A(ALAC/MP4),FLAC
        '''

        export = export if export else self.output
        folder = str(folder)
        audio = [f for f in os.listdir(folder) if f.split('.')[-1].lower() in ['mp3', 'm4a', 'flac','ogg']]
        if not audio:
            logger.error('Supported audio file for %s is missing,Cannot continue formatting!' % folder)
            return     
        audio = audio[-1]
        audio = self.GenerateDownloadPath(filename=audio, folder=folder)
        format = audio.split('.')[-1].lower()
        # Locate audio file,uses last match
        track = self.GenerateDownloadPath(filename='track.json', folder=folder)
        # Locate track file
        cover = self.GenerateDownloadPath(filename='cover.jpg', folder=folder)
        # Locate cover image

        track = json.loads(open(track, encoding='utf-8').read())
        tHelper = TrackHelper(track)

        def write_keys(song):
            # Write trackdatas
            song['title'] = tHelper.TrackName
            song['artist'] = tHelper.Artists if tHelper.Artists else 'Various Artists'
            song['album'] = tHelper.AlbumName if tHelper.AlbumName else 'Unknown'
            song['tracknumber'] = str(tHelper.TrackNumber)
            song['date'] = str(tHelper.TrackPublishTime)
            song.save()

        if format == 'm4a':
            # Process m4a files: Apple’s MP4 (aka M4A, M4B, M4P)
            song = easymp4.EasyMP4(audio)
            write_keys(song)
            if os.path.exists(cover):
                song = MP4(audio)
                # Write cover image
                song['covr'] = [MP4Cover(open(cover, 'rb').read())]
                song.save()
        elif format == 'mp3':
            # Process mp3 files: MPEG audio stream information and tags
            song = EasyMP3(audio)
            write_keys(song)
            if os.path.exists(cover):
                song = ID3(audio)
                # Write cover image
                song.add(APIC(encoding=3, mime='image/jpeg', type=3,
                              desc='Cover', data=open(cover, 'rb').read()))
                song.save()
        elif format == 'flac':
            # Process FLAC files:Free Lossless Audio Codec
            song = FLAC(audio)
            write_keys(song)
            if os.path.exists(cover):
                pic = Picture()
                pic.data = open(cover, 'rb').read()
                pic.mime = 'image/jpeg'
                song.add_picture(pic)
                song.save()
        elif format == 'ogg':
            # Process OGG files:Ogg Encapsulation Format
            song = OggVorbis(audio)
            write_keys(song)
            if os.path.exists(cover):
                pic = Picture()
                pic.data = open(cover, 'rb').read()
                pic.mime = 'image/jpeg'
                song["metadata_block_picture"] = [base64.b64encode(pic.write()).decode('ascii')]
                song.save()
        # Rename & move file
        savename = tHelper.Title + '.' + format
        try:
            path = self.GenerateDownloadPath(filename=savename, folder=export)
            shutil.copy(audio, path)
            logger.debug('Exported audio to path %s' % path[-truncate_length:])
            return path
        except Exception as e:
            raise Exception('While copying audio file:%s' % e)
Пример #13
0
if producer:
    audio["----:com.apple.iTunes:PRODUCER"] = producer.encode()
if mixer:
    audio["----:com.apple.iTunes:MIXER"] = mixer.encode()
if label:
    audio["----:com.apple.iTunes:LABEL"] = label.encode()
if barcode:
    audio["----:com.apple.iTunes:BARCODE"] = barcode.encode()
if isrc:
    audio["----:com.apple.iTunes:ISRC"] = isrc.encode()
if albumartistid:
    audio[
        "----:com.apple.iTunes:MusicBrainz Album Artist Id"] = albumartistid.encode(
        )
if releasegroupid:
    audio[
        "----:com.apple.iTunes:MusicBrainz Release Group Id"] = releasegroupid.encode(
        )
if albumid:
    audio["----:com.apple.iTunes:MusicBrainz Album Id"] = albumid.encode()

if (compilation == 1):
    audio["cpil"] = [compilation]
audio["stik"] = [1]
audio["\xa9cmt"] = [comment]
with open(picture, "rb") as f:
    audio["covr"] = [MP4Cover(f.read(), MP4Cover.FORMAT_JPEG)]
#audio["\xa9lyr"] = [syncedlyrics]
audio.pprint()
audio.save()
Пример #14
0
def get_mp4_coverart(path):
    with open(path, 'rb') as f:
        data = f.read()
    cover = MP4Cover(data)
    return cover
Пример #15
0
def set_M4A_data(SONG_INFO, is_quiet, song_path, choice):
    """
    Set the tags in the m4a file passed.
    """
    cover_added = False

    try:
        # If more than one choice then call getChoice
        option = 0
        if len(SONG_INFO) > 1:
            if not is_quiet:
                option = getChoice(SONG_INFO, 'metadata')
            elif choice is not None and choice in range(1, len(SONG_INFO)):
                option = choice

        SONG_PATH = os.path.join(defaults.DEFAULT.SONG_TEMP_DIR,
                                 song_path)

        audio = MP4(SONG_PATH)

        # Download the cover image, if failed, pass
        if dwCover(SONG_INFO, option):
            imagedata = open(defaults.DEFAULT.COVER_IMG, 'rb').read()
            audio["covr"] = [MP4Cover(
                                imagedata,
                                imageformat=MP4Cover.FORMAT_JPEG
                            )]
            # REmove the image
            os.remove(defaults.DEFAULT.COVER_IMG)
            cover_added = True

        # If tags are not present then add them
        try:
            audio.add_tags()
        except Exception:
            pass

        audio.save()

        option = int(option)

        # Add the meta data, the key's can be found at
        # https://mutagen.readthedocs.io/en/latest/api/mp4.html#mutagen.mp4.MP4Tags
        audio["\xa9nam"] = SONG_INFO[option].track_name
        audio["\xa9alb"] = SONG_INFO[option].collection_name
        audio["\xa9ART"] = SONG_INFO[option].artist_name
        audio["\xa9day"] = SONG_INFO[option].release_date
        audio["\xa9gen"] = SONG_INFO[option].primary_genre_name

        # Adding track number would probably thwor some kind
        # of render error, will leave for later

        audio.save()

        defaults.DEFAULT.SONG_NAME_TO_SAVE = SONG_INFO[option].track_name + '.m4a'

        # Rename the downloaded file
        os.rename(SONG_PATH, os.path.join(
                                    defaults.DEFAULT.SONG_TEMP_DIR,
                                    defaults.DEFAULT.SONG_NAME_TO_SAVE
                                ))

        return option, cover_added

    except Exception as e:
        return e
Пример #16
0
    def writeTags(self,
                  path,
                  artwork=True,
                  thumbnail=False,
                  width=None,
                  height=None):
        self.log.info("Tagging file: %s." % path)
        if width and height:
            try:
                self.setHD(width, height)
            except:
                self.log.exception("Unable to set HD tag.")

        try:
            video = MP4(path)
        except MP4StreamInfoError:
            self.log.error(
                'File is not a valid MP4 file and cannot be tagged.')
            return False

        try:
            video.delete()
        except:
            self.log.debug("Unable to clear original tags, will proceed.")

        if self.mediatype == MediaType.Movie:
            video["\xa9nam"] = self.title  # Movie title
            video["desc"] = self.tagline  # Short description
            video["ldes"] = self.description  # Long description
            video["\xa9day"] = self.date  # Year
            video["stik"] = [9]  # Movie iTunes category
        elif self.mediatype == MediaType.TV:
            video["tvsh"] = self.showname  # TV show title
            video["\xa9nam"] = self.title  # Video title
            video["tven"] = self.title  # Episode title
            video["desc"] = self.shortDescription  # Short description
            video["ldes"] = self.description  # Long description
            network = [x['name'] for x in self.network]
            video["tvnn"] = network  # Network
            video["\xa9day"] = self.airdate  # Airdate
            video["tvsn"] = [self.season]  # Season number
            video["disk"] = [(self.season, 0)]  # Season number as disk
            video["\xa9alb"] = self.showname + ", Season " + str(
                self.season)  # iTunes Album as Season
            video["tves"] = [self.episode]  # Episode number
            video["trkn"] = [
                (self.episode, len(self.seasondata.get('episodes', [])))
            ]  # Episode number iTunes
            video["stik"] = [10]  # TV show iTunes category

        if self.HD:
            video["hdvd"] = self.HD
        if self.genre and len(self.genre) > 0:
            video["\xa9gen"] = self.genre[0].get('name')
        video["----:com.apple.iTunes:iTunMOVI"] = self.xml.encode(
            "UTF-8", errors="ignore")  # XML - see xmlTags method
        if self.rating:
            video["----:com.apple.iTunes:iTunEXTC"] = self.rating.encode(
                "UTF-8", errors="ignore")  # iTunes content rating

        if artwork:
            coverpath = self.getArtwork(path, thumbnail=thumbnail)
            if coverpath is not None:
                cover = open(coverpath, 'rb').read()
                if path.endswith('png'):
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_PNG)
                                     ]  # png poster
                else:
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_JPEG)
                                     ]  # jpeg poster

        if self.original:
            video["\xa9too"] = "SMA:" + os.path.basename(self.original)
        else:
            video["\xa9too"] = "SMA:" + os.path.basename(path)

        try:
            self.log.info("Trying to write tags.")
            video.save()
            self.log.info("Tags written successfully.")
            return True
        except:
            self.log.exception("There was an error writing the tags.")
        return False
    def writeTags(self,
                  path,
                  converter,
                  artwork=True,
                  thumbnail=False,
                  width=None,
                  height=None):
        self.log.info("Tagging file: %s." % path)
        if width and height:
            try:
                self.setHD(width, height)
            except:
                self.log.exception("Unable to set HD tag.")

        try:
            video = MP4(path)
        except MP4StreamInfoError:
            self.log.debug(
                'File is not a valid MP4 file and cannot be tagged using mutagen, falling back to FFMPEG limited tagging.'
            )
            try:
                metadata = {}
                if self.mediatype == MediaType.Movie:
                    metadata['TITLE'] = self.title  # Movie title
                    metadata["COMMENT"] = self.description  # Long description
                    metadata["DATE_RELEASE"] = self.date  # Year
                    metadata["DATE"] = self.date  # Year
                elif self.mediatype == MediaType.TV:
                    metadata['TITLE'] = self.title  # Video title
                    metadata["COMMENT"] = self.description  # Long description
                    metadata["DATE_RELEASE"] = self.airdate  # Air Date
                    metadata["DATE"] = self.airdate  # Air Date
                    metadata["ALBUM"] = self.showname + ", Season " + str(
                        self.season)  # Album as Season

                if self.genre and len(self.genre) > 0:
                    metadata["GENRE"] = self.genre[0].get('name')

                metadata["ENCODER"] = "SMA"

                coverpath = None
                if artwork:
                    coverpath = self.getArtwork(path, thumbnail=thumbnail)

                try:
                    conv = converter.tag(path, metadata, coverpath)
                except:
                    self.log.exception("FFMPEG Tag Error.")
                    return False
                _, cmds = next(conv)
                self.log.debug("Metadata tagging FFmpeg command:")
                self.log.debug(" ".join(str(item) for item in cmds))
                for timecode, debug in conv:
                    self.log.debug(debug)
                self.log.info(
                    "Tags written successfully using FFMPEG fallback method.")
                return True
            except:
                self.log.exception(
                    "Unexpected tagging error using FFMPEG fallback method.")
                return False

        try:
            video.delete()
        except:
            self.log.debug("Unable to clear original tags, will proceed.")

        if self.mediatype == MediaType.Movie:
            video["\xa9nam"] = self.title  # Movie title
            video["desc"] = self.tagline  # Short description
            video["ldes"] = self.description  # Long description
            video["\xa9day"] = self.date  # Year
            video["stik"] = [9]  # Movie iTunes category
        elif self.mediatype == MediaType.TV:
            video["tvsh"] = self.showname  # TV show title
            video["\xa9nam"] = self.title  # Video title
            video["tven"] = self.title  # Episode title
            video["desc"] = self.shortDescription  # Short description
            video["ldes"] = self.description  # Long description
            network = [x['name'] for x in self.network]
            video["tvnn"] = network  # Network
            video["\xa9day"] = self.airdate  # Airdate
            video["tvsn"] = [self.season]  # Season number
            video["disk"] = [(self.season, 0)]  # Season number as disk
            video["\xa9alb"] = self.showname + ", Season " + str(
                self.season)  # iTunes Album as Season
            video["tves"] = [self.episode]  # Episode number
            video["trkn"] = [
                (self.episode, len(self.seasondata.get('episodes', [])))
            ]  # Episode number iTunes
            video["stik"] = [10]  # TV show iTunes category

        if self.HD:
            video["hdvd"] = self.HD
        if self.genre and len(self.genre) > 0:
            video["\xa9gen"] = self.genre[0].get('name')
        video["----:com.apple.iTunes:iTunMOVI"] = self.xml.encode(
            "UTF-8", errors="ignore")  # XML - see xmlTags method
        if self.rating:
            video["----:com.apple.iTunes:iTunEXTC"] = self.rating.encode(
                "UTF-8", errors="ignore")  # iTunes content rating

        if artwork:
            coverpath = self.getArtwork(path, thumbnail=thumbnail)
            if coverpath is not None:
                cover = open(coverpath, 'rb').read()
                if coverpath.endswith('png'):
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_PNG)
                                     ]  # png poster
                else:
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_JPEG)
                                     ]  # jpeg poster

        if self.original:
            video["\xa9too"] = "SMA:" + os.path.basename(self.original)
        else:
            video["\xa9too"] = "SMA:" + os.path.basename(path)

        try:
            self.log.info("Trying to write tags.")
            video.save()
            self.log.info("Tags written successfully using mutagen.")
            return True
        except:
            self.log.exception("There was an error writing the tags.")
        return False
Пример #18
0
def start_process(filenames, mode):
    """
    This is the main funtion of the script
    where it does its main processing.\n
    filenames is the list of files to be processed\n
    mode = 1,2,3 or 4\n
    1 means mp4 to tagged mp4\n
    2 means mp4 with sub to subbed and tagged mp4\n
    3 means mkv to tagged mp4\n
    4 means mkv with sub to subbed and tagged mp4
    """

    for filename in filenames:
        try:
            title = filename[:-4]
            
            stream_md = collect_stream_metadata(filename)
            streams_to_process = []
            dvdsub_exists=False
            for stream in stream_md['streams']:
                if not stream['codec_name'] in sub_codec_blacklist:
                    streams_to_process.append(stream['index'])
                else:
                    dvdsub_exists=True
            
            print('\nSearching IMDb for "{}"'.format(title))
            
            imdb = Imdb()
            movie_results = []
            results = imdb.search_for_title(title)
            for result in results:
                if result['type'] == "feature":
                    movie_results.append(result)
                    
            if not movie_results:
                while not movie_results:
                    title = input('\nNo results for "' + title +
                                  '" Enter alternate/correct movie title >> ')
                    
                    results = imdb.search_for_title(title)
                    for result in results:
                        if result['type'] == "feature":
                            movie_results.append(result)
                
            # The most prominent result is the first one
            # mpr - Most Prominent Result
            mpr = movie_results[0]
            print('\nFetching data for {} ({})'.format(mpr['title'],
                                                       mpr['year']))
                                                     
            # imdb_movie is a dict of info about the movie
            imdb_movie = imdb.get_title(mpr['imdb_id'])
            
            imdb_movie_title = imdb_movie['base']['title']
            imdb_movie_year = imdb_movie['base']['year']
            imdb_movie_id = mpr['imdb_id']
                        
            
            imdb_movie_rating = imdb_movie['ratings']['rating']
            
            if not 'outline' in imdb_movie['plot']:
                imdb_movie_plot_outline = (imdb_movie['plot']['summaries'][0]
                                           ['text'])
                print("\nPlot outline does not exist. Fetching plot summary "
                        "instead.\n\n")
            else:
                imdb_movie_plot_outline = imdb_movie['plot']['outline']['text']
            
            # Composing a string to have the rating and the plot of the
            # movie which will go into the 'comment' metadata of the 
            # mp4 file.
            imdb_rating_and_plot = str('IMDb rating ['
                                       + str(float(imdb_movie_rating))
                                       + '/10] - '
                                       + imdb_movie_plot_outline)
                                       
            
            imdb_movie_genres = imdb.get_title_genres(imdb_movie_id)['genres']
            
            # Composing the 'genre' string of the movie.
            # I use ';' as a delimeter to searate the multiple genre values
            genre = ';'.join(imdb_movie_genres)
            
            
            newfilename = (imdb_movie_title
                           + ' ('
                           + str(imdb_movie_year)
                           + ').mp4')
                           
            # We don't want the characters not allowed in a filename
            newfilename = (newfilename
                           .replace(':', ' -')
                           .replace('/', ' ')
                           .replace('?', ''))

            command = ""
            stream_map = []
            for f in streams_to_process:
                stream_map.append("-map 0:{}".format(f))
            stream_map_str = ' '.join(stream_map)           
            
            

            if mode == 1:
                # it is required to rename it as its already an mp4 file that
                # wasn't proccessed by ffmpeg
                os.rename(filename, newfilename)
            if mode == 2 or mode == 4:

                command = ('ffmpeg -i "'
                           + filename
                           + '" -sub_charenc UTF-8 -i "'
                           + filename[:-4]
                           + '.srt" '
                           + stream_map_str
                           + ' -map 1 -c copy -c:s mov_text '
                             '"' + newfilename + '"')
                subprocess.run(shlex.split(command))
            if mode == 3:
                command = ('ffmpeg -i '
                           + '"' + filename + '" '
                           + stream_map_str
                           + ' -c copy -c:s mov_text '
                             '"' + newfilename + '"')
                subprocess.run(shlex.split(command))
                
            if dvdsub_exists:
                print("\nRemoved DVD Subtitles due to uncompatibility with "
                      "mp4 file format")

            # The poster is fetched from tmdb only if there is no file
            # named " filename + '.jpg' " in the working directory
            # this way user can provide their own poster image to be used
            poster_filename = filename[:-4] + '.jpg'
            if not os.path.isfile(poster_filename):
                print('\nFetching the movie poster...')
                tmdb_find = tmdb.Find(imdb_movie_id)
                tmdb_find.info(external_source = 'imdb_id')
                
                path = tmdb_find.movie_results[0]['poster_path']
                complete_path = r'https://image.tmdb.org/t/p/w780' + path
                
                uo = urllib.request.urlopen(complete_path)
                with open(poster_filename, "wb") as poster_file:
                    poster_file.write(uo.read())
                    poster_file.close()
            
            

            video = MP4(newfilename)
            with open(poster_filename, "rb") as f:
                video["covr"] = [MP4Cover(
                                    f.read(),
                                    imageformat=MP4Cover.FORMAT_JPEG)]
                video['\xa9day'] = str(imdb_movie_year)
                video['\xa9nam'] = imdb_movie_title
                video['\xa9cmt'] = imdb_rating_and_plot
                video['\xa9gen'] = genre
                print('\nAdding poster and tagging file...')

            try:
                video.save()
                #  I have encounterd this error in pevious version
                #  of script, now I handle it by removing the metadata
                #  of the file. That seems to solve the probelem
            except OverflowError:
                remove_meta_command = ('ffmpeg -i "' + newfilename
                                       + '" -codec copy -map_metadata -1 "'
                                       + newfilename[:-4] + 'new.mp4"')
                subprocess.run(shlex.split(remove_meta_command))
                video_new = MP4(newfilename[:-4] + 'new.mp4')
                with open(poster_filename, "rb") as f:
                    video_new["covr"] = [MP4Cover(
                                            f.read(),
                                            imageformat=MP4Cover.FORMAT_JPEG)]
                    video_new['\xa9day'] = str(imdb_movie_year)
                    video_new['\xa9nam'] = imdb_movie_title
                    video_new['\xa9cmt'] = imdb_rating_and_plot
                    video_new['\xa9gen'] = genre
                    print('\nAdding poster and tagging file...')

                try:
                    video_new.save()
                    if not os.path.exists('auto fixed files'):
                        os.makedirs('auto fixed files')
                    os.rename(newfilename[:-4]
                              + 'new.mp4', 'auto fixed files\\'
                              + newfilename[:-4] + '.mp4')
                    os.remove(newfilename)

                except OverflowError:
                    errored_files.append(filename
                                         + (' - Could not save even after'
                                            'striping metadata'))
                    continue

            os.remove(poster_filename)
            print('\n' + filename
                       + (' was proccesed successfuly!\n\n===================='
                          '======================================'))
        except Exception as e:
            print('\nSome error occured while processing '
                  + filename
                  + '\n\n====================================================')
            errored_files.append(filename + ' - ' + str(e))
            PrintException()
Пример #19
0
    def writeTags(self, mp4Path, artwork=True, thumbnail=False):
        self.log.info("Tagging file: %s." % mp4Path)
        ext = os.path.splitext(mp4Path)[1][1:]
        if ext not in valid_output_extensions:
            self.log.error("File is not the correct format.")
            sys.exit()

        video = MP4(mp4Path)
        try:
            video.delete()
        except IOError:
            self.log.debug(
                "Unable to clear original tags, attempting to proceed.")

        video["tvsh"] = self.show  # TV show title
        video["\xa9nam"] = self.title  # Video title
        video["tven"] = self.title  # Episode title
        video["desc"] = self.shortDescription()  # Short description
        video[
            "ldes"] = self.description  # Long description (same a short for tv)
        video["tvnn"] = self.network  # Network
        if self.airdate != "0000-00-00":
            video["\xa9day"] = self.airdate  # Airdate
        video["tvsn"] = [self.season]  # Season number
        video["disk"] = [(int(self.season), 0)]  # Season number as disk
        video["\xa9alb"] = (self.show + ", Season " + str(self.season)
                            )  # iTunes Album as Season
        video["tves"] = [self.episode]  # Episode number
        video["trkn"] = [(int(self.episode), len(self.seasondata))
                         ]  # Episode number iTunes
        video["stik"] = [10]  # TV show iTunes category
        if self.HD is not None:
            video["hdvd"] = self.HD
        if self.genre is not None:
            video["\xa9gen"] = self.genre[1:-1].split("|")[0]
            # video["\xa9gen"] = self.genre.replace('|', ',')[1:-1]  # Genre(s)
        video[
            "----:com.apple.iTunes:iTunMOVI"] = self.xml  # XML - see xmlTags method
        video["----:com.apple.iTunes:iTunEXTC"] = self.setRating(
        )  # iTunes content rating

        if artwork:
            path = self.getArtwork(mp4Path, thumbnail=thumbnail)
            if path is not None:
                cover = open(path, "rb").read()
                if path.endswith("png"):
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_PNG)
                                     ]  # png poster
                else:
                    video["covr"] = [MP4Cover(cover, MP4Cover.FORMAT_JPEG)
                                     ]  # jpeg poster
        if self.original:
            video["\xa9too"] = "MDH:" + os.path.basename(self.original)
        else:
            video["\xa9too"] = "MDH:" + os.path.basename(mp4Path)
        MP4(mp4Path).delete(mp4Path)
        for i in range(3):
            try:
                self.log.info("Trying to write tags.")
                video.save()
                self.log.info("Tags written successfully.")
                break
            except IOError as e:
                self.log.exception(
                    "There was a problem writing the tags. Retrying.")
                time.sleep(5)
Пример #20
0
	def tagFile(self, filename, metadata, art_url):
		if not self.file_done:
			return
		image = None
		if art_url is not None:
			self.getFile('artwork.jpg', art_url, True)
			try:
				with open('artwork.jpg', 'rb') as file:
					image = file.read()
			except:
				pass
		if filename.endswith('.mp3'):
			audio = MP3(filename, ID3=ID3)
			try:
				audio.add_tags()
			except:
				pass
			if image:
				audio.tags.add(
					APIC(
						encoding=3,
						mime='image/jpeg',
						type=3,
						desc=u'Cover',
						data=image
					)
				)
			audio.tags["TIT2"] = TIT2(encoding=3, text=(metadata.get('title', '')))
			try:
				audio.tags["TPE1"] = TPE1(encoding=3, text=metadata.get('artist', ''))
			except:
				pass
			audio.tags["TDRC"] = TDRC(encoding=3, text=(metadata.get('year', '')))
			audio.tags["TCON"] = TCON(encoding=3, text=(metadata.get('genre', ' ')))
			audio.save()
		elif filename.endswith('.flac'):
			audio = FLAC(filename)
			try:
				audio.add_tags()
			except:
				pass
			audio.tags['title'] = metadata['title']
			audio.tags['artist'] = metadata['artist']
			audio.tags['year'] = metadata['year']
			audio.tags['genre'] = metadata['genre']
			audio.tags.add(
				APIC(
					encoding=3,
					mime='image/jpeg',
					type=3,
					desc=u'Cover',
					data=image
				)
			)
			audio.save()
		elif filename.endswith('.m4a'):
			audio = MP4(filename)
			try:
				audio.add_tags()
			except:
				pass
			covr = []
			covr.append(MP4Cover(image, MP4Cover.FORMAT_JPEG))
			audio.tags['covr'] = covr
			audio.tags['title'] = metadata['title']
			audio.tags['artist'] = metadata['artist']
			#audio.tags['year'] = metadata['year']
			audio.tags['genre'] = metadata['genre']
			audio.save()
		if os.path.isfile('artwork.jpg'):
			os.remove('artwork.jpg')
Пример #21
0
def single_album(artist_name, album_name):
    # Create query
    query = artist.replace(" ", "+") + "+" + album.replace(" ", "+") + "+album"

    # Story query album image URL
    album_url = search(query)

    # Album subfolder is just the given album name
    album_subfolder = album_name

    # Create the /album_art folder and the album subfolder
    make_img_folder(album_subfolder)

    # Download the image from the album_url URL and save it in given album name subfolder
    filename, headers = urllib.urlretrieve(
        album_url, "album_art/%s/" % album_subfolder + "img.jpg")

    print("\nDone!")
    print("\nAdding artwork to specified album...")

    # Check if album actually exists in music directory
    if os.path.exists(music_dir + artist_name + album_name):
        for dirpath, subdirs, files in os.walk(music_dir + artist_name +
                                               album_name):
            for song_name in files:
                if song_name != ".DS_Store":
                    print("Replacing %s artwork" % song_name)
                    path = music_dir + artist_name + album_name + "/"

                    # If m4a file, convert to mp3
                    if song_name.endswith("m4a"):
                        # print("Converting to %s MP3" % song_name)

                        # new_song = convert_song(artist_name, album_name, song_name)

                        # Remove old m4a file
                        # os.remove(music_dir + "%s/%s/%s" % (artist_name, album_name, song_name))

                        song = MP4(music_dir + "%s/%s/%s" %
                                   (artist_name, album_name, song_name))

                        with open(
                                dir_path +
                                "/album_art/%s/img.jpg" % album_subfolder,
                                "rb") as f:
                            song["covr"] = [
                                MP4Cover(f.read(),
                                         imageformat=MP4Cover.FORMAT_JPEG)
                            ]

                        song.save()

                        # song = mp3.MP3(path + new_song)

                    elif song_name.endswith("mp3"):
                        song = mp3.MP3(path + song_name)
                        # Change album artwork
                        imagedata = open(
                            dir_path +
                            "/album_art/%s/img.jpg" % album_subfolder,
                            "rb").read()
                        song.tags.add(
                            id3.APIC(3, 'image/jpg', 3, 'Album Artwork',
                                     imagedata))
                        song.save()

                    print("Done!")

    else:
        print(
            "Artist/album not found. Make sure you have spelt the name exactly correct."
        )
Пример #22
0
 def test_cover_png(self):
     self.set_key('covr', [
         MP4Cover(b'woooo', MP4Cover.FORMAT_PNG),
         MP4Cover(b'hoooo', MP4Cover.FORMAT_JPEG),
     ])
Пример #23
0
    def _save(self, filename, metadata):
        log.debug("Saving file %r", filename)
        file = MP4(encode_filename(self.filename))
        if file.tags is None:
            file.add_tags()
        tags = file.tags

        if config.setting["clear_existing_tags"]:
            tags.clear()

        for name, values in metadata.rawitems():
            if name.startswith('lyrics:'):
                name = 'lyrics'
            if name in self.__r_text_tags:
                tags[self.__r_text_tags[name]] = values
            elif name in self.__r_bool_tags:
                tags[self.__r_bool_tags[name]] = (values[0] == '1')
            elif name in self.__r_int_tags:
                try:
                    tags[self.__r_int_tags[name]] = [int(value) for value in values]
                except ValueError:
                    pass
            elif name in self.__r_freeform_tags:
                values = [v.encode("utf-8") for v in values]
                tags[self.__r_freeform_tags[name]] = values
            elif name in self.__r_freeform_tags_ci:
                values = [v.encode("utf-8") for v in values]
                delall_ci(tags, self.__r_freeform_tags_ci[name])
                if name in self.__casemap:
                    name = self.__casemap[name]
                else:
                    name = self.__r_freeform_tags_ci[name]
                tags[name] = values
            elif name == "musicip_fingerprint":
                tags["----:com.apple.iTunes:fingerprint"] = [b"MusicMagic Fingerprint%s" % v.encode('ascii') for v in values]
            elif self.supports_tag(name) and name not in ('tracknumber',
                    'totaltracks', 'discnumber', 'totaldiscs'):
                values = [v.encode("utf-8") for v in values]
                name = self.__casemap.get(name, name)
                tags['----:com.apple.iTunes:' + name] = values

        if "tracknumber" in metadata:
            if "totaltracks" in metadata:
                tags["trkn"] = [(int(metadata["tracknumber"]),
                                 int(metadata["totaltracks"]))]
            else:
                tags["trkn"] = [(int(metadata["tracknumber"]), 0)]

        if "discnumber" in metadata:
            if "totaldiscs" in metadata:
                tags["disk"] = [(int(metadata["discnumber"]),
                                 int(metadata["totaldiscs"]))]
            else:
                tags["disk"] = [(int(metadata["discnumber"]), 0)]

        covr = []
        for image in metadata.images.to_be_saved_to_tags():
            if image.mimetype == "image/jpeg":
                covr.append(MP4Cover(image.data, MP4Cover.FORMAT_JPEG))
            elif image.mimetype == "image/png":
                covr.append(MP4Cover(image.data, MP4Cover.FORMAT_PNG))
        if covr:
            tags["covr"] = covr

        self._remove_deleted_tags(metadata, tags)

        file.save()
Пример #24
0
    def FormatSong(self, folder, export=''):
        '''
            'Format' a song's metadata with the infomation given in folder

            Call once all download tasks is finished

            Suppports MP3,M4A(ALAC/MP4),FLAC
        '''
        export = export if export else self.output
        folder = str(folder)
        audio = [
            f for f in os.listdir(folder)
            if f.split('.')[-1] in ['mp3', 'm4a', 'flac']
        ]
        if not audio: return
        audio = audio[-1]
        audio = self.GenerateDownloadPath(filename=audio, folder=folder)
        format = audio.split('.')[-1]
        # Locate audio file,uses last match
        meta = self.GenerateDownloadPath(filename='meta.json', folder=folder)
        # Locate meta file
        cover = self.GenerateDownloadPath(filename='cover.jpg', folder=folder)
        # Locate cover image

        if not audio:
            self.log('audio.m4a / audio.mp3 / audio.flac',
                     format=strings.ERROR_FILE_MISSING)
            return
        if not os.path.exists(meta):
            self.log('meta.json', format=strings.ERROR_FILE_MISSING)
            return
        if not os.path.exists(cover):
            self.log('cover.jpg', format=strings.WARN_FILE_MISSING)

        meta = json.loads(open(meta, encoding='utf-8').read())

        def write_keys(song):
            # Write metadatas
            song['title'] = meta['title']
            song['artist'] = meta['author']
            song['album'] = meta['album']
            song.save()

        if format == 'm4a':
            # Process m4a files: Apple’s MP4 (aka M4A, M4B, M4P)
            song = easymp4.EasyMP4(audio)
            write_keys(song)
            if os.path.exists(cover):
                song = MP4(audio)
                # Write cover image
                song['covr'] = [MP4Cover(open(cover, 'rb').read())]
                song.save()
        elif format == 'mp3':
            # Process mp3 files: MPEG audio stream information and tags
            song = EasyMP3(audio)
            write_keys(song)
            if os.path.exists(cover):
                song = ID3(audio)
                # Write cover image
                song.add(
                    APIC(encoding=3,
                         mime='image/jpeg',
                         type=3,
                         desc='Cover',
                         data=open(cover, 'rb').read()))
                song.save()
        elif format == 'flac':
            # Process FLAC files:Free Lossless Audio Codec
            song = FLAC(audio)
            write_keys(song)
            if os.path.exists(cover):
                pic = Picture()
                pic.data = open(cover, 'rb').read()
                pic.mime = 'image/jpeg'
                song.add_picture(pic)
                song.save()

        # Rename & move file
        savename = '{1} - {0}.{2}'.format(meta['title'], meta['author'],
                                          format)
        try:
            path = self.GenerateDownloadPath(filename=savename, folder=export)
            shutil.copy(audio, path)
            self.log(path, format=strings.INFO_EXPORT_COMPLETE)
        except Exception as e:
            self.log(e, format=strings.ERROR_INVALID_OPERATION)
        return path
Пример #25
0
def mp3_tag(absolute_song_fp, song):
    '''tag mp3 with metdata'''
    default_path = os.path.dirname(os.path.realpath(__file__))
    no_cover_art = [
        '/img/no_album_art.png', '', '/web-client/images/empty_album.png',
        '/web-client/images/empty_album.png'
    ]
    song['coverart'] = song['coverart'].replace('"', '')
    ## Seeing if the try except clause below will fix the url error when no album art is available
    # if song['coverart'] not in no_cover_art:
    #     r = urllib2.urlopen(song['coverart'])
    #     picture_type = song['coverart'].split('.')[-1]
    #     cover_art_path = default_path + '\\' + 'coverart' + '.' + picture_type
    #     temp_art = open(cover_art_path, 'wb')
    #     temp_art.write(r.read())
    #     temp_art.close()
    # else:
    try:
        r = urllib2.urlopen(song['coverart'])
        picture_type = song['coverart'].split('.')[-1]
        cover_art_path = default_path + '\\' + 'coverart' + '.' + picture_type
        temp_art = open(cover_art_path, 'wb')
        temp_art.write(r.read())
        temp_art.close()
    except:
        song['coverart'] = None
    if SONG_QUALITY == '.m4a':
        try:
            audio = MP4(absolute_song_fp)
            if song['coverart']:
                with open(cover_art_path, 'rb') as f:
                    audio['covr'] = [
                        MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_PNG)
                    ]
                os.remove(cover_art_path)  # delete coverart
            audio["\xa9nam"] = unicode(song['song'])
            audio["\xa9ART"] = unicode(song['artist'])
            audio["\xa9alb"] = unicode(song['album'])
            audio.save()
        except:
            print "\nUnexpected error:", sys.exc_info()[0]
            pass
    if SONG_QUALITY == '.mp3':
        try:
            audio = MP3(absolute_song_fp)
            if song['coverart']:
                audio.tags.add(
                    APIC(
                        encoding=3,  # 3 is for utf-8
                        mime='image/' +
                        picture_type,  # image/jpeg or image/png
                        type=3,  # 3 is for the cover image
                        desc=u'Cover',
                        data=open(cover_art_path, 'rb').read()))
                os.remove(cover_art_path)  # delete coverart
            audio.tags.add(TIT2(encoding=3, text=unicode(song['song'])))
            audio.tags.add(TPE1(encoding=3, text=unicode(song['artist'])))
            audio.tags.add(TALB(encoding=3, text=unicode(song['album'])))
            audio.save(mp3, v1=2, v2_version=3)
        except:
            print "\nUnexpected error:", sys.exc_info()[0]
            pass
    print ""