def from_tags(self): # artist - album - title - genre - year - track # duration tags = auto.File(os.path.join(self.dirpath, self.filename)) if tags.valid: self.data['duration'] = float(tags.duration) self.data['contributors'] = [{ 'name': tags.artist, 'role': 'MainArtist' }] self.data['release'] = { 'title': tags.album, 'contributors': [{ 'name': tags.artist, 'role': 'MainArtist' }] } self.data['trackNumber'] = tags.track self.data['title'] = tags.title self.data['genre'] = tags.genre self.data['details'] = [] try: self.data['details'] = [{'year': int(tags.year)}] except ValueError as exc: # ValueError is raised when tags.year cannot be converted to int logger.warning(u'Cannot convert year: {0} to int ({1})'.format( tags.year, str(exc))) else: logger.warning( u'Could not read the tags for this file: {0}'.format( os.path.join(self.dirpath, self.filename)))
def _get_tracks(self): """ Walk through all files and folders """ from hsaudiotag import auto # hsaudiotag3k for root, dirs, files in os.walk(self.destination): for file in files: path = os.path.join(root, file) tags = auto.File(path) if not tags.valid: #print(path) continue artist = tags.artist.strip() if not artist: artist = 'Unknown artist' album = tags.album.strip() if not album: album = '_' title = tags.title.strip() if not title: title = 'Unknown track' if artist not in self.tracks: self.tracks[artist] = {} if album not in self.tracks[artist]: self.tracks[artist][album] = [] self.tracks[artist][album].append(title)
def hsaudiotag_auto(): from hsaudiotag import auto myfile = auto.File(FILE) myfile.artist myfile.album myfile.title myfile.track myfile.duration
def download_part(self, url, target, params, item): self.dl_running = True try: self.part = requests.get(url, stream=True, params=params) if self.part.status_code == 404: gui.show_message("Server: File not found", mode="error") self.dl_ready = "failure" return elif self.part.status_code != 200: gui.show_message("Server Error", mode="error") self.dl_ready = "failure" return except: gui.show_message("Could not connect to server", mode="error") self.dl_ready = "failure" return bitrate = 0 a = 0 z = 0 if os.path.isfile(target): os.remove(target) with open(target, 'wb') as f: for chunk in self.part.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks a += 1 if a == 300: # kilobyes~ self.dl_ready = True if url != self.active_url: self.part.close() print("Abort download") break f.write(chunk) z += 1 if z == 60: z = 0 if bitrate == 0: audio = auto.File(target) bitrate = audio.bitrate if bitrate > 0: gui.update += 1 pctl.download_time = a * 1024 / (bitrate / 8) / 1000 pctl.download_time = -1 self.dl_ready = True self.dl_running = False
def download(self): print("Start download") try: self.part = requests.get(self.network_url, stream=True, params=self.params) if self.part.status_code == 404: gui.show_message("Server: File not found", mode="error") self.status = "error" return elif self.part.status_code != 200: gui.show_message("Server Error", mode="error") self.status = "error" return except: gui.show_message("Could not connect to server", mode="error") self.status = "error" return bitrate = 0 a = 0 z = 0 with open(self.filepath, 'wb') as f: for chunk in self.part.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks a += 1 if a == 300: # kilobyes~ self.status = "ready" if self.cancel is True: self.part.close() self.status = "failed" print("Abort download") return f.write(chunk) z += 1 if z == 60: z = 0 if bitrate == 0: audio = auto.File(self.filepath) bitrate = audio.bitrate if bitrate > 0: gui.update += 1 self.downloaded_duration = a * 1024 / ( bitrate / 8) / 1000 #pctl.download_time = a * 1024 / (bitrate / 8) / 1000 #pctl.download_time = -1 self.status = "done" print("Download done")
def get_file_infos(self, sfile): if sfile is not None: mfile = auto.File(sfile) fileInfos = dict() fileInfos.update({ "artist": mfile.artist, "album": mfile.album, "title": mfile.title, "track_number": mfile.track }) return fileInfos
def map_audio(self): """ Takes in a string that represents thefile directory that will be inspected for MP3 and M4A files. Returns a dictionary. The key of the dictionary is an Artist. The value is another dictionary, whose key is the Album title, and value is a dictionary of songs. Each song dictionary is key'ed by its name, and its value is a list of the songs that were considered duplicates as a list. The song list object has dictionaries of each song, include keys for bitrate, path, and file type. """ for root, dirs, files in os.walk(self.dir): for name in files: if (name.split(".")[-1].lower() == 'm4a' or \ name.split(".")[-1].lower() == 'mp3'): cur_path = "{0}/{1}".format(root, name) cur_file = auto.File(cur_path) artist = cur_file.artist.lower().strip() album = cur_file.album.lower().strip() title = cur_file.title.lower().strip() bitrate = cur_file.bitrate if not artist in self.audio_dict: self.audio_dict[artist] = {} if not album in self.audio_dict[artist]: self.audio_dict[artist][album] = {} title_key = title for in_album_title in self.audio_dict[artist][album]: if sm(None, title, in_album_title).ratio() > 0.9: title_key = in_album_title if not title_key in \ self.audio_dict[artist][album]: self.audio_dict[artist][album][title_key] = [] self.audio_dict[artist][album][title_key].append({ 'path': cur_path, 'bitrate': bitrate, 'file_name': name }) return self
def explore_collection(original_path): tracks = [] for path, dirs, files in os.walk('%s' % original_path): for f in files: if f.split('.')[-1] in SUPPORTED_FILETYPES: abs_path = os.path.join(path, f) tags = auto.File(abs_path) music_path = abs_path.replace(original_path, '') track = (music_path, tags.title, tags.track, tags.duration, tags.artist, tags.album) tracks.append(track) return tracks
def _read_info(self, field): fs.File._read_info(self, field) if field in TAG_FIELDS: f = auto.File(str(self.path)) self.audiosize = f.audio_size self.bitrate = f.bitrate self.duration = f.duration self.samplerate = f.sample_rate self.artist = f.artist self.album = f.album self.title = f.title self.genre = f.genre self.comment = f.comment self.year = f.year self.track = f.track
def playlist_add(): if request.method == 'POST': if request.files: fp = request.files['media_file'] if fp: if allowed_file(fp.filename): filename = secure_filename('%d-%s.%s' % (time.time(), randint(1000, 999999), fp.filename)) filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) fp.save(filepath) # saved file, now try to get the uploaded info audio_file = auto.File(filepath) return render_template('playlist/confirm_upload.html', uri=filepath, song_title=audio_file.title, artist=audio_file.artist ) else: err = '%s and %s' % (', '.join(ALLOWED_EXTENSIONS[:-1]), ALLOWED_EXTENSIONS[-1]) flash(err, 'error') return else: search_term = request.form['search'] is_yt = yt_re.search(search_term) uri = title = artist = None if is_yt: video_id = get_video_id(search_term) title, artist = get_video_info(video_id) if artist is None: title, artist = title_splitter(title) else: title, artist = get_from_echonest(search_term) if not title: title = search_term.capitalize() if not artist: artist = 'Unknown' return render_template('playlist/confirm_upload.html', uri=search_term, song_title=title, artist=artist ) return render_template('playlist/add.html')
def track_info(path): #print path try: track = auto.File(path) return [ track.title, track.album, track.artist, #path.split('/')[:-1], path, track.duration ] #return Track(track.title, #track.album, #track.artist, #path.split('/')[-1], #track.duration) except IOError: pass
def process(file, config, rcontext, columns=None): fullpath = file.fullpath # Try to parse .ogg data try: # Read the .ogg file ogg_file = auto.File(fullpath) # Check if .ogg file is readed correctly if ogg_file.valid: # Store audio data in list assorted = [ ogg_file.title, ogg_file.artist, ogg_file.album, ogg_file.genre, ogg_file.year, ogg_file.track, ogg_file.comment, ogg_file.duration, ogg_file.sample_rate, ogg_file.audio_size, ogg_file.bitrate, ogg_file.audio_offset ] # delete the ogg_file variable del ogg_file # Make sure we stored exactly the same amount of columns as # specified!! assert len(assorted) == len(columns) # Print some data that is stored in # the database if debug is true if config.DEBUG: print "\nOGG file data:" for i in range(0, len(assorted)): print "%-18s %s" % (columns[i], assorted[i]) print # Store in database return assorted else: return None except: traceback.print_exc(file=sys.stderr) # Store values in database so not the whole application crashes return None
def _build_rewritten_filenames(self): """ Rewrite file names of playlists for destination folder """ for k, f in enumerate(self.playlists_files): name, ext = os.path.splitext(os.path.basename(f)) # Rewrite file names to ID3 tags # TODO Maximum filename length on some file systems if self.rewrite_file_names: from hsaudiotag import auto # hsaudiotag3k tags = auto.File(f) if not tags.artist.strip(): raise IOError('Tag artist is empty %s' % f) if not tags.album.strip(): raise IOError('Tag album is empty %s' % f) if not tags.title.strip(): raise IOError('Tag title is empty %s' % f) name = '%s - %s - %s' % (tags.artist, tags.album, tags.title ) # Actually - should be – name = re.sub('[^\w\s()-\.\']', '', name).strip() # Check if file with same potential filename already exists in same PL # If so, append (1), (2), etc. to filename nth_file = 0 while True: nth_file += 1 nth = ' (%d)' % nth_file if nth_file > 1 else '' new_name = '%s%s' % (name, nth) # Compare lowered names, needed for case-insensitive file systems rewritten_lower = map(lambda n: n.lower(), self.playlists_files_rewritten.values()) if (new_name + ext).lower() not in rewritten_lower: name = new_name break self.playlists_files_rewritten[k] = name + ext
def scanMedia(path): confirmExistence(path) formatPath(path) playArr = [] imgArr = [] types = [ '*.mp3', '*.wav', '*.ogg', '*.mp4', '*.webm', '*.ogv', '*.jpg', '*.jpeg', '*.gif', '*.png' ] types = r'|'.join([fnmatch.translate(x) for x in types]) #mp3s = [os.path.join(root, i) for root, dirs, files in os.walk(path) for i in files if i[-3:] == "mp3"] #preliminary functionality media = [ os.path.join(root, x) for root, dirs, files in os.walk(path) for x in files if re.match(types, x) ] for file in media: #print file file = os.path.abspath(file).rstrip('\0') name, ext = os.path.splitext(file) type = checkType(ext).rstrip('\0') if type == 'image': info = {'image': file, 'filename': fileNameOnly(file)} #print fileNameOnly(file) imgArr.append(info) elif type == 'audio': meta = auto.File(file) #getID3v1(file) title = meta.title.rstrip('\0') artist = meta.artist.rstrip('\0') album = meta.album.rstrip('\0') comment = meta.comment.rstrip('\0') duration = meta.duration location = [] location.append(file) info = { 'filename': title, 'type': type, 'creator': artist, 'album': album, 'title': title, 'comment': comment, 'duration': duration, 'location': location, 'image': '', 'info': type, #'path' : file } #print title playArr.append(info) #playArr[title] = OrderedDict([('filename',title), # ('type',checkType(ext).rstrip('\0')), # ('creator',artist), # ('album',album), # ('title',title), # ('annotation',annotation), # ('path',track)]) # } else { # // Apply album/creator image # for ($k=0;$k<sizeOf($gloArr);$k++){ # if ($gloArr[$k]['path'] == $playVal['path']){ # $playVal['image'] = ''.$gloArr[$k]['path'].'/'.$gloArr[$k]['file']; # } # } # } # } for playVal in playArr: for i in range(0, len(imgArr)): if imgArr[i]['filename'] == playVal['filename']: playVal['image'] = imgArr[i]['image'] #//echo $globalImg; #// Apply global image # if($playVal['image'] == '' && $globalImg != ''){ $playVal['image'] = $globalImg; } return playArr
def get_directory_entries(self, root, rootfd, files): log.info('Processing: {}'.format(root)) # Get the path relative to the top level directory relative_path = os.path.relpath(root, self._topdir) # If we don't have it, it's the top level directory so we # seed the _paths dictionary. if relative_path not in self._paths: self._paths[relative_path] = {'shortname': '/'} # Get the shortname for the directory (collected one level up). current_path_shortname = self._paths[relative_path]['shortname'] while True and HAVE_FCNTL: # Get both names for the next directory entry using a ioctl call. result = fcntl.ioctl(rootfd, vfat_ioctl.VFAT_IOCTL_READDIR_BOTH, self._buffer) # Have we finished? if result < 1: break # Interpret the resultant bytearray # sl = length of shortname # sn = shortname # ll = length of longname # ln = longname sl, sn, ll, ln = struct.unpack(vfat_ioctl.BUFFER_FORMAT, self._buffer) # Decode the bytearrays into strings # If longname has zero length, use shortname shortname = sn[:sl].decode() if ll > 0: filename = ln[:ll].decode() else: filename = shortname # Don't process . or .. if (filename != '.') and (filename != '..'): fullname = os.path.join(root, filename) # Check whether it's a directory if os.path.isdir(fullname): # Create the _paths entry, add following os.sep self._paths[os.path.relpath(fullname, self._topdir)] = { 'shortname': os.path.join(current_path_shortname, shortname, '') } else: if filename.lower().endswith(valid_media_files): self._file_index += 1 print('Files: {}, Playlists: {}'.format( self._file_index + 1, self._playlist_index + 1), end='\r') title = "" performer = "" album = "" genre = "" # If there is no ID3 information: # # Title <- filename without extension # Album <- parent directory # Performer <- grandparent directory # Genre <- 0 metadata = auto.File(fullname) title = metadata.title if title == "": title = filename.split(".")[0] # KMEL seems to remove all but the first performer # if there is a '/' in this field. # To be compatible, we'll do the same. # TODO: Remove this restriction after compatibility # testing. performer = metadata.artist performer = performer.split('/')[0] if performer == "": # KMEL seems to use the grandparent directory if the # performer is empty. try: performer = os.path.basename( os.path.split(relative_path)[0]) except: performer = "" album = metadata.album if album == "": # KMEL seems to use the parent directory if the album # is empty. album = os.path.basename(relative_path) genre = metadata.genre if genre == "": pass track = metadata.track if hasattr(metadata, 'disc'): disc = metadata.disc else: disc = 0 mf = MediaFile( index=self._file_index, fullname=fullname, shortdir=self._paths[relative_path]['shortname'], shortfile=shortname, longdir='{}{}{}'.format(os.sep, relative_path, os.sep), longfile=filename, title=title, performer=performer, album=album, genre=genre, tracknumber=track, discnumber=disc) self._media_files.append(mf) log.debug(mf) elif filename.lower().endswith(valid_media_playlists): self._playlist_index += 1 print('Files: {}, Playlists: {}'.format( self._file_index + 1, self._playlist_index + 1), end='\r') self._playlists.append(playlist(fullname))
def get_seconds(audio_file): audio_file = auto.File(audio_file) return audio_file.duration
def get_tags_info(audio_file): myfile = auto.File(audio_file) title = myfile.title duration = (float(myfile.duration)) / 60 return {'title': title, 'duration': duration}
def __init__(self, path): QThread.__init__(self) # self.file will be used to get the file duration, and tags self.file = auto.File(path.replace('/', os.sep).replace('\\', os.sep)) # pygame mixer will be used to play the file pygame.mixer.music.load(path.replace('/', os.sep).replace('\\', os.sep))
def _get_md5partial_offset_and_size(self): f = auto.File(str(self.path)) return (f.audio_offset, f.audio_size)
def get_month_data(month_dir): songs = [] month_files = os.listdir(month_dir) song_filenames = [f for f in month_files if f.endswith('.mp3')] max_rank = max( [f.split("-")[0] for f in song_filenames if not f.startswith('ZZ')], default=0) youtube_link = get_youtube_link(month_dir) month_dir_part = month_dir.replace(ARCHIVE_DIR, '').strip(os.sep) month_dir_replaced = fix_month_dir(month_dir_part) banner_jpg = (month_dir_part + '.jpg' in month_files) banner_gif = (month_dir_part + '.gif' in month_files) for f in song_filenames: song_path = os.path.join(month_dir, f) song_data = parse_id3.File(song_path) duel = fix_duel_name(song_data.album).replace('DoD', '', 1) month_number = duel.split('-')[1].split(':')[0] artist = fix_artist(song_data.artist) songs.append({ 'rank': f.split('-')[0].replace('tie', ''), 'max_rank': max_rank, 'artists': artist.split(', '), 'multiple_artists': len(artist.split(', ')) > 1, 'games': song_data.genre.split(', '), 'multiple_games': len(song_data.genre.split(', ')) > 1, 'title': song_data.title, 'duration': song_data.duration, 'duel': duel, 'link': '/' + song_path.replace('\\', '/'), 'theme': duel.split(': ', 1)[1], 'year': '20' + duel.split('-')[0], 'month': month_number, 'month_name': calendar.month_name[int(month_number)], 'month_dir': month_dir_replaced, 'has_log': month_dir_part + '.log' in month_files, 'has_banner': banner_jpg or banner_gif, 'has_lyrics': 'lyrics.txt' in month_files, 'banner_jpg': banner_jpg, 'banner_gif': banner_gif, 'has_archive': month_dir_part + '.zip' in month_files, 'youtube_link': youtube_link, 'id': hashlib.md5((song_data.title + song_data.genre.split(', ')[0] + duel).encode()).hexdigest()[:10] }) return songs
for filename in filenames: count_Files += 1 trackFileName = os.path.join(root, filename) print_Line = "File: " + trackFileName + "\n" if trackFileName.endswith(".mp3"): trackFormat = "MP3" elif trackFileName.endswith(".m4a"): trackFormat = "MP4" else: trackFormat = "???" count_Skipped += 1 if trackFormat != "???": audioSeg = AudioSegment.from_file(trackFileName, format=trackFormat) print_Line += " Format: " + trackFormat + "\n" myMusic = auto.File(trackFileName) print_Line += " Title: " + myMusic.title + "\n" print_Line += " Artist: " + myMusic.artist + "\n" print_Line += " Album: " + myMusic.album + "\n" print_Line += " Track: " + str(myMusic.track) + "\n" if trackFormat != "???": print_Line += " dBFS: " + str(audioSeg.dBFS) + "\n" print_Line += " Max dBFS: " + str(audioSeg.max_dBFS) + "\n" print_Line += " rms: " + str(audioSeg.rms) + "\n" print_Line += " Max rms: " + str(audioSeg.max) + "\n" print_Line += " Dur: " + str(myMusic.duration) + " secs\n" if myMusic.bitrate > 0: print_Line += " BitRate: " + str(myMusic.bitrate) + "\n" storedRate = myMusic.bitrate else: print_Line += " Sample Rate: " + str(myMusic.sample_rate) + "\n"
def auto_default(): myfile = auto.File(FILE) report(myfile)
def download_part(self, url, target, params, id): # GStreamer can't seek some types of HTTP sources. # # To work around this, when a seek is requested by the user, this # function facilitates the download of the URL in whole, then loaded # into GStreamer as a complete file to provide at least some manner of seeking # ability for the user. (User must wait for full download) # # (Koel and Airsonic MP3 sources are exempt from this as seeking does work with them) # # A better solution might be to download file externally then feed the audio data # into GStreamer as it downloads. This still would have the issue that the whole file # must have been downloaded before a seek could begin. # # With the old BASS backend, this was done with the file on disk being constantly # appended to. Unfortunately GStreamer doesn't support playing files in this manner. try: part = requests.get(url, stream=True, params=params) except: gui.show_message("Could not connect to server", mode="error") self.dl_ready = True return bitrate = 0 a = 0 z = 0 # print(target) f = open(target, "wb") for chunk in part.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks a += 1 # if a == 300: # kilobyes~ # self.dl_ready = True if id != self.id: part.close() f.close() os.remove(target) return # break f.write(chunk) # Periodically update download the progress indicator z += 1 if id == self.id: if z == 60: z = 0 if bitrate == 0: audio = auto.File(target) bitrate = audio.bitrate if bitrate > 0: gui.update += 1 pctl.download_time = a * 1024 / (bitrate / 8) / 1000 f.close() pctl.download_time = -1 self.dl_ready = True
def process_Files(self): global musicDir if musicDir == "": musicDir = self.musicDir_Box.currentText() myDBRefresh = self.musicDir_Box.currentData()[0] myTestProd = self.musicDir_Box.currentData()[1] else: print( str(datetime.datetime.now().strftime("%H:%M:%S")) + " Processing of files in '" + musicDir + "'") self.openDatabase() if not os.path.exists(musicDir): messageText = str(datetime.datetime.now().strftime("%H:%M:%S")) + \ " ERROR!! Path '" + str(musicDir) + "' was NOT FOUND!" self.messages_List.insertPlainText(messageText + "\n") print(messageText) sys.exit(4) else: messageText = str(datetime.datetime.now().strftime("%H:%M:%S")) + \ " Scanning files in '" + str(musicDir) self.messages_List.insertPlainText(messageText + "\n") total_File_Count = sum(len(files) for _, _, files in os.walk(musicDir)) messageText = str(datetime.datetime.now().strftime("%H:%M:%S")) + \ " Found " + str(total_File_Count) + " files to process" self.messages_List.insertPlainText(messageText + "\n") count_Dirs = 0 count_Files = 0 count_Skipped = 0 count_Tracks = 0 messageText = str(datetime.datetime.now().strftime( "%H:%M:%S")) + " Processing started" self.messages_List.insertPlainText(messageText + "\n") for root, directories, filenames in os.walk(musicDir): for directory in directories: count_Dirs += 1 for filename in filenames: QtWidgets.QApplication.processEvents() count_Files += 1 trackFileName = os.path.join(root, filename) if trackFileName.endswith( ".mp3") and '.Apple' not in trackFileName: trackFormat = "MP3" elif trackFileName.endswith( ".m4a") and '.Apple' not in trackFileName: trackFormat = "MP4" else: trackFormat = "???" if trackFormat != "???": audioSeg = AudioSegment.from_file(trackFileName, format=trackFormat) myMusic = auto.File(trackFileName) if myMusic.bitrate > 0: storedRate = myMusic.bitrate else: storedRate = myMusic.sample_rate filestat = os.stat(trackFileName) # Only use if duration is greater than 15 seconds if myMusic.duration > 15: insertTrackList = [ trackFormat, trackFileName.encode('ascii', 'replace'), myMusic.artist, myMusic.album, myMusic.title.encode('ascii', 'replace'), str(myMusic.track), myMusic.genre, str(myMusic.duration), str(format(myMusic.size / (1024 * 1024), '.2f')), str(storedRate), '{0:.4f}'.format(audioSeg.dBFS), str(audioSeg.rms), str( datetime.datetime.fromtimestamp( os.path.getmtime(trackFileName))) ] self.add_track_to_database(insertTrackList) count_Tracks += 1 else: insertSkippedList = [ trackFormat, trackFileName.encode('ascii', 'replace') ] self.add_skipped_to_database(insertSkippedList) count_Skipped += 1 else: insertSkippedList = [ trackFormat, trackFileName.encode('ascii', 'replace') ] self.add_skipped_to_database(insertSkippedList) count_Skipped += 1 if count_Files % 10 == 0: # Update Progress Bar display files_processed_pct = (count_Files / total_File_Count) * 100 self.progressBar.setValue(files_processed_pct) if count_Files % 500 == 0: messageText = str( datetime.datetime.now().strftime("%H:%M:%S")) messageText += " Processing - Files: " + str(count_Files) messageText += ", Tracks:" + str( count_Tracks) + ", Skipped:" + str(count_Skipped) self.messages_List.insertPlainText(messageText + "\n") # print(messageText) self.messages_List.verticalScrollBar().setValue( self.messages_List.verticalScrollBar().maximum()) messageText = str(datetime.datetime.now().strftime("%H:%M:%S")) messageText += " End! Dirs=" + str(count_Dirs) + ", Files=" + str( count_Files) messageText += ", Tracks:" + str(count_Tracks) + ", Skipped:" + str( count_Skipped) self.messages_List.insertPlainText(messageText + "\n") print(messageText) # disconnect from server cursor.close() db.close()