So i was using Rythm bot in discord and while using the command {prefix}np i noticed that there is video duration display. Please view the given image.
IMAGE
I wanna know how to do it in discord.py, it might be useful for me. When you seek a specific time frame, it should display the timeline with correct ratio and proportion(i exactly don't know how to explain it but you get it right). I tried doing myself and i failed. so any help would be appreciated :)
First, you have to determine the length of the song, the current play length, and how many characters long your answer should be.
Now you have to determine the location of the play sign (current_length).
You can do that by doing the same as if you wanted to calculate a percentage, but instead of 100% maximum you want the character length (20 in this case) as maximum:
current_length = display_length / total_seconds * current_seconds
You also have to convert current_length to an integer so you can determine its loaction in the display_string
So, putting that into code:
total_seconds = 217
current_seconds = 132
display_string = ""
display_length = 20
current_length = int(display_length / total_seconds * current_seconds)
for i in range(display_length):
if i == current_length:
display_string += ">"
else:
display_string += "-"
print(display_string)
Related
A program I'm developing involves a function that adjusts the BPM (beats per minute) of one song to the BPM of another target song.
The issue is, sometimes adjusting the song to the exact BPM of the target song isn't a good idea, as the first song may be sped up or slowed down too much, so it sounds too fast or too slow. In these situations, it makes sense to adjust the BPM of the song to another closer BPM that is still compatible with the target song's BPM.
Here's an example:
BPM of song 1: 150BPM
BPM of target song: 84BPM
In this case, slowing down a 150BPM song to 84BPM isn't very practical - the audio will become too distorted and sound weird. It makes more sense to adjust song 1 to 168BPM - double the BPM of the target song, as this requires significantly less modification to song 1, and will sound more natural.
Looking at the same example switched around:
BPM of song 1: 84BPM
BPM of target song: 150BPM
In this case, it makes sense to slow song 1 down to 75BPM, half of 150, rather than speeding the song all the way up to 150.
In this program, the BPMs of song 1 and the target song differ based on what songs it is given (obviously). What is want this function to do is always go to the closest number compatible with the target BPM - what's the math I need? I'm using Python. I've had a huge headache today making the rest of the whole program.
I think you have all you need. You can figure it out as a human, so put that into code. The problem often is that you don't exactly know what you're doing, because you're too used to it.
Let's get started with a function definition:
def targetbpm(bpmPlaying: int, bpmTarget: int) -> int:
pass
And the given expected outcomes of the two examples you provided
assert(targetbpm(150, 84) == 168)
assert(targetbpm(84, 150) == 75)
Let's tackle the first assertion. What options are there? As you said, you could go to 84, but it would be better to double that.
def targetbpm(bpmPlaying: int, bpmTarget: int) -> int:
choices = [bpmTarget, bpmTarget*2]
Which one to choose? The one with the minimum difference to what is currently playing. So let's get these differences and the minimum of these:
bpmdiff = [abs(bpmPlaying - choice) for choice in choices]
minimum = min(bpmdiff)
Now let's go back to the original choices and select the corresponding one
index = bpmdiff.index(minimum)
return choices[index]
Now you'll find that the second assertion is not passing yet. The reason is that you have another choice here: half the BPM. So let's add that:
choices = [bpmTarget, bpmTarget*2, bpmTarget // 2]
Problem solved.
This would be one quick way to do it.
def get_BPM_multiple(base, target):
distance = abs(target - base)
multiple = 1
for i in range(2, 8): # 8 or whatever
if base < target:
newdist = abs(target - base * i)
else:
newdist = abs(target - base / i)
if newdist < distance:
distance = newdist
multiple = i
else:
break
if base < target:
print(f"Multiply base {base}BPM by {multiple}: {base * multiple}BPM, "
f"close to target {target}BPM.")
return base * multiple
else:
print(f"Divide base {base}BPM by {multiple}: {base / multiple}BPM, "
f"close to target {target}BPM.")
return base / multiple
get_BPM_multiple(base=300, target=84)
# Divide base 300BPM by 4: 75.0BPM, close to target 84BPM.
get_BPM_multiple(base=84, target=150)
# Multiply base 84BPM by 2: 168BPM, close to target 150BPM.
I developed this script in SIKULI, but I would like to add more functions and I'm thinking about using Python and learning the language.
SIKULI has OCR but still contains some bugs, not performing so well. Likewise I would like to use OCR/tesseract/pytesseract in python.
The idea of this script is to make you heal in a game, according to the current % of health, reading the number of the current health bar vs the total value it has.
After reading this number, a calculation is performed with the result in %.
Could you help me fix this script by inserting the necessary libraries and tweaking the code to make it work in Python?
#==Config HP==
Healing_1 = 95
Hk_healing_1 = '5'
Healing_2 = 65
Hk_healing_2 = '1'
Healing_3 = 30
Hk_healing_3 = '3'
#==Code==
while True:
GAME = App("GAME")
GAME.focus()
Settings.OcrTextRead = True
#==hp==
hp = Region(88,28,191,23)
hp = hp.text()
hp2 = hp.replace(",","")
X = hp2.split("/")
try:
check_hp = float(X[0]) / float(X[1]) * 100
except:
type(Hk_healing_3)
#==hp check==
if check_hp < 100:
if check_hp <= Healing_3:
type(Hk_healing_3)
elif check_hp <= Healing_2:
type(Hk_healing_2)
elif check_hp <= Healing_1:
type(Hk_healing_1)
else:
pass
Just for information, this function should identify the text in a region of the screen. The text of the screen, will be displayed as xxxx/xxxx (current value / total value) - it's could be other format as x/x, xx/xx, xxx/xxx, xxxx/xxxx, xxxxx/xxxxx, x/xxxx, x/xxxxxxx ...
The text will be split to perform the calculation (% of current value).
I'm attempting to sync a gif to the beat of music playing on Spotify, but I'm encountering a speed issue while doing so. I must be going crazy because I can't find a reason as to why this isn't working. Below is my methodology:
Take initial BPM (ex: 150) and find the Beats/Second (BPS)
BPS = BPM / 60
Find the Seconds/Beat (SPB) from the Beats/Second (BPS)
SPB = 1 / BPS
Find the Seconds/Loop (SPL) by multiplying by the number of Beats/Loop (BPL) of the .gif
SPL = SPB * BPL
Convert Seconds/Loop (SPL) to Milliseconds/Loop (MSPL)
MSPL = SPL * 1000
Divide the Milliseconds/Loop (MSPL) by the number of frames (num_frames) in the .gif to find the time required for one frame (frame_time), rounding to the nearest even number since .gif frame times are only accurate up to whole milliseconds
frame_time = MSPL / num_frames
Add up the total frame times (actual_duration) and loop through frames adding or subtracting 1 millisecond until actual_duration matches ceil(MSPL) (always prioritizing longer actual duration over shorter duration)
difference = MSPL - actual_duration
if not math.isclose(0, difference):
# Add the difference and always prioritize longer duration compared to real duration value
correction = int(math.ceil(difference))
for i in range(0, abs(correction)):
# Add/subtract corrections as necessary to get actual duration as close as possible to calculated duration
frame_times[i % len(frame_times)] += math.copysign(1, correction)
Now from this, the actual Milliseconds/Loop of the gif should always be equal to MSLP or greater than MSLP. However, when I save the .gif with the specified frame times, if the correction value is not 0 then the .gif always plays at a faster speed than expected. I have noticed that when using other services online that provide the same "sync gif to music" functionality, this is also the case; so it's not just me going crazy I think.
Below is the actual code used to get frame times:
def get_frame_times(tempo: float, beats_per_loop: int, num_frames: int):
# Calculate the number of seconds per beat in order to get number of milliseconds per loop
beats_per_sec = tempo / 60
secs_per_beat = 1 / beats_per_sec
duration = math.ceil(secs_per_beat * beats_per_loop * 1000)
frame_times = []
# Try to make frame times as even as possible by dividing duration by number of frames and rounding
actual_duration = 0
for _ in range(0, num_frames):
# Rounding method: Bankers Rounding (round to the nearest even number)
frame_time = round(duration / num_frames)
frame_times.append(frame_time)
actual_duration += frame_time
# Add the difference and always prioritize longer duration compared to real duration value
difference = duration - actual_duration
if not math.isclose(0, difference):
correction = int(math.ceil(difference))
for i in range(0, abs(correction)):
# Add/subtract corrections as necessary to get actual duration as close as possible to calculated duration
frame_times[i % len(frame_times)] += math.copysign(1, correction)
return frame_times
I'm saving the gif by using PIL (Pillow)'s Image module:
frame_times = get_frame_times(tempo, beats_per_loop, num_frames)
frames = []
for i in range(0, num_frames):
# Frames are appended to frames list here
# disposal=2 used since the frames may be transparent
frames[0].save(
output_file,
save_all=True,
append_images=frames[1:],
loop=0,
duration=frame_times,
disposal=2)
Is there anything that I am doing wrong here? I can't seem to find out why this isn't working and why the actual duration of the gif is much shorter than the specified frame times. It makes me feel slightly better that other sites/services that provide this functionality end up with the same results, but at the same time I feel like this should definitely be possible.
Solved! I don't know if this is a limitation of the .gif format or if it's a limitation of the Image module in PIL, but it appears that frame times can only be accurate up to multiples of 10 milliseconds. Upon inspecting the actual frame times of the modified image, they were being floored to the nearest multiple of 10 resulting in an overall faster playback speed than expected.
To fix this, I modified the code to choose frame times in increments of 10 (again prioritizing a longer actual duration if necessary) and dispersing the frame time adjustments as evenly as possible throughout the list:
def get_frame_times(tempo: float, beats_per_loop: int, num_frames: int):
# Calculate the number of seconds per beat in order to get number of milliseconds per loop
beats_per_sec = tempo / 60
secs_per_beat = 1 / beats_per_sec
duration = round_tens(secs_per_beat * beats_per_loop * 1000)
frame_times = []
# Try to make frame times as even as possible by dividing duration by number of frames
actual_duration = 0
for _ in range(0, num_frames):
frame_time = round_tens(duration / num_frames)
frame_times.append(frame_time)
actual_duration += frame_time
# Adjust frame times to match as closely as possible to the actual duration, rounded to multiple of 10
# Keep track of which indexes we've added to already and attempt to split corrections as evenly as possible
# throughout the frame times
correction = duration - actual_duration
adjust_val = int(math.copysign(10, correction))
i = 0
seen_i = {i}
while actual_duration != duration:
frame_times[i % num_frames] += adjust_val
actual_duration += adjust_val
if i not in seen_i:
seen_i.add(i)
elif len(seen_i) == num_frames:
seen_i.clear()
i = 0
else:
i += 1
i += num_frames // abs(correction // 10)
return frame_times
I am currently trying to program a script for my school project. It is supposed to take one pixel from the camera feed and measure at that spot multiple times (for noise cancellation). The part of my code that I am not satisfied with currently looks like this:
canon.ScanXY(x,y)
img_1 = canon.FetchImage(0, 1 * 1)
canon.StopScan()
canon.ScanXY(x,y)
img_2 = canon.FetchImage(0, 1 * 1)
canon.StopScan()
...
canon.ScanXY(x,y)
img_xxx = canon.FetchImage(0, 1 * 1)
canon.StopScan()
The code above will return a string with name img_xxx where xxx stands for a specific number. I was wondering, if there is an easier way to do this. I was trying to loop the function, but was unable to do it so that I have different result from every iteration. And at the end I need to add all of those together in order to create one string from all that were generated before:
img_final = (img_1 + img_2 + img_3 + ... + img_xxx)
and finally to print a Picture out of the result, using
img = np.fromstring(img_final, dtype="uint8").reshape(8,8)
fig, ax = plt.subplots()
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
ax.set_xticklabels((0,1))
x=ax.imshow(img,cmap="gray")
The code works, but if I want to change anything, it really takes a lot of time. So far I was working with 64 or less strings, but I want to refine the results, so I would need much more iterations. Any help would be appreciated.
img_final is supposed to be the sum of a sequence of individual img's. The analogy to adding a sequence of integers read from the console would be:
final = int(input("First num: "))
for x in range(xxx-1):
num = int(input("Next num: "))
final += num
Am kind of new to coding,please help me out with this one with explanations:
songs is an array of objects which are formatted as follows:
{artist: 'Artist', title: 'Title String', playback: '04:30'}
You can expect playback value to be formatted exactly like above.
Output should be a title of the longest song from the database that matches the criteria of not being longer than specified time. If there's no songs matching criteria in the database, return false.
Either you could change playback, so that instead of a string, it's an integer (for instance, the length of the song in seconds) which you convert to a string for display, and test from there, or, during the test, you could take playback and convert it to its length in seconds, like so:
def songLength(playback):
seconds = playback.split(':')
lengthOfSong = int(seconds[0]) * 60 + int(seconds[1])
return lengthOfSong
This will give the following result:
>>> playback = '04:30'
>>> songLength(playback)
270
I'm not as familiar with the particular data structure you're using, but if you can iterate over these, you could do something like this:
def longestPossible(array, maxLength):
longest = 0
songName = ''
for song in array:
lenSong = songLength(song.playback) # I'm formatting song's playback like this because I'm not sure how you're going to be accessing it.
if maxLength >= lenSong and (maxLength - lenSong) < (maxLength - longest):
longest = lenSong
songName = song.title
if longest != 0:
return songName
else:
return '' # Empty strings will evaluate to False.
I haven't tested this, but I think this should at least get you on the right track. There are more Pythonic ways of doing this, so never stop improving your code. Good luck!