#!/usr/bin/python3 import datetime as dt from threading import Timer from pydub import AudioSegment from time import sleep from timeloop import Timeloop # type: ignore import vlc # type: ignore class RepeatedTimer(object): def __init__(self, interval, function, *args, **kwargs): self._timer = None self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.is_running = False self.start() def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs) def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False tl = Timeloop() def leading_silence(audio_segment, silence_threshold=-50.0, chunk_size=10): """ Returns the millisecond/index that the leading silence ends. audio_segment - the segment to find silence in silence_threshold - the upper bound for how quiet is silent in dFBS chunk_size - chunk size for interating over the segment in ms https://github.com/jiaaro/pydub/blob/master/pydub/silence.py """ trim_ms = 0 # ms assert chunk_size > 0 # to avoid infinite loop while ( audio_segment[trim_ms:trim_ms + chunk_size].dBFS < silence_threshold and trim_ms < len(audio_segment)): trim_ms += chunk_size # if there is no end it should return the length of the segment return min(trim_ms, len(audio_segment)) def significant_fade(audio_segment, fade_threshold=-20.0, chunk_size=10): """ Returns the millisecond/index of the point where the fade is down to fade_threshold and doesn't get louder again. audio_segment - the segment to find silence in fade_threshold - the upper bound for how quiet is silent in dFBS chunk_size - chunk size for interating over the segment in ms """ assert chunk_size > 0 # to avoid infinite loop segment_length = audio_segment.duration_seconds * 1000 # ms trim_ms = segment_length - chunk_size while ( audio_segment[trim_ms:trim_ms + chunk_size].dBFS < fade_threshold and trim_ms > 0): trim_ms -= chunk_size # if there is no trailing silence, return lenght of track (it's less # the chunk_size, but for chunk_size = 10ms, this may be ignored) return trim_ms def trailing_silence(audio_segment, silence_threshold=-50.0, chunk_size=10): """ Returns the millisecond/index that the trailing silence starts. audio_segment - the segment to find silence in silence_threshold - the upper bound for how quiet is silent in dFBS chunk_size - chunk size for interating over the segment in ms """ assert chunk_size > 0 # to avoid infinite loop segment_length = audio_segment.duration_seconds * 1000 # ms trim_ms = segment_length - chunk_size while ( audio_segment[trim_ms:trim_ms + chunk_size].dBFS < silence_threshold and trim_ms > 0): trim_ms -= chunk_size # if there is no trailing silence, return lenght of track (it's less # the chunk_size, but for chunk_size = 10ms, this may be ignored) return trim_ms def ms_to_mmss(ms, decimals=0): if not ms: return "-" if ms < 0: sign = "-" else: sign = "" minutes, remainder = divmod(ms, 60 * 1000) seconds = remainder / 1000 return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}" # @tl.job(interval=timedelta(seconds=1)) def update_progress(player, talk_at, silent_at): elapsed_time = player.get_time() total_time = player.get_length() remaining_time = total_time - elapsed_time talk_time = remaining_time - (total_time - talk_at) silent_time = remaining_time - (total_time - silent_at) end_time = (dt.datetime.now() + timedelta( milliseconds=remaining_time)).strftime("%H:%M:%S") print( f"\t{ms_to_mmss(elapsed_time)}/" f"{ms_to_mmss(total_time)}\t\t" f"Talk in: {ms_to_mmss(talk_time)} " f"Silent in: {ms_to_mmss(silent_time)} " f"Ends at: {end_time} [{ms_to_mmss(remaining_time)}]" , end="\r") # Print name of current song, print name of next song. Play current when # return pressed, Pri--current-song-output-lengthnt remaining time every # second. When it ends, print name of new current and next song. def test(): track = "wibg.mp3" segment = AudioSegment.from_mp3(track) print(f"Track: {track}") print(f"Leading silence: {ms_to_mmss(leading_silence(segment), decimals=1)}") talk_at = significant_fade(segment) silent_at = trailing_silence(segment) print(f"Talkover fade: {ms_to_mmss(talk_at)}") print(f"Track silent from: {ms_to_mmss(silent_at)}") p = vlc.MediaPlayer("wibg.mp3") _ = input("") p.play() print() rt = RepeatedTimer(0.5, update_progress, p, talk_at, silent_at) sleep(1) while p.is_playing(): sleep(1) rt.stop() # better in a try/finally block to make sure the program ends! print("End") test() # next_song = get_next_song # # def play_track(): # r = run_aud_cmd("--current-song-length # # # # def play(): # play_track() # songtimer_start() # # # print("Start playing in 3 seconds") # # sleep(3) # # play() # print("starting...") # This auto-starts, no need of rt.start() # rt = RepeatedTimer(0.3, hello, "World") # # count = 5 # while count > 0: # print("main job here") # sleep(2) # rt.stop() # better in a try/finally block to make sure the program ends! # #!/usr/bin/python3 # # import time # from timeloop import Timeloop # from datetime import timedelta # # tl = Timeloop() # # @tl.job(interval=timedelta(seconds=2)) # def sample_job_every_2s(): # print(f"2s job current time: {time.ctime()}") # # @tl.job(interval=timedelta(seconds=5)) # def sample_job_every_5s(): # print(f"5s job current time: {time.ctime()}") # # @tl.job(interval=timedelta(seconds=10)) # def sample_job_every_10s(): # print(f"10s job current time: {time.ctime()}") # # @tl.job(interval=timedelta(seconds=0.2)) # def sample_job_every_10s(): # print(f"200ms job current time: {time.ctime()}") # # if __name__ == "__main__": # tl.start(block=True) #