def setmusiclength(self): #important function on a player (also hard to do) if self.currentsong.endswith('.mp3') == True: self.song = MP3(self.currentsong) self.songinfo = ID3(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songmins = str(self.songmins).zfill(2) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs)) try: self.songname.config(text=self.songinfo['TIT2'].text[0]) self.artistname.config(text=self.songinfo['TPE1'].text[0]) self.albumname.config(text=self.songinfo['TALB'].text[0]) except: self.songname.config(text=self.currentsong) self.artistname.config(text='failed to read metadata') self.albumname.config(text='failed to read metadata') if self.currentsong.endswith('.flac') == True: self.song = FLAC(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songmins = str(self.songmins).zfill(2) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs)) self.music_player_scale.config(from_=0, to=self.songlength) try: self.songname.config(text=self.song['TITLE']) self.artistname.config(text=self.song['ARTIST']) self.albumname.config(text=self.song['ALBUM']) except: self.songname.config(text=self.currentsong) self.artistname.config(text='failed to read metadata') self.albumname.config(text='failed to read metadata') if self.currentsong.endswith('.ogg') == True: self.song = WAVE(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs))
def __init__(self, fileLocation): self.musicLocation = fileLocation try: self.musicLength = floor(MP3(self.musicLocation).info.length) except: self.musicLength = floor(WAVE(self.musicLocation).info.length) self.musicTitle = Path(self.musicLocation).name
def _process_audio_file(self, file_path: str, format_name: str): if format_name == "mp3": audio = MP3(file_path) elif format_name == "wav": audio = WAVE(file_path) self.duration = float(audio.info.length) self.size = float(os.stat(file_path).st_size)
def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.tmp_wav_pcm_2s_16000_08_ID3v23.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = WAVE(self.tmp_wav_pcm_2s_16000_08_ID3v23.filename) self.failUnlessEqual(new["TIT1"], ["foobar"])
def test_picard_lifecycle(self): path_tmp_wav_file = \ get_temp_copy(self.fn_wav_pcm_2s_16000_08_notags) from mutagen.id3 import ID3 wav = WAVE(path_tmp_wav_file) id3 = wav.tags """" Picard WaveFile._get_tags: """ self.assertIsNone(id3, "Ensure ID3-tag-header does not exist") """" Picard WaveFile._get_tags: initialize tags """ wav.add_tags() id3 = wav.tags self.assertIsInstance(id3, ID3) """ ID3v2.3 separator """ separator = '/' """ Initialize Picard like metadata tags """ self.__init_id3_tags(id3, major=3) """ Write the Picard like metadata to the empty WAVE-file """ id3.save(path_tmp_wav_file, v23_sep=separator) """ Tags (metadata) have been added; now load the file again """ wav = WAVE(path_tmp_wav_file) id3 = wav.tags self.assertIsInstance(id3, ID3) self.assertEquals(id3["TRCK"], "1/10") self.assertEquals(id3["TPOS"], "1/1") self.assertEquals(id3["TXXX:MusicBrainz Release Group Id"], "e00305af-1c72-469b-9a7c-6dc665ca9adc") self.assertEquals(id3["TXXX:MusicBrainz Album Artist Id"], [ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ]) self.assertEquals(id3["TXXX:CATALOGNUMBER"], ["PRAR931391"]) self.assertEquals(id3["TSRC"], ["NLB931100460", "USMH51100098"])
def load(): if self.fileType == "mp3": self.raw = MP3(self.filePath) elif self.fileType == "wav": self.raw = WAVE(self.filePath) self.info = self.raw.info self.ok = True # we've got all required info, lets try to grab some more complex data self.tags = ID3(self.filePath) art_frames = self.tags.getall("APIC") art = [add_frame_to_cache(frame) for frame in art_frames] if len(art): self.art = art
def get_audio_file_duration(file_path: str) -> float: _, ext = os.path.splitext(file_path) if ext not in [".mp3", ".wav"]: raise ValueError("Unsupported file format: %s (%s)" % (ext, file_path)) if ext == ".mp3": mp3 = MP3(file_path) duration = mp3.info.length elif ext == ".wav": wav = WAVE(file_path) duration = wav.info.length return duration
def _play_wav(self, file_path: str) -> None: if not shutil.which("aplay"): raise Exception( 'Unable to find "aplay" binary. Make sure it\'s installed on the ' "system." ) wav = WAVE(file_path) duration = wav.info.length LOG.trace('Playing audio file "%s"' % (file_path), duration=duration) args = "aplay -q %s" % (shlex.quote(file_path)) # NOTE: We set preexec_fn since we want child process to also be killed if the parent is # killed subprocess.run(args, shell=True, check=True, preexec_fn=on_parent_exit("SIGTERM"))
def audioFile(audio): aud_str = str(audio) if aud_str.endswith(".mp3"): aud1 = MP3(audio) len1 = aud1.info.length return int(len1) elif aud_str.endswith('.wav'): aud2 = WAVE(audio) len2 = aud2.info.length return int(len2) elif aud_str.endswith('.flac'): aud3 = FLAC(audio) len3 = aud3.info.length return int(len3) elif aud_str.endswith('.aac'): aud4 = AAC(audio) len4 = aud4.info.length return int(len4) elif aud_str.endswith('.ac3'): aud5 = AC3(audio) len5 = aud5.info.length return int(len5) elif aud_str.endswith('.aiff'): aud6 = AIFF(audio) len6 = aud6.info.length return int(len6) elif aud_str.endswith('.asf'): aud7 = ASF(audio) len7 = aud7.info.length return int(len7) elif aud_str.endswith('.dsf'): aud8 = DSF(audio) len8 = aud8.info.length return int(len8) elif aud_str.endswith('.mp4'): aud9 = MP4(audio) len9 = aud9.info.length return int(len9) elif aud_str.endswith('.smf'): aud10 = SMF(audio) len10 = aud10.info.length return int(len10) elif aud_str.endswith('.ogg'): aud12 = OggFileType(audio) len12 = aud12.info.length return int(len12) else: return str("File type not supported.")
def run(self): if self.audioname != "none": pygame.mixer.music.load(self.audioname) if self.audioname[-3:] == "mp3": self.song = MP3(self.audioname) elif self.audioname[-3:] == "wav": self.song = WAVE(self.audioname) elif self.audioname[-3:] == "ogg": self.song = OggFileType(self.audioname) #not tested self.songLength = self.song.info.length if self.pushtotalk: self.c.press(self.pushkey) pygame.mixer.music.play() while self.running == True and pygame.mixer.music.get_busy( ) == True: time.sleep(0.5) pass if self.pushtotalk: self.c.release(self.pushkey)
async def on_voice_state_update(user, before, after): val = random.randint(1, 8) if val == 2: if after.channel is not None and before.channel is None and user.id != 665024859918696509: print("you win!!!") print(f"{user} joined {after.channel}") wait_time = random.randint(1, 30) print(f"waiting {wait_time}") time.sleep(wait_time) vc = await after.channel.connect() time.sleep(1) peez_list = os.listdir("./peezy_mp3") clip = peez_list[random.randint(0, len(peez_list) - 1)] audio = WAVE(f"./peezy_mp3/{clip}") vc.play(discord.FFmpegPCMAudio(f"./peezy_mp3/{clip}")) time.sleep(audio.info.length) for x in client.voice_clients: await x.disconnect() print("Done")
def checkFileValidity(filename, directory, format): audio = "" if format == "FLAC": try: audio = FLAC(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "AIFF": try: audio = AIFF(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "MP3": try: audio = MP3(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "OGG": try: audio = OggVorbis(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "WAV": try: audio = WAVE(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" elif format == "M4A": # M4A is deprecated in mutagen, MP4 is suggested instead try: audio = MP4(str(directory) + "/" + str(filename)) except: messagebox.showinfo("Error", "Invalid or Corrupt File") return "Invalid or corrupt file\n" return audio
def setUp(self): fn_wav_pcm_2s_16000_08_id3v23 = \ os.path.join(DATA_DIR, "silence-2s-PCM-16000-08-ID3v23.wav") self.wav_pcm_2s_16000_08_ID3v23 = \ WAVE(fn_wav_pcm_2s_16000_08_id3v23) self.tmp_fn_pcm_2s_16000_08_ID3v23 = \ get_temp_copy(fn_wav_pcm_2s_16000_08_id3v23) self.tmp_wav_pcm_2s_16000_08_ID3v23 = \ WAVE(self.tmp_fn_pcm_2s_16000_08_ID3v23) self.fn_wav_pcm_2s_16000_08_notags = \ os.path.join(DATA_DIR, "silence-2s-PCM-16000-08-notags.wav") self.wav_pcm_2s_16000_08_notags = \ WAVE(self.fn_wav_pcm_2s_16000_08_notags) self.tmp_fn_pcm_2s_16000_08_notag = \ get_temp_copy(self.fn_wav_pcm_2s_16000_08_notags) self.tmp_wav_pcm_2s_16000_08_notag = \ WAVE(self.tmp_fn_pcm_2s_16000_08_notag) fn_wav_pcm_2s_44100_16_id3v23 = \ os.path.join(DATA_DIR, "silence-2s-PCM-44100-16-ID3v23.wav") self.wav_pcm_2s_44100_16_ID3v23 = WAVE(fn_wav_pcm_2s_44100_16_id3v23)
"Started new video, {} id: {}".format(post_title, post.id)) except: pass submission_id = post.id vidname = post.id submission = reddit.submission(submission_id) text_to_wav("en-US-Wavenet-B", submission.title, "1post") print(" - post text converted to wav - ") screenshotter.createPostSS(submission.title, sub_input, subIcon, upImage, downImage, str(submission.ups), submission.author) print(" - created post ss - ") imgdir = pathlib.Path(SAMPLE_INPUTS + '/imgs/1post') path = os.path.join(SAMPLE_INPUTS, "audio") file = os.path.join(path, "1post.wav") aud = WAVE(file) audio_info = aud.info duration = int(audio_info.length) output_video = os.path.join(SAMPLE_OUTPUTS, "1post_output.mp4") video_creator.makeVideo(imgdir, file, output_video, duration) submissionList = [] submission.comments.replace_more(limit=10) comments = submission.comments.list() commentCounter = 0 timeCounter = 0.0 avatar = submission.author.icon_img response = requests.get(avatar) file = open(pathlib.Path(RESOURCES + "/images/avatar.png"), "wb") file.write(response.content)
def main(): op = OptionParser(usage=__doc__) op.add_option("--folder", help="name of the folder to process") op.add_option("--catno", help="release catalogue number to search by") op.add_option("--id", help="Discogs release code to search by") op.add_option("--list", help="list versions of the release and exit") op.add_option("--debug", help="print out the details for debugging") opts, args = op.parse_args() if opts.debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.WARNING) tracklist = [] bitrates = [] file_counter = 0 total_duration = 0 image_counter = 0 fetched_release_info = {} folder_name_pattern = {} results = None calculated_duration = (0, 0, 0) calculated_duration_from_audio = (0, 0, 0) release_info = re.split(r'[^a-zA-Z\d\s:\!\.\']', opts.folder) release_info = filter(None, release_info) artist = next(release_info).strip() album = next(release_info).strip().title() if opts.list: list_results = d.search(album, artist=artist, type='release') for i in range(list_results.count): print_release_version(list_results[i]) sys.exit() folder_files = sorted(os.listdir(opts.folder)) audio_files, files_count, sample_file_1, sample_file_2 = filter_files( folder_files) print(f"audio files found: {files_count}") # ========================================================================== logger.debug(f"\n >>> parsed artist: {artist}") logger.debug(f"\n >>> parsed album: {album}") logger.debug(f"\n >>> folder files: {folder_files}") logger.debug(f"\n >>> audio files: {audio_files}") logger.debug(f"\n >>> sample file 1: {sample_file_1}") logger.debug(f"\n >>> sample file 2: {sample_file_2}") # ========================================================================== if opts.id: fetched_release_info["id"] = opts.id release = d.release(opts.id) prepared_tracks = [ track for track in release.tracklist if track.position \ or len(track.data.get('sub_tracks', [])) > 0 ] # Handle a rare case of mash-up tracks on mixed compilations # listed without durations any_duration_absent = any( len(track.duration) < 1 for track in prepared_tracks) if any_duration_absent and files_count != len(prepared_tracks): prepared_tracks = [ track for track in prepared_tracks if track.duration] fetched_release_info["artist"] = release.artists[0].name fetched_release_info["tracklist"] = [ track.title for track in prepared_tracks] fetched_release_info["year"] = release.year total_artists = len( set(track.artists[0].name for track in prepared_tracks)) multiple_track_artists = any( len(track.artists) > 1 for track in prepared_tracks) if multiple_track_artists or total_artists > 1: fetched_release_info["various"] = True if opts.catno: results = d.search(opts.catno, type='release') if not opts.catno and not opts.id: results = d.search(album, artist=artist, type='release') if results: print(f"release versions found: {results.count}") for i in range(results.count): prepared_tracks = [ track for track in results[i].tracklist if track.position \ or len(track.data.get('sub_tracks', [])) > 0 \ and not re.search('[b-zB-Z]', track.position) ] if len(prepared_tracks) == files_count: picked_id = pick_release_format_id(results[i]) first_track = prepare_track_title(prepared_tracks[0].title) last_track = prepare_track_title(prepared_tracks[-1].title) first_titles = list( set(first_track.split()) & set(sample_file_1.split())) last_titles = list( set(last_track.split()) & set(sample_file_2.split())) # ============================================================== logger.debug(f"\n >>>>>> resulted title: {results[i].title}") logger.debug("\n >>>>>> resulted catalogue number: " f"{results[i].data['catno']}") logger.debug("\n >>>>>> format name: " f"{results[i].formats[0].get('name')}") logger.debug("\n >>>>>> format descriptions: " f"{results[i].formats[0].get('descriptions')}") logger.debug(f"\n >>>>>> picked release ID: {picked_id}") logger.debug(f"\n >>>>>> first track: {first_track}") logger.debug("\n >>>>>> first track split: " f"{first_track.split()}") logger.debug(f"\n >>>>>> last track: {last_track}") logger.debug("\n >>>>>> last track split: " f"{last_track.split()}") logger.debug(f"\n >>>>>> sample file 1: {sample_file_1}") logger.debug("\n >>>>>> sample file 1 split: " f"{sample_file_1.split()}") logger.debug(f"\n >>>>>> sample file 2: {sample_file_2}") logger.debug("\n >>>>>> sample file 2 split: " f"{sample_file_2.split()}") logger.debug(f"\n >>>>>> first titles: {first_titles}") logger.debug(f"\n >>>>>> last titles: {last_titles}") # ============================================================== if len(first_titles) > 1 and len(last_titles) > 1: fetched_release_info["id"] = picked_id \ if results[i].id == picked_id else None fetched_release_info["artist"] = results[i].artists[0].name fetched_release_info["tracklist"] = [ track.title for track in prepared_tracks] fetched_release_info["year"] = results[i].year fetched_release_info["various"] = False release = d.release(fetched_release_info["id"]) # ========================================================== logger.debug("\n >>>>>>>>> release ID: " f"{fetched_release_info['id']}") # ========================================================== if fetched_release_info["artist"] == 'Various': fetched_release_info["artists"] = [ re.sub(r"\(\d+\)", '', track.artists[0].name).strip() \ for track in results[i].tracklist \ if track.position ] # ====================================================== logger.debug("\n >>>>>>>>> artists: " f"{fetched_release_info['artists']}") # ====================================================== fetched_release_info["various"] = True if fetched_release_info["id"]: break # ========================================================================== logger.debug(f"\n >>> release: {release}") logger.debug(f"\n >>> fetched release ID: {fetched_release_info['id']}") logger.debug(f"\n >>> fetched format: " f"{release.formats[0].get('descriptions')}") # ========================================================================== # Process images if release.images: for image in release.images: image_counter += 1 f = open(os.path.join(opts.folder, '{}-{:02}.jpg'.format( fetched_release_info["id"], image_counter)),'wb') f.write(requests.get(image["resource_url"]).content) f.close() main_image = os.path.join(opts.folder, '{}-01.jpg'.format(fetched_release_info["id"])) main_image_size = Image.open(main_image).size if os.path.exists( main_image) else (0, 0) folder_image = os.path.join(opts.folder, 'folder.jpg') folder_image_size = Image.open(folder_image).size if os.path.exists( folder_image) else (0, 0) cover_image = os.path.join(opts.folder, 'cover.jpg') cover_image_size = Image.open(cover_image).size if os.path.exists( cover_image) else (0, 0) image_sizes = { "main": main_image_size[0], "folder": folder_image_size[0], "cover": cover_image_size[0] } chosen_image = None for k, v in image_sizes.items(): if v in range(450, 650): if k == "main": chosen_image = main_image elif k == "folder": chosen_image = folder_image elif k == "cover": chosen_image = cover_image if chosen_image: # ================================================================== logger.debug(f"\n >>>>>> chosen image: {chosen_image}") logger.debug("\n >>>>>> chosen image size: " f"{Image.open(chosen_image).size}") # ================================================================== try: shutil.copyfile( os.path.join(chosen_image), os.path.join(folder_image)) except shutil.SameFileError: pass else: try: shutil.copyfile( os.path.join(opts.folder, '{}-01.jpg'.format(fetched_release_info["id"])), os.path.join(folder_image)) except shutil.SameFileError: pass print(f"fetched artist: {fetched_release_info['artist']}") print(f"fetched tracklist: {fetched_release_info['tracklist']}") print(f"fetched year: {fetched_release_info['year']}") release_date = release.data["released"].replace("-", ".") catalogue_number = release.data["labels"][0]["catno"].replace("/", "_") if catalogue_number == "none": catalogue_number = "" print(f"catalogue number: {catalogue_number}") # Collect release options folder_name_pattern["type"] = "" for media_format in release.formats: if media_format["qty"] > "1": if media_format["name"] in physical_media_formats: folder_name_pattern["type"] += "{}{}, ".format( media_format["qty"], media_format["name"]) if media_format["name"] == "Vinyl" and "LP" in \ media_format["descriptions"]: folder_name_pattern["type"] += f"{media_format['qty']}LP, " media_format["descriptions"].remove("LP") cleansed_descriptions = sanitize_descriptions(media_format) media_format_name = media_format["name"] if media_format["name"] not in \ physical_media_formats else "" if media_format_name: folder_name_pattern["type"] += f"{media_format_name}, " if cleansed_descriptions: folder_name_pattern["type"] += ", ".join(cleansed_descriptions) folder_name_pattern["type"] += ", " if fnmatch.filter(os.listdir(opts.folder), '*.nfo'): folder_name_pattern["type"] += "scene, " # ========================================================================== logger.debug(f"\n >>> folder name pattern: {folder_name_pattern}") # ========================================================================== release_title_raw = string.capwords(release.title.strip()).title() release_title = release_title_raw.replace("?", "_").replace(":", " -") \ .replace("/", "-") type_descriptions = (str(folder_name_pattern["type"]).lower() \ .replace("\"", "''") if "type" in folder_name_pattern.keys() else "") type_descriptions = re.sub(r'ep(?!\w+)', 'EP', type_descriptions) type_descriptions = re.sub(r'lp(?!\w+)', 'LP', type_descriptions) type_descriptions = re.sub(r'cd(?!\w+)', 'CD', type_descriptions) type_descriptions_for_tags = [i.strip() \ for i in type_descriptions.split(',') if i] descriptions_for_tags_found = [i for i in descriptions_for_tags \ if i in type_descriptions_for_tags] if fetched_release_info["artist"] == 'Various': type_descriptions = re.sub('compilation', '', type_descriptions) # If there's a stray comma in the descriptions, remove it type_descriptions = re.sub(r'\s,', '', type_descriptions) album_title_for_tags = "V/A: {title} [{type}]".format( title=release.title.strip(), type=type_descriptions.strip(', ')) \ if descriptions_for_tags_found else f"V/A: {release.title.strip()}" else: album_title_for_tags = "{title} [{type}]".format( title=release.title.strip(), type=", ".join(descriptions_for_tags_found) ) if descriptions_for_tags_found else release.title.strip() # ========================================================================== logger.debug(f"\n >>> release title: {release_title}") logger.debug(f"\n >>> album title for tags: {album_title_for_tags}") logger.debug(f"\n >>> type descriptions: {type_descriptions}") # ========================================================================== # Process audio files for audio_file in audio_files: is_writeable = os.access(os.path.join(opts.folder, audio_file), os.W_OK) if not is_writeable: os.chmod(os.path.join(opts.folder, audio_file), stat.S_IWRITE) file_extension = os.path.splitext(audio_file)[-1].lower()[1:] track_title, track_artist, track_position, multiple_discs = prepare_tags( prepared_tracks, file_counter, fetched_release_info) track_position_for_tags = track_position.split('-')[1] \ if multiple_discs else track_position if not track_position_for_tags.isdigit(): track_position_for_tags = str(file_counter+1) disc_number = track_position.split('-')[0] if multiple_discs else "" if disc_number: album_title_for_tags = re.sub( r'\d?CD\d?', f'CD{disc_number}', album_title_for_tags) albumart = os.path.join(opts.folder, 'folder.jpg') # ================================================================== logger.debug(f"\n >>>>>> audio file: {audio_file}") logger.debug(f"\n >>>>>> file extension: {file_extension}") logger.debug(f"\n >>>>>> tag track: {track_title}") logger.debug(f"\n >>>>>> tag artist: {track_artist}") logger.debug(f"\n >>>>>> track position: {track_position}") logger.debug(f"\n >>>>>> disc number: {disc_number}") logger.debug(f"\n >>>>>> is writeable: {is_writeable}") logger.debug(f"\n >>>>>> album art: {albumart}") # ================================================================== if file_extension == "mp3": audio = MP3(os.path.join(opts.folder, audio_file)) audio.tags['TIT2'] = TIT2(encoding=3, text=track_title) audio.tags['TPE1'] = TPE1(encoding=3, text=track_artist) audio.tags['TALB'] = TALB(encoding=3, text=album_title_for_tags) audio.tags['TDRC'] = TDRC(encoding=3, text=str(fetched_release_info["year"])) audio.tags['TRCK'] = TRCK(encoding=3, text=track_position_for_tags) audio.tags.update() # Get bitrate information fetched_release_info["bitrate_mode"] = str(audio.info.bitrate_mode) bitrates.append(audio.info.bitrate) total_duration += audio.info.length # ================================================================== logger.debug("\n >>>>>>>>> bitrate mode: " f"{fetched_release_info['bitrate_mode']}") logger.debug(f"\n >>>>>>>>> bitrates: {bitrates}") # ================================================================== # Embed the artwork if os.path.isfile(albumart): # ============================================================== logger.debug(f"\n >>>>>>>>>>>> album art in mp3: {albumart}") # ============================================================== image = Picture() mime = 'image/jpeg' with open(albumart, 'rb') as f: image.data = f.read() audio.tags['APIC:'] = APIC(encoding=3, mime=mime, type=3, desc=u'front cover', data=image.data) audio.save() elif file_extension == "flac": audio = FLAC(os.path.join(opts.folder, audio_file)) audio["title"] = track_title audio["artist"] = track_artist audio["album"] = album_title_for_tags # Get bitrate information file_bitrate = (audio.info.bits_per_sample \ * audio.info.total_samples) / audio.info.length bitrates.append(file_bitrate) fetched_release_info["bitrate_mode"] = "BitrateMode.VBR" total_duration += audio.info.length # ================================================================== logger.debug(f"\n >>>>>>>>> bitrates: {bitrates}") logger.debug(f"\n >>>>>>>>> embedded pictures: {audio.pictures}") # ================================================================== if not audio.pictures: # ============================================================== logger.debug(f"\n >>>>>>>>>>>> album art in flac: {albumart}") # ============================================================== if os.path.isfile(albumart): image = Picture() with open(albumart, 'rb') as f: image.data = f.read() image.mime = 'image/jpeg' image.type = PictureType.COVER_FRONT image.width = 500 image.height = 500 audio.add_picture(image) audio.save() # ================================================================== logger.debug( f"\n >>>>>>>>> embedded pictures after save: {audio.pictures}") # ================================================================== elif file_extension == "m4a": audio = MP4(os.path.join(opts.folder, audio_file)) audio.tags['\xa9nam'] = [track_title] audio.tags['\xa9ART'] = [track_artist] audio.tags['aART'] = [track_artist] audio.tags['\xa9alb'] = [album_title_for_tags] audio.tags.update() audio.save() bitrates.append(audio.info.bitrate) # ================================================================== logger.debug(f"\n >>>>>>>>> bitrates: {bitrates}") # ================================================================== fetched_release_info["bitrate_mode"] = "BitrateMode.CBR" total_duration += audio.info.length elif file_extension == "wav": audio = WAVE(os.path.join(opts.folder, audio_file)) # Create ID3 tag if not present if not audio.tags: audio.add_tags() audio.tags['TIT2'] = TIT2(encoding=3, text=track_title) audio.tags['TPE1'] = TPE1(encoding=3, text=track_artist) audio.tags['TALB'] = TALB(encoding=3, text=album_title_for_tags) audio.tags['TDRC'] = TDRC(encoding=3, text=str(fetched_release_info["year"])) audio.tags['TRCK'] = TRCK(encoding=3, text=track_position_for_tags) if 'APIC:' not in audio.tags.keys(): # ============================================================== logger.debug(f"\n >>>>>>>>> album art in wav: {albumart}") # ============================================================== if os.path.isfile(albumart): image = Picture() with open(albumart, 'rb') as f: image.data = f.read() # ========================================================== logger.debug( f"\n >>>>>>>>>>>> image mime in wav: {image.mime}") # ========================================================== mime = 'image/jpeg' audio.tags['APIC:'] = APIC(encoding=3, mime=mime, type=3, desc=u'front cover', data=image.data) audio.tags.update() audio.save() bitrates.append(1411200) # ================================================================== logger.debug(f"\n >>>>>>>>> bitrates: {bitrates}") # ================================================================== fetched_release_info["bitrate_mode"] = "BitrateMode.CBR" total_duration += audio.info.length fetched_release_info["bitrate_kbps"] = int(audio.info.bitrate / 1000) fetched_release_info["sample_rate"] = audio.info.sample_rate fetched_release_info["bits_per_sample"] = audio.info.bits_per_sample \ if hasattr(audio.info, 'bits_per_sample') else "no data" fetched_release_info["channels"] = audio.info.channels rename_files( opts, audio_file, file_counter, fetched_release_info, multiple_discs, track_artist, track_position, track_title, file_extension ) file_counter += 1 # ================================================================== logger.debug(f"\n >>>>>> total duration: {total_duration}") # ================================================================== print(f"tracks processed: {file_counter}") average_bitrate = int(sum(bitrates) / len(bitrates)) print(f"average bitrate (bps): {average_bitrate}") calculated_duration_from_audio = calculate_durations(total_duration) # Choose a bitrate mode descriptor if fetched_release_info["bitrate_mode"] in [ "BitrateMode.CBR", "BitrateMode.UNKNOWN"]: if average_bitrate in range(319700, 320200): folder_name_pattern["media"] = "320" elif average_bitrate in range(256000, 256200): folder_name_pattern["media"] = "256" elif average_bitrate in range(224000, 224200): folder_name_pattern["media"] = "224" elif average_bitrate in range(192000, 192200): folder_name_pattern["media"] = "192" elif average_bitrate in range(160000, 160200): folder_name_pattern["media"] = "160" elif average_bitrate in range(128000, 128200): folder_name_pattern["media"] = "128" elif average_bitrate in range(1300000, 1500000): folder_name_pattern["media"] = "WAV" else: folder_name_pattern["media"] = "_".join( str(i)[:3] for i in set(bitrates)) elif fetched_release_info["bitrate_mode"] == "BitrateMode.VBR": if average_bitrate in range(700000, 1200000): folder_name_pattern["media"] = "FLAC" else: folder_name_pattern["media"] = "VBR" elif fetched_release_info["bitrate_mode"] == "BitrateMode.ABR": folder_name_pattern["media"] = "ABR" # Apply the new folder name pattern new_folder_name = "{year} {title} [{type}{catno}] @{media}".format( year=release_date, title=strip_accents(release_title), type=type_descriptions if catalogue_number \ else type_descriptions.strip(', '), catno=str(catalogue_number).upper(), media=folder_name_pattern["media"] ) os.rename(opts.folder, new_folder_name) calculated_duration = calculate_durations(0, release=release) # Print release details print(f"processed release title: {new_folder_name}\n") for track in prepared_tracks: print(f"{track.position} {track.title} {track.duration}") print("============ total duration (h:m:s): ", f"{calculated_duration[0]:02d}:{calculated_duration[1]:02d}" f":{calculated_duration[2]:02d}") print("==== total duration [audio] (h:m:s): ", f"{calculated_duration_from_audio[0]:02d}:" f"{calculated_duration_from_audio[1]:02d}:" f"{calculated_duration_from_audio[2]:02d}") print("================== folder size (Mb): ", "{:.2f}".format( float(get_folder_size(new_folder_name)) / 1000000.0).replace(".", ",")) print("\n================== sample rate (Hz): ", fetched_release_info["sample_rate"] \ if "sample_rate" in fetched_release_info.keys() else "no data") print("================== bit depth (bits): ", fetched_release_info["bits_per_sample"] \ if "bits_per_sample" in fetched_release_info.keys() else "no data") print("==================== bitrate (kbps): ", fetched_release_info["bitrate_kbps"] \ if "bitrate_kbps" in fetched_release_info.keys() else "no data") print("========================== channels: ", fetched_release_info["channels"] \ if "channels" in fetched_release_info.keys() else "no data")
def audio_length(aud_file): audio = WAVE(aud_file) length = int(audio.info.length) print(length)
class MusicPlayer(ThemedTk): def __init__(self, *args, **kwargs): #pre-variable initialization self.versionname = 'Pytone v1.5b' #initialization super(MusicPlayer, self).__init__(theme='equilux') pygame.init() mixer.init() MUSIC_END = pygame.USEREVENT + 1 pygame.mixer.music.set_endevent(MUSIC_END) self.automusicslider = threading.Thread(target=self.musicsliderplace) self.musicloop = threading.Thread(target=self.loopsong) #window layout initialization self.resizable(False, False) self.title(self.versionname) #1.3 release self.configure(background='grey22') self.geometry('1000x600') self.iconbitmap('icon.ico') self.protocol("WM_DELETE_WINDOW", self.ask_quit) self.style = ttk.Style() self.style.configure('TButton', background='grey22') self.style.configure('TScale', background='grey22') #icon initialization self.play_icon = PhotoImage(file='assets/play.png') self.pause_icon = PhotoImage(file='assets/pause.png') self.volume_min_icon = PhotoImage(file='assets/volume-min.png') self.volume_medium_icon = PhotoImage(file='assets/volume-medium.png') self.volume_max_icon = PhotoImage(file='assets/volume-max.png') self.volume_mute_icon = PhotoImage(file='assets/volume-mute.png') self.repeat_icon = PhotoImage(file='assets/repeat.png') self.shuffle_icon = PhotoImage(file='assets/shuffle.png') self.skip_back_icon = PhotoImage(file='assets/skip-back.png') self.skip_forward_icon = PhotoImage(file='assets/skip-forward.png') self.play_icon_active = PhotoImage(file='assets/play_active.png') self.pause_icon_active = PhotoImage(file='assets/pause_active.png') self.volume_min_icon_active = PhotoImage( file='assets/volume-min_active.png') self.volume_medium_icon_active = PhotoImage( file='assets/volume-medium_active.png') self.volume_max_icon_active = PhotoImage( file='assets/volume-max_active.png') self.volume_mute_icon_active = PhotoImage( file='assets/volume-mute_active.png') self.repeat_icon_active = PhotoImage(file='assets/repeat_active.png') self.shuffle_icon_active = PhotoImage(file='assets/shuffle_active.png') self.skip_back_icon_active = PhotoImage( file='assets/skip-back_active.png') self.skip_forward_icon_active = PhotoImage( file='assets/skip-forward_active.png') self.browse_file_icon = PhotoImage(file='assets/browse-file.png') self.browse_file_icon_active = PhotoImage( file='assets/browse-file_active.png') self.explorer_icon = PhotoImage(file='assets/explorer.png') self.explorer_icon_active = PhotoImage( file='assets/explorer_active.png') self.music_icon = PhotoImage(file='assets/music.png') self.music_icon_active = PhotoImage(file='assets/music_active.png') self.mute_icon = PhotoImage(file='assets/mute.png') self.mute_icon_active = PhotoImage(file='assets/mute_active.png') self.disc_icon = PhotoImage(file='assets/disc.png') self.disc_icon_active = PhotoImage(file='assets/disc_active.png') #variable initialization self.songstatus = StringVar() self.v = DoubleVar() self.currentsong = None self.pauseonly = False self.songlength = 1 #post initialization self._widget() self._config() self._layout() def _widget(self): #widget setup self.play_pause_button = Button(self, image=self.play_icon, command=self.play_pause, takefocus=False, relief=FLAT, bg='grey22', activebackground='grey22') self.VolumeSlider = ttk.Scale(self, variable=self.v, from_=0, to=100, orient=HORIZONTAL, command=self.setvolume) self.music_player_scale = ttk.Scale(self, orient=HORIZONTAL, command=self.musicsliderset) self.volume_button = Button(self, image=self.volume_max_icon, relief=FLAT, bg='grey22', activebackground='grey22', command=self.togglemute) self.progress_label_1 = Label(self, text='00:00', bg='grey22', fg='white') self.progress_label_2 = Label(self, text='00:00', bg='grey22', fg='white') self.repeat_button = Button(self, image=self.repeat_icon, bg='grey22', relief=FLAT, activebackground='grey30', command=self.loopshuffletoggle) self.shuffle_button = Button(self, image=self.shuffle_icon, bg='grey22', relief=FLAT, activebackground='grey30', command=self.loopshuffletoggle) self.last_song_button = Button(self, image=self.skip_back_icon, bg='grey22', relief=FLAT, activebackground='grey22', command=self.previous_song) self.next_song_button = Button(self, image=self.skip_forward_icon, bg='grey22', relief=FLAT, activebackground='grey22', command=self.next_song) self.playlist = Listbox(self, relief=FLAT, selectmode=SINGLE, bg="grey20", fg="grey88", font=('Arial', 13), width=82, height=15, selectbackground="grey40", activestyle='none') self.browse_button = Button(self, bg='grey30', fg='grey92', activebackground='grey70', image=self.browse_file_icon, command=self.selectpath, relief=FLAT) self.pathname = Label(self, bg='grey22', fg='white', font=('arial', 10)) self.pathtoggle = Button(self, image=self.explorer_icon, bg='grey22', relief=FLAT, width=500, height=50, command=self.toggleplaylist) self.nowmusictoggle = Button(self, image=self.music_icon, bg='grey30', relief=FLAT, width=500, height=50, command=self.toggleplaylist) self.currentvolume = Label(self, bg='grey22', fg='grey88', relief=FLAT, text='100') self.songname = Label(self, bg='grey22', fg='grey88', relief=FLAT, text='', font=('Arial', 30, 'bold')) self.artistname = Label(self, bg='grey22', fg='grey88', relief=FLAT, text='', font=('Arial', 13)) self.albumname = Label(self, bg='grey22', fg='grey88', relief=FLAT, text='', font=('Arial', 13)) self.discicon = Button(image=self.disc_icon, bg='grey30', relief=FLAT, command=self.songdetail) #widget binding self.playlist.bind('<Button-1>', self.playlistclick) self.playlist.bind('<Double-Button-1>', self.playlistdoubleclick) #24/7 threading self.automusicslider.daemon = True self.musicloop.daemon = True self.automusicslider.start() self.musicloop.start() def _layout(self): #widget placement self.songname.place(relx=0.25, rely=0.47) self.artistname.place(relx=0.25, rely=0.59) self.albumname.place(relx=0.25, rely=0.67) self.play_pause_button.place(relx=0.5, rely=0.85, anchor=CENTER) self.repeat_button.place(relx=0.4, rely=0.85, anchor=CENTER) #self.shuffle_button.place(relx=0.6, rely=0.85, anchor=CENTER) self.music_player_scale.place(relx=0.5, rely=0.95, width=500, anchor=CENTER) self.progress_label_1.place(relx=0.20, rely=0.93) self.progress_label_2.place(relx=0.75, rely=0.93) self.last_song_button.place(relx=0.45, rely=0.85, anchor=CENTER) self.next_song_button.place(relx=0.55, rely=0.85, anchor=CENTER) self.volume_button.place(relx=0.81, rely=0.845) self.VolumeSlider.place(relx=0.85, rely=0.85) self.pathtoggle.place(relx=0.0, rely=0.0) self.nowmusictoggle.place(relx=0.5, rely=0.0) self.currentvolume.place(relx=0.95, rely=0.85) self.discicon.place(relx=0.04, rely=0.44) def playlistclick(self, event): self.loadsong() def playlistdoubleclick(self, event): self.loadsong() self.toggleplaylist() self.play_music() def check_event(self): pass def _config(self): #variable setup self.VolumeSlider.set(100) self.songstatus.set("choosing") #key binding self.bind('<Button-1>', self._flat_button) self.bind('<Enter>', self._button_hover) self.bind('<Leave>', self._button_leave) self.bind('<space>', self.play_pause) def toggleplaylist(self): #toggle playlist and its accessories here if self.playlist.winfo_ismapped() == True: self.playlist.place_forget() self.pathname.place_forget() self.browse_button.place_forget() self.pathtoggle.config(bg='grey22') self.nowmusictoggle.config(bg='grey30') else: self.playlist.place(relx=0.01, rely=0.15) self.playlist.tkraise() self.pathname.place(relx=0.01, rely=0.10) self.browse_button.place(relx=0.96, rely=0.086) self.pathtoggle.config(bg='grey30') self.nowmusictoggle.config(bg='grey22') def setmusiclength(self): #important function on a player (also hard to do) if self.currentsong.endswith('.mp3') == True: self.song = MP3(self.currentsong) self.songinfo = ID3(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songmins = str(self.songmins).zfill(2) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs)) try: self.songname.config(text=self.songinfo['TIT2'].text[0]) self.artistname.config(text=self.songinfo['TPE1'].text[0]) self.albumname.config(text=self.songinfo['TALB'].text[0]) except: self.songname.config(text=self.currentsong) self.artistname.config(text='failed to read metadata') self.albumname.config(text='failed to read metadata') if self.currentsong.endswith('.flac') == True: self.song = FLAC(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songmins = str(self.songmins).zfill(2) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs)) self.music_player_scale.config(from_=0, to=self.songlength) try: self.songname.config(text=self.song['TITLE']) self.artistname.config(text=self.song['ARTIST']) self.albumname.config(text=self.song['ALBUM']) except: self.songname.config(text=self.currentsong) self.artistname.config(text='failed to read metadata') self.albumname.config(text='failed to read metadata') if self.currentsong.endswith('.ogg') == True: self.song = WAVE(self.currentsong) self.songlength = self.song.info.length self.songround = round(self.songlength) self.songmins, self.songsecs = divmod(self.songround, 60) self.songsecs = str(self.songsecs).zfill(2) self.progress_label_2.config(text=str(self.songmins) + ':' + str(self.songsecs)) def musicsliderset(self, *args): #Also important as user need to choose where to play #self.userlength = self.music_player_scale.get() #print(self.userlength) #mixer.music.set_pos(self.userlength) pass def musicsliderplace(self): for i in range(999999999): self.currenttime = mixer.music.get_pos() self.currenttime, self.currenttimemil = divmod( self.currenttime, 1000) self.currentmin, self.currentsec = divmod(self.currenttime, 60) self.currentmin = str(self.currentmin).zfill(2) self.currentsec = str(self.currentsec).zfill(2) self.progress_label_1.config(text=str(self.currentmin) + ':' + str(self.currentsec)) if self.progress_label_1['text'] == '-1:59': self.progress_label_1.config(text='00:00') self.currentsongpos = int(self.currenttime) / int(self.songlength) self.music_player_scale.set(self.currentsongpos) time.sleep(1) def _button_hover(self, event): try: if type(event.widget) == Button: exec('event.widget.config(image=self.' + re.search( r'assets/(.*?)\.png', root.call(event.widget.cget('image'), 'cget', '-file')).group(1).replace('-', '_') + '_icon_active)') except AttributeError: pass #button hover out animation def _button_leave(self, event): if type(event.widget) == Button: exec('event.widget.config(image=self.' + re.search( r'assets/(.*?)\.png', root.call(event.widget.cget('image'), 'cget', '-file')).group( 1).replace('-', '_').replace('_active', '') + '_icon)') #relief locking def _flat_button(self, event): if type(event.widget) == Button: event.widget.config(relief=FLAT) #music play and pause area def loadsong(self): self.currentsong = self.playlist.get(ACTIVE) #loading bay try: mixer.music.load(self.currentsong) self.play_pause_button.config(image=self.pause_icon_active) self.setmusiclength() except pygame.error: mixer.music.unload() messagebox.showerror(title="ERROR", message="Invalid Music Format!") def play_music(self, *args): mixer.music.play() self.title(self.versionname + ' - Playing ' + self.currentsong) self.check_event() def loopshuffletoggle(self): if self.repeat_button.cget('bg') == 'grey50': self.repeat_button.config(bg='grey22') else: self.repeat_button.config(bg='grey50') def loopsong(self): for i in range(99999999): if pygame.mixer.music.get_busy( ) == False and self.repeat_button.cget('bg') == 'grey50': pygame.mixer.music.play() else: pass time.sleep(1) def play_pause(self): if self.play_pause_button['image'] == str(self.pause_icon_active): mixer.music.pause() self.title(self.versionname + ' - Paused ') self.play_pause_button.config(image=self.play_icon_active) else: mixer.music.unpause() self.title(self.versionname + ' - Playing ' + self.currentsong) self.play_pause_button.config(image=self.pause_icon_active) def next_song(self): selection_indices = self.playlist.curselection() # default next selection is the beginning next_selection = 0 # make sure at least one item is selected if len(selection_indices) > 0: # Get the last selection, remember they are strings for some reason # so convert to int last_selection = int(selection_indices[-1]) # clear current selections self.playlist.selection_clear(selection_indices) # Make sure we're not at the last item if last_selection < self.playlist.size() - 1: next_selection = last_selection + 1 self.playlist.activate(next_selection) self.playlist.selection_set(next_selection) self.play_pause_button.config(image=self.pause_icon_active) self.loadsong() self.play_music() def previous_song(self): selection_indicesb = self.playlist.curselection() # default next selection is the beginning next_selectionb = 0 # make sure at least one item is selected if len(selection_indicesb) > 0: # Get the last selection, remember they are strings for some reason # so convert to int last_selectionb = int(selection_indicesb[-1]) # clear current selections self.playlist.selection_clear(selection_indicesb) # Make sure we're not at the last item if last_selectionb < self.playlist.size() - 1: next_selectionb = last_selectionb - 1 self.playlist.activate(next_selectionb) self.playlist.selection_set(next_selectionb) self.play_pause_button.config(image=self.pause_icon_active) self.loadsong() self.play_music() #volume control def setvolume(self, event): self.volume = self.VolumeSlider.get() self.volumed = self.volume / 100 + 0.00 mixer.music.set_volume(self.volumed) #also write your code here self.currentvolume.config(text=int(self.volume)) if self.volume <= 100: self.volume_button.config(image=self.volume_max_icon) if self.volume <= 70: self.volume_button.config(image=self.volume_medium_icon) if self.volume <= 40: self.volume_button.config(image=self.volume_min_icon) if self.volume == 0: self.volume_button.config(image=self.mute_icon) def togglemute(self): if self.VolumeSlider.get() != 0: #mute self.VolumeSlider.set(0) else: #unmute self.VolumeSlider.set(100) def songdetail(self): detailwindow = Toplevel() detailwindow.geometry('800x500') detailwindow.config(bg='grey22') detailwindow.attributes('-alpha', 0.9) detailwindow.title('Metadata') try: self.detailbox = Label(detailwindow, bg='grey22', fg='white', text=self.song.pprint()) self.detailbox.pack(side=TOP) except: messagebox.showerror(title='Error', message='Failed to read metadata') def selectpath(self): path = filedialog.askdirectory() self.playlist.delete(0, 'end') try: os.chdir(path) songs = os.listdir() filteredsongs = filter(lambda x: x.endswith(('.mp3', '.flac')), songs) self.pathname.config(text='Selected path: ' + path) for s in filteredsongs: self.playlist.insert(END, s) except OSError: self.pathname.config(text='Please choose a path...') def ask_quit(self): if mixer.music.get_busy() == False: root.destroy() elif askokcancel("Exit", "Stop Music?"): mixer.music.stop() root.destroy()
def initiateWAVE(filename, directory, thumbnails, options): audio = WAVE(str(directory) + "/" + str(filename)) # verify artist information is present before preceeding if ' - ' not in filename and str(audio['TCON']) == '': messagebox.showinfo("No artist information found, aborting procedure") return False, False, False # transcribe formal tagnames into informal counterpart formalTagDict = { 'TPE1': 'Artist', 'TALB': 'Album', 'TPE2': 'Album Artist', 'TBPM': 'BPM', 'COMM::eng': 'Comment', 'TCMP': 'Compilation', 'TCOP': 'Copyright', 'TPOS': 'Discnumber', 'TCON': 'Genre', 'APIC:': 'Image', 'TKEY': 'Key', 'TDRC': 'Release_Date', 'TIT2': 'Title', 'TXXX:replaygain_track_gain': 'ReplayGain', } # transcribe informal tagnames into formal counterpart informalTagDict = {v: k for k, v in formalTagDict.items()} ID3Frames = { 'TPE1': TPE1, 'TALB': TALB, 'TPE2': TPE2, 'TBPM': TBPM, 'COMM': COMM, 'TCMP': TCMP, 'TCOP': TCOP, 'TPOS': TPOS, 'TCON': TCON, 'APIC:': APIC, 'TKEY': TKEY, 'TDRC': TDRC, 'TIT2': TIT2, 'TXXX': TXXX, } fileParameters = [] tagList = list(audio.keys()) for tag in tagList: # delete extraneous tags if the tag is not in the list of selected tags and the delete unselected tags option is activated if (tag not in formalTagDict or formalTagDict[tag] not in options["Selected Tags (L)"] ) and options["Delete Unselected Tags (B)"].get() == True: audio.pop(tag) audio.save() else: fileParameters.append(tag) for tag in options["Selected Tags (L)"]: if tag in informalTagDict: tag = informalTagDict[tag] # add tags of interest if missing if tag not in fileParameters: try: if "COMM" in tag: audio[tag] = COMM(encoding=3, lang="eng", text="") elif "TXXX" in tag: audio[tag] = TXXX(encoding=3, desc="replaygain_track_gain", text="") else: audio[tag] = ID3Frames[tag](encoding=3, text="") audio.save() except: messagebox.showinfo( "Permission Error", "Unable to save tags, file may be open somewhere") return False, False, False # check for discrepancies between tags and filename # check both artist and title tags if ' - ' in filename: artist = filename.split(' - ')[0] title = filename[filename.index(filename.split(' - ')[1]):filename. rfind('.')] if artist != str(audio["TPE1"]) or title != str(audio["TIT2"]): # save artist and title to tag if both are empty if str(audio["TPE1"]) == '' and str(audio["TIT2"]) == '': audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() else: audio, filename = compareArtistAndTitle( audio, artist, title, filename, directory, options) # only check title tag else: title = filename[:filename.rfind('.')] if title != str(audio["TIT2"]): # save title to tag if tag is empty if str(audio["TIT2"]) == '': audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() else: audio, filename = compareTitle(audio, title, filename, directory, options) # handle naming format and typo check if options["Audio naming format (S)"].get() == "Artist - Title" or options[ 'Audio naming format (S)'].get() == 'Title': namingConvention = options['Audio naming format (S)'].get() artist = str(audio["TPE1"]) audio, filename = handleStaticNamingConvention(audio, filename, artist, title, directory, namingConvention) if options["Scan Filename and Tags (B)"].get( ) == True and type(audio) != bool: audio, filename, options = extractArtistAndTitle( audio, filename, directory, options, namingConvention) if type(audio) != bool: # save thumbnail to list image = audio["APIC:"] if image.data != b'': stream = BytesIO(image.data) image = Image.open(stream).convert("RGBA") thumbnails = saveThumbnail(image, thumbnails) stream.close() else: thumbnails = saveThumbnail("NA", thumbnails) return audio, filename, informalTagDict, thumbnails, options
def _get_length(self, wav_file): return int(WAVE(wav_file).info.length)
class TWave(TestCase): def setUp(self): fn_wav_pcm_2s_16000_08_id3v23 = \ os.path.join(DATA_DIR, "silence-2s-PCM-16000-08-ID3v23.wav") self.wav_pcm_2s_16000_08_ID3v23 = \ WAVE(fn_wav_pcm_2s_16000_08_id3v23) self.tmp_fn_pcm_2s_16000_08_ID3v23 = \ get_temp_copy(fn_wav_pcm_2s_16000_08_id3v23) self.tmp_wav_pcm_2s_16000_08_ID3v23 = \ WAVE(self.tmp_fn_pcm_2s_16000_08_ID3v23) self.fn_wav_pcm_2s_16000_08_notags = \ os.path.join(DATA_DIR, "silence-2s-PCM-16000-08-notags.wav") self.wav_pcm_2s_16000_08_notags = \ WAVE(self.fn_wav_pcm_2s_16000_08_notags) self.tmp_fn_pcm_2s_16000_08_notag = \ get_temp_copy(self.fn_wav_pcm_2s_16000_08_notags) self.tmp_wav_pcm_2s_16000_08_notag = \ WAVE(self.tmp_fn_pcm_2s_16000_08_notag) fn_wav_pcm_2s_44100_16_id3v23 = \ os.path.join(DATA_DIR, "silence-2s-PCM-44100-16-ID3v23.wav") self.wav_pcm_2s_44100_16_ID3v23 = WAVE(fn_wav_pcm_2s_44100_16_id3v23) def test_channels(self): self.failUnlessEqual(self.wav_pcm_2s_16000_08_ID3v23.info.channels, 2) self.failUnlessEqual(self.wav_pcm_2s_44100_16_ID3v23.info.channels, 2) def test_sample_rate(self): self.failUnlessEqual(self.wav_pcm_2s_16000_08_ID3v23.info.sample_rate, 16000) self.failUnlessEqual(self.wav_pcm_2s_44100_16_ID3v23.info.sample_rate, 44100) def test_number_of_samples(self): self.failUnlessEqual( self.wav_pcm_2s_16000_08_ID3v23.info._number_of_samples, 32000) self.failUnlessEqual( self.wav_pcm_2s_44100_16_ID3v23.info._number_of_samples, 88200) def test_bits_per_sample(self): self.failUnlessEqual( self.wav_pcm_2s_16000_08_ID3v23.info.bits_per_sample, 8) self.failUnlessEqual( self.wav_pcm_2s_44100_16_ID3v23.info.bits_per_sample, 16) def test_bitrate(self): self.failUnlessEqual(self.wav_pcm_2s_16000_08_ID3v23.info.bitrate, 64000) self.failUnlessEqual(self.wav_pcm_2s_44100_16_ID3v23.info.bitrate, 352800) def test_length(self): self.failUnlessAlmostEqual(self.wav_pcm_2s_16000_08_ID3v23.info.length, 2.0, 2) self.failUnlessAlmostEqual(self.wav_pcm_2s_44100_16_ID3v23.info.length, 2.0, 2) def test_not_my_file(self): self.failUnlessRaises(InvalidChunk, WAVE, os.path.join(DATA_DIR, "empty.ogg")) def test_pprint(self): self.wav_pcm_2s_44100_16_ID3v23.pprint() def test_mime(self): self.failUnless("audio/wav" in self.wav_pcm_2s_44100_16_ID3v23.mime) self.failUnless("audio/wave" in self.wav_pcm_2s_44100_16_ID3v23.mime) def test_id3_tags(self): id3 = self.wav_pcm_2s_44100_16_ID3v23.tags self.assertEquals(id3["TALB"], "Quod Libet Test Data") self.assertEquals(id3["TCON"], "Silence") self.assertEquals(id3["TIT2"], "Silence") self.assertEquals(id3["TPE1"], ["piman / jzig"]) def test_id3_tags_uppercase_chunk(self): id3 = self.wav_pcm_2s_16000_08_ID3v23 self.assertEquals(id3["TALB"], "Quod Libet Test Data") self.assertEquals(id3["TCON"], "Silence") self.assertEquals(id3["TIT2"], "Silence") self.assertEquals(id3["TPE1"], ["piman / jzig"]) def test_delete(self): self.tmp_wav_pcm_2s_16000_08_ID3v23.delete() self.failIf(self.tmp_wav_pcm_2s_16000_08_ID3v23.tags) self.failUnless(WAVE(self.tmp_fn_pcm_2s_16000_08_ID3v23).tags is None) def test_save_no_tags(self): self.tmp_wav_pcm_2s_16000_08_ID3v23.tags = None self.tmp_wav_pcm_2s_16000_08_ID3v23.save() self.assertTrue(self.tmp_wav_pcm_2s_16000_08_ID3v23.tags is None) def test_add_tags_already_there(self): self.failUnless(self.tmp_wav_pcm_2s_16000_08_ID3v23.tags) self.failUnlessRaises(Exception, self.tmp_wav_pcm_2s_16000_08_ID3v23.add_tags) def test_roundtrip(self): self.failUnlessEqual(self.tmp_wav_pcm_2s_16000_08_ID3v23["TIT2"], ["Silence"]) self.tmp_wav_pcm_2s_16000_08_ID3v23.save() new = WAVE(self.tmp_wav_pcm_2s_16000_08_ID3v23.filename) self.failUnlessEqual(new["TIT2"], ["Silence"]) def test_save_tags(self): from mutagen.id3 import TIT1 tags = self.tmp_wav_pcm_2s_16000_08_ID3v23.tags tags.add(TIT1(encoding=3, text="foobar")) tags.save() new = WAVE(self.tmp_wav_pcm_2s_16000_08_ID3v23.filename) self.failUnlessEqual(new["TIT1"], ["foobar"]) """" Simulate the way Picard writes and update tags """ def test_picard_lifecycle(self): path_tmp_wav_file = \ get_temp_copy(self.fn_wav_pcm_2s_16000_08_notags) from mutagen.id3 import ID3 wav = WAVE(path_tmp_wav_file) id3 = wav.tags """" Picard WaveFile._get_tags: """ self.assertIsNone(id3, "Ensure ID3-tag-header does not exist") """" Picard WaveFile._get_tags: initialize tags """ wav.add_tags() id3 = wav.tags self.assertIsInstance(id3, ID3) """ ID3v2.3 separator """ separator = '/' """ Initialize Picard like metadata tags """ self.__init_id3_tags(id3, major=3) """ Write the Picard like metadata to the empty WAVE-file """ id3.save(path_tmp_wav_file, v23_sep=separator) """ Tags (metadata) have been added; now load the file again """ wav = WAVE(path_tmp_wav_file) id3 = wav.tags self.assertIsInstance(id3, ID3) self.assertEquals(id3["TRCK"], "1/10") self.assertEquals(id3["TPOS"], "1/1") self.assertEquals(id3["TXXX:MusicBrainz Release Group Id"], "e00305af-1c72-469b-9a7c-6dc665ca9adc") self.assertEquals(id3["TXXX:MusicBrainz Album Artist Id"], [ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ]) self.assertEquals(id3["TXXX:CATALOGNUMBER"], ["PRAR931391"]) self.assertEquals(id3["TSRC"], ["NLB931100460", "USMH51100098"]) @staticmethod def __init_id3_tags(id3, major=3): """ Attributes: id3 ID3 Tag object major ID3 major version, e.g.: 3 for ID3v2.3 """ from mutagen.id3 import TRCK, TPOS, TXXX, TPUB, TALB, UFID, TPE2, \ TSO2, TMED, TIT2, TPE1, TSRC, IPLS, TORY, TDAT, TYER id3.add(TRCK(encoding=major, text="1/10")) id3.add(TPOS(encoding=major, text="1/1")) id3.add( TXXX(encoding=major, desc="MusicBrainz Release Group Id", text="e00305af-1c72-469b-9a7c-6dc665ca9adc")) id3.add(TXXX(encoding=major, desc="originalyear", text="2011")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Type", text="album")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Id", text="e7050302-74e6-42e4-aba0-09efd5d431d8")) id3.add(TPUB(encoding=major, text="J&R Adventures")) id3.add(TXXX(encoding=major, desc="CATALOGNUMBER", text="PRAR931391")) id3.add(TALB(encoding=major, text="Don\'t Explain")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Status", text="official")) id3.add(TXXX(encoding=major, desc="SCRIPT", text="Latn")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Release Country", text="US")) id3.add(TXXX(encoding=major, desc="BARCODE", text="804879313915")) id3.add( TXXX(encoding=major, desc="MusicBrainz Album Artist Id", text=[ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ])) id3.add(TPE2(encoding=major, text="Beth Hart & Joe Bonamassa")) id3.add(TSO2(encoding=major, text="Hart, Beth & Bonamassa, Joe")) id3.add(TXXX(encoding=major, desc="ASIN", text="B005NPEUB2")) id3.add(TMED(encoding=major, text="CD")) id3.add( UFID(encoding=major, owner="http://musicbrainz.org", data=b"f151cb94-c909-46a8-ad99-fb77391abfb8")) id3.add(TIT2(encoding=major, text="Sinner's Prayer")) id3.add( TXXX(encoding=major, desc="MusicBrainz Artist Id", text=[ "3fe817fc-966e-4ece-b00a-76be43e7e73c", "984f8239-8fe1-4683-9c54-10ffb14439e9" ])) id3.add(TPE1(encoding=major, text=["Beth Hart & Joe Bonamassa"])) id3.add( TXXX(encoding=major, desc="Artists", text=["Beth Hart", "Joe Bonamassa"])) id3.add(TSRC(encoding=major, text=["NLB931100460", "USMH51100098"])) id3.add( TXXX(encoding=major, desc="MusicBrainz Release Track Id", text="d062f484-253c-374b-85f7-89aab45551c7")) id3.add( IPLS(encoding=major, people=[["engineer", "James McCullagh"], ["engineer", "Jared Kvitka"], ["arranger", "Jeff Bova"], ["producer", "Roy Weisman"], ["piano", "Beth Hart"], ["guitar", "Blondie Chaplin"], ["guitar", "Joe Bonamassa"], ["percussion", "Anton Fig"], ["drums", "Anton Fig"], ["keyboard", "Arlan Schierbaum"], ["bass guitar", "Carmine Rojas"], ["orchestra", "The Bovaland Orchestra"], ["vocals", "Beth Hart"], ["vocals", "Joe Bonamassa"]])), id3.add(TORY(encoding=major, text="2011")) id3.add(TYER(encoding=major, text="2011")) id3.add(TDAT(encoding=major, text="2709"))
# def convert(seconds): # hours = seconds // 3600 # seconds %= 3600 # mins = seconds // 60 # seconds %= 60 # return(hours, mins, seconds) totalLength = 0 i = 1 newDirectory = mainDirectory + str(i) + "/" os.mkdir(newDirectory) for entry in obj: if entry.is_file(): audio = WAVE(entry) length = int(audio.info.length) print("this file is " + str(length) + " seconds") totalLength = totalLength + length print("running total is " + str(totalLength) + " seconds") if totalLength <= 3600 and length < 600: shutil.move(mainDirectory + str(entry.name), str(newDirectory + entry.name)) print(entry.name + " has been moved: " + str(totalLength) + " seconds have been used") else: i = i + 1 newDirectory = mainDirectory + str(i) + "/" os.mkdir(newDirectory) shutil.move(mainDirectory + str(entry.name), str(newDirectory + entry.name))
def rename(directory, filename, artist, title, extension, namingConvention): if namingConvention == "Artist - Title" or (namingConvention == 'Dynamic' and ' - ' in filename): try: os.rename( directory + '/' + filename, directory + '/' + str(artist) + ' - ' + str(title) + extension) filename = str(artist) + ' - ' + str(title) + extension except PermissionError: messagebox.showinfo( "Permission Error", "File cannot be renamed, it may still be open") return False, False elif namingConvention == "Title" or (namingConvention == 'Dynamic' and ' - ' not in filename): try: os.rename(directory + '/' + filename, str(directory) + '/' + str(title) + extension) filename = str(title) + extension except PermissionError: messagebox.showinfo( "Permission Error", "File cannot be renamed, it may still be open") return False, False if extension == ".wav": audio = WAVE(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".flac": audio = FLAC(str(directory) + '/' + filename) audio['artist'] = artist audio['title'] = title audio.save() return audio, filename elif extension == ".aiff": audio = AIFF(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".m4a": audio = MP4(str(directory) + '/' + filename) audio["\xa9ART"] = artist audio["\xa9nam"] = title audio.save() return audio, filename elif extension == ".mp3": audio = MP3(str(directory) + '/' + filename) audio["TPE1"] = TPE1(encoding=3, text=artist) audio["TIT2"] = TIT2(encoding=3, text=title) audio.save() return audio, filename elif extension == ".ogg": audio = OggVorbis(str(directory) + '/' + filename) audio['artist'] = artist audio['title'] = title audio.save() return audio, filename
def test_roundtrip(self): self.failUnlessEqual(self.tmp_wav_pcm_2s_16000_08_ID3v23["TIT2"], ["Silence"]) self.tmp_wav_pcm_2s_16000_08_ID3v23.save() new = WAVE(self.tmp_wav_pcm_2s_16000_08_ID3v23.filename) self.failUnlessEqual(new["TIT2"], ["Silence"])
def main(tex, pdf, vid, fast=False, tempo=1.0): lines = open(tex).readlines() lines = [l.strip() for l in lines] lines = list(filter(lambda l: '%>' in l, lines)) cur = -1 slideid = -1 frames = {} slide_per_frame = {} for l in lines: if l == '%>next': cur += 1 slideid += 1 frames[cur] = [] slide_per_frame[cur] = slideid elif l == '%>prev': cur += 1 slideid -= 1 frames[cur] = [] slide_per_frame[cur] = slideid elif l == '%>stop': break else: frames[cur].append(l) tmpdir = 'slides' os.makedirs(tmpdir, exist_ok=True) density = 304.8 if not fast else 61 command = f'convert -verbose -density {density} {pdf} {tmpdir}/%d.png' print(f'Executing command: {command}') os.system(command) # NOTE: the audio files are cached if the next did not change of a slide # delete the folder to clear the cache os.makedirs('audios', exist_ok=True) lengths = {} for i in sorted(frames.keys()): text = '\n'.join(frames[i]) oldtext = '' try: oldtext = open(f'audios/{i}.wav.txt', 'r').read() except: pass if text != oldtext: # NOTE: the noise is just to make it a bit more real run(text, f'audios/{i}.wav', noise=0.0005) os.system( f'sox audios/{i}.wav audios/{i}_tuned.wav reverb 25 25 lowpass -1 2300 pitch 0 tempo {tempo}' ) with open(f'audios/{i}.wav.txt', 'w') as f: f.write(text) length = WAVE(f'audios/{i}_tuned.wav').info.length lengths[i] = length print(i, length) files = ' '.join(f'audios/{i}_tuned.wav' for i in sorted(frames.keys())) os.system(f'sox --combine concatenate {files} audio.mp3 rate -v 44100') images = {} for f in sorted(frames.keys()): p = f'slides/{slide_per_frame[f]}.png' i = iio.read(p) print(f'{p}: {i.shape}') if i.shape[2] == 3: pass elif i.shape[2] == 4: # i.e. with an alpha channel (in [0., 255.]) # 255 seems to mean opaque, so I guess 0 is fully transparent i = i[:,:,0:3] * (i[:,:,3:] / 255.) \ + np.full(i.shape, 255.)[:,:,0:3] * (1. - i[:,:,3:] / 255.) print(f'{p}: {i.shape} (same image, removed alpha channel)') elif i.shape[2] == 1: # iio gives (h, w, 1) shape for gray images i = np.repeat(i, 3, axis=2) print(f'{p}: {i.shape} (same image, replicated single channel)') else: print(f'ERROR: Incorrect number of channels in image {p}') raise ValueError i = i.astype(np.uint8) images[f] = i.astype(np.uint8) height, width, _ = i.shape audio_stream = ffmpeg.input('audio.mp3') process = (ffmpeg.input( 'pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height), r=framerate).concat(audio_stream.audio, a=1).output( vid, pix_fmt=pix_fmt, crf=crf, preset=preset, vcodec=vcodec, r=framerate, tune='stillimage').overwrite_output().run_async(pipe_stdin=True)) acclengths = 0 accframe = 0 for f in sorted(frames.keys()): frame = images[f] l = lengths[f] while accframe < (acclengths + l) * framerate: process.stdin.write(frame.astype(np.uint8).tobytes()) accframe += 1 acclengths += l process.stdin.close() process.wait() print(acclengths / 60, 'minutes')
def speech_to_text(filename, cursor): # Из полученной строки вынимаем нужные нам параметры # We extract the parameters we need from the received string path = filename.split( '.wav' )[0] + '.wav' # нужно чтобы учесть папки у которых в названии есть пробел filename = filename.replace(path + ' ', '') parameters = [path] parameters.extend(filename.split(' ')) # проверяем что нету не заданных параметров # check that there are no parameters that are not set if len(parameters) != 4: log( f'date:{datetime.datetime.today().strftime("%Y-%m-%d")} time:{datetime.datetime.today().strftime("%H:%M")}' f' id:{1} AO:{""} phone:{""} audio_length:{""} result:{""} ' f'except:{"Неверное колличество параметров! Вы должны указать 4 параметра через пробел"}', False) raise Exception( 'Неверное колличество параметров! Вы должны указать 4 параметра через пробел\n' 'Example: Путь телефон флаг_записи_БД этап') # получаем переменные # getting variables path, phone, flag_bd, step = parameters[0], parameters[1], parameters[ 2], parameters[3] try: response = client.recognize(path, audio_config) print(response) # первый случай # first case if step == '1': # задаем множество со словами, которые нужно отследить # specify multiple words that you want to monitor checklist = {'автоответчик', 'сигнала'} common_words = set(response[0]["alternatives"][0] ["transcript"].split()) & checklist if len(common_words) > 0: AO = 'AO' else: AO = 'человек' # второй случай # second case elif step == '2': # задаем множество со словами, которые нужно отследить # specify multiple words that you want to monitor checklist = {'да', 'удобно', 'говорите', 'слушаю'} common_words = set(response[0]["alternatives"][0] ["transcript"].split()) & checklist if len(common_words) > 0: AO = 'положительно' else: AO = 'отрицательно' else: log( f'date:{datetime.datetime.today().strftime("%Y-%m-%d")} time:{datetime.datetime.today().strftime("%H:%M")}' f' id:{1} AO:{""} phone:{phone} audio_length:{""} result:{""} ' f'except:{"Этап распознования может быть либо 1 либо 2"}', False) raise Exception('Этап распознования может быть либо 1 либо 2') # получаем длину аудио # get the length of audio audio_length = str(WAVE('1.wav').info.length) # запись в бд # the record in the database if flag_bd == '1': # в качестве ProjectID будем брать этап распознавания, а в качестве ServerID будем брать flag_bd # we will use the recognition stage as the ProjectID, and we will use flag_bd as the ServerID cursor['cursor'].execute( f'INSERT INTO speech_to_text.operations (data,time,ao,phone,audio_length, result, ProjectID, ServerID)' f' VALUES (\'{datetime.datetime.today().strftime("%Y-%m-%d")}\',' f' \'{datetime.datetime.today().strftime("%H:%M")}\', \'{AO}\', \'{phone}\', \'{audio_length}\',' f' \'{response[0]["alternatives"][0]["transcript"]}\', {step}, {flag_bd}) RETURNING id' ) # получаем уникальный id записи в БД # get the unique id of the database entry id = cursor['cursor'].fetchone()[0] cursor['conection'].commit() else: with open('log.txt') as f: id = str(sum(1 for _ in f)) + 'n' # логируем успешный вариант # log the successful option log( f'date:{str(datetime.datetime.today().strftime("%Y-%m-%d"))} time:\'{str(datetime.datetime.today().strftime("%H:%M"))}\'' f' id:{id} AO:{AO} phone:{phone} audio_length:{audio_length} result:{response[0]["alternatives"][0]["transcript"]}', True) # Возвращаем в зависимости от шага и распознания # We return it depending on the step and recognition if (AO == 'AO') or (AO == 'отрицательно'): return 0 else: return 1 except Exception as e: log( f'date:{datetime.datetime.today().strftime("%Y-%m-%d")} time:{datetime.datetime.today().strftime("%H:%M")}' f' id:{1} AO:{""} phone:{phone} audio_length:{""} result:{""} except:{str(e)}', False)
def get_seconds_duration(track): audio = WAVE(f'./AUDIO/{selected_playlist.replace(".txt", "")}/{track}') audio_info = audio.info length = int(audio_info.length) return length
def test_delete(self): self.tmp_wav_pcm_2s_16000_08_ID3v23.delete() self.failIf(self.tmp_wav_pcm_2s_16000_08_ID3v23.tags) self.failUnless(WAVE(self.tmp_fn_pcm_2s_16000_08_ID3v23).tags is None)
def grab_reddit_data(submission_id, reddit, videoexport): target_submission = reddit.submission(id=submission_id) # target_submission.comment_sort = "top" # general data regarding the post main_post_dict = { "id": submission_id, "title": target_submission.title, "body": target_submission.selftext, "upvotes": target_submission.score, "subreddit": target_submission.subreddit_name_prefixed, "comments": target_submission.comments, "author": target_submission.author, "url": target_submission.url, "css-selector": target_submission.name } reddit_data = {"general": main_post_dict} comment_data = [] if bool(videoexport['video']['comment_size_is_seconds']): counter = 0 i = 0 # number of iteration in the while loop comments = deepcopy(target_submission.comments) comments = list(comments) # get all top level comments as a list while counter < videoexport['video']['comment_size']: comment = get_reddit_comment(i, comments) cmnt = { "id": comment.id, "author": comment.author, "body": comment.body, "name": comment.name } comment_data.append(cmnt) tmplocation = "tmp/" + comment.id + ".mp3" balcon_tts(voicename=videoexport['tts']['voice'], speed=videoexport['tts']['speed'], volume=videoexport['tts']['volume'], outputfile=tmplocation, text=re.sub(r'\\\B', r'', cmnt['body'])) audio = WAVE(tmplocation) audio_info = audio.info length = int(audio_info.length) counter += length i += 1 shutil.rmtree("tmp") os.mkdir("tmp") else: i = 0 # number of iteration in the while loop comments = deepcopy(target_submission.comments) comments = list(comments) # get all top level comments as a list while i < videoexport['video']['comment_size']: comment = get_reddit_comment(i, comments) cmnt = { "id": comment.id, "author": comment.author, "body": comment.body, "name": comment.name } comment_data.append(cmnt) i += 1 reddit_data['comment_data'] = comment_data return reddit_data
sound.export(dst, format="wav") # function to convert the information into some readable format def audio_duration(length): hours = length // 3600 # calculate in hours length %= 3600 mins = length // 60 # calculate in minutes length %= 60 seconds = length # calculate in seconds return hours, mins, seconds # returns the duration # Create a WAVE object Specify the directory address of your wavpack file audio = WAVE(dst) # contains all the metadata about the wavpack file audio_info = audio.info length = audio_info.length #getting information about file time_series, sample_rate = librosa.load(dst) # getting a matrix which contains amplitude values according to frequency and time indexes stft = np.abs(librosa.stft(time_series, hop_length=512, n_fft=2048 * 4)) # converting the matrix to decibel matrix spectrogram = librosa.amplitude_to_db(stft, ref=np.max) # getting an array of frequencies