我试图将gif与Spotify上播放的音乐节拍同步,但在同步过程中遇到了速度问题。我一定是疯了,因为我找不到这不起作用的理由。以下是我的方法:
BPS
)
BPS = BPM / 60
BPS
)中查找秒/拍(SPB
)
SPB = 1 / BPS
BPL
),找到秒数/圈数(SPL
)
SPL = SPB * BPL
SPL
)转换为毫秒/循环(MSPL
)
MSPL = SPL * 1000
MSPL
)除以.gif中的帧数(num_frames
),以找到一帧(frame_time
)所需的时间,舍入到最接近的偶数,因为.gif帧时间仅精确到整毫秒
frame_time = MSPL / num_frames
actual_duration
),循环帧加或减1毫秒,直到actual_duration
匹配ceil(MSPL)
(始终优先考虑更长的实际持续时间而不是更短的持续时间)
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)
现在,gif的实际毫秒/循环应该始终等于MSLP或大于MSLP。但是,当我使用指定的帧时间保存.gif时,如果校正值不是0,则.gif的播放速度总是比预期的快。我注意到,当使用其他在线服务提供相同的“将gif同步到音乐”功能时,情况也是如此;所以我想不仅仅是我疯了
下面是用于获取帧时间的实际代码:
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
我正在使用PIL(枕头)的图像模块保存gif:
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)
这里有什么我做错的吗?我似乎无法找到为什么这不起作用,以及为什么gif的实际持续时间比指定的帧时间短得多。其他提供此功能的站点/服务最终也会获得相同的结果,这让我感觉稍微好一点,但同时我觉得这肯定是可能的
解决了!我不知道这是对.gif格式的限制,还是对PIL中的图像模块的限制,但帧时间似乎只能精确到10毫秒的倍数。在检查修改后图像的实际帧时间时,它们被调整到最接近10的倍数,从而使整体播放速度比预期的快
为了解决这个问题,我修改了代码,以10为增量选择帧时间(如果需要,再次优先考虑更长的实际持续时间),并在整个列表中尽可能均匀地分散帧时间调整:
相关问题 更多 >
编程相关推荐