mirror of
https://github.com/harry0703/MoneyPrinterTurbo.git
synced 2026-02-21 16:37:21 +08:00
第一帧视频没有转场特效
This commit is contained in:
parent
f0b8fbbbfb
commit
e90c195e9e
@ -93,7 +93,7 @@ class VideoParams(BaseModel):
|
||||
|
||||
subtitle_enabled: Optional[bool] = True
|
||||
subtitle_position: Optional[str] = "custom" # top, bottom, center, custom
|
||||
custom_position: float = 70.0
|
||||
custom_position: float = 85.0
|
||||
font_name: Optional[str] = "STHeitiMedium.ttc"
|
||||
text_fore_color: Optional[str] = "#FFFFFF"
|
||||
text_background_color: Union[bool, str] = True
|
||||
|
||||
@ -58,6 +58,11 @@ def pulse_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
:param speed: 动画速度
|
||||
:return: 应用了动画效果的剪辑
|
||||
"""
|
||||
# 确保剪辑有持续时间
|
||||
if not hasattr(clip, 'duration') or clip.duration is None:
|
||||
logger.warning("Clip has no duration, using default duration of 5 seconds")
|
||||
clip = clip.with_duration(5)
|
||||
|
||||
# 应用整体缩放效果
|
||||
return clip.resized(lambda t: 1 + 0.1 * np.sin(speed * 2 * np.pi * t))
|
||||
|
||||
@ -70,6 +75,11 @@ def whole_bounce_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
:param speed: 动画速度
|
||||
:return: 应用了动画效果的剪辑
|
||||
"""
|
||||
# 确保剪辑有持续时间
|
||||
if not hasattr(clip, 'duration') or clip.duration is None:
|
||||
logger.warning("Clip has no duration, using default duration of 5 seconds")
|
||||
clip = clip.with_duration(5)
|
||||
|
||||
# 获取原始位置
|
||||
original_position = clip.pos
|
||||
|
||||
@ -129,10 +139,13 @@ def light_sweep_animation(clip: ImageClip, duration: float, speed: float = 1.0)
|
||||
# 创建一个白色光照剪辑
|
||||
light_clip = ColorClip(size=clip.size, color=(255, 255, 255))
|
||||
light_clip = light_clip.with_mask(light_mask)
|
||||
light_clip = light_clip.with_duration(duration)
|
||||
|
||||
# 合成原始剪辑和光照剪辑
|
||||
# 由于 ColorClip 没有 with_blend 方法,我们直接使用 CompositeVideoClip
|
||||
return CompositeVideoClip([clip, light_clip])
|
||||
composite_clip = CompositeVideoClip([clip, light_clip])
|
||||
composite_clip = composite_clip.with_duration(duration)
|
||||
return composite_clip
|
||||
|
||||
|
||||
def fade_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
@ -143,6 +156,11 @@ def fade_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
:param speed: 动画速度
|
||||
:return: 应用了动画效果的剪辑
|
||||
"""
|
||||
# 确保剪辑有持续时间
|
||||
if not hasattr(clip, 'duration') or clip.duration is None:
|
||||
logger.warning("Clip has no duration, using default duration of 5 seconds")
|
||||
clip = clip.with_duration(5)
|
||||
|
||||
# 创建一个函数,根据时间返回不透明度
|
||||
def make_frame_opacity(t):
|
||||
# 计算总时长
|
||||
@ -191,6 +209,11 @@ def wave_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
:param speed: 动画速度
|
||||
:return: 应用了动画效果的剪辑
|
||||
"""
|
||||
# 确保剪辑有持续时间
|
||||
if not hasattr(clip, 'duration') or clip.duration is None:
|
||||
logger.warning("Clip has no duration, using default duration of 5 seconds")
|
||||
clip = clip.with_duration(5)
|
||||
|
||||
# 获取原始位置
|
||||
original_position = clip.pos
|
||||
|
||||
@ -220,6 +243,11 @@ def bounce_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
:param speed: 动画速度
|
||||
:return: 应用了动画效果的剪辑
|
||||
"""
|
||||
# 确保剪辑有持续时间
|
||||
if not hasattr(clip, 'duration') or clip.duration is None:
|
||||
logger.warning("Clip has no duration, using default duration of 5 seconds")
|
||||
clip = clip.with_duration(5)
|
||||
|
||||
# 注意:这个函数需要对每个字符单独处理
|
||||
# 但由于我们已经将文本渲染为图像,无法直接操作单个字符
|
||||
# 这里我们实现一个模拟效果,通过对图像应用波浪变形来模拟字符跳动
|
||||
@ -235,9 +263,14 @@ def bounce_animation(clip: ImageClip, speed: float = 1.0) -> ImageClip:
|
||||
# 获取原始帧
|
||||
frame = clip.get_frame(t)
|
||||
|
||||
# 创建一个新的帧
|
||||
# 创建一个新的帧,保持透明通道
|
||||
# 使用与原始帧相同的数据类型和形状,但初始化为透明
|
||||
new_frame = np.zeros_like(frame)
|
||||
|
||||
# 如果有alpha通道(RGBA),将所有像素设置为完全透明
|
||||
if frame.shape[2] == 4:
|
||||
new_frame[:, :, 3] = 0 # 设置alpha通道为0(完全透明)
|
||||
|
||||
# 对每一列应用不同的垂直偏移,创造波浪效果
|
||||
for x in range(w):
|
||||
# 计算该列的垂直偏移量,使用正弦函数创建波浪效果
|
||||
|
||||
@ -93,6 +93,9 @@ def combine_videos(
|
||||
random.shuffle(raw_clips)
|
||||
|
||||
# Add downloaded clips over and over until the duration of the audio (max_duration) has been reached
|
||||
# 用于跟踪是否是第一个视频片段
|
||||
is_first_clip = True
|
||||
|
||||
while video_duration < audio_duration:
|
||||
for clip in raw_clips:
|
||||
# Check if clip is longer than the remaining audio
|
||||
@ -139,27 +142,34 @@ def combine_videos(
|
||||
f"resizing video to {video_width} x {video_height}, clip size: {clip_w} x {clip_h}"
|
||||
)
|
||||
|
||||
shuffle_side = random.choice(["left", "right", "top", "bottom"])
|
||||
logger.info(f"Using transition mode: {video_transition_mode}")
|
||||
if video_transition_mode.value == VideoTransitionMode.none.value:
|
||||
clip = clip
|
||||
elif video_transition_mode.value == VideoTransitionMode.fade_in.value:
|
||||
clip = video_effects.fadein_transition(clip, 1)
|
||||
elif video_transition_mode.value == VideoTransitionMode.fade_out.value:
|
||||
clip = video_effects.fadeout_transition(clip, 1)
|
||||
elif video_transition_mode.value == VideoTransitionMode.slide_in.value:
|
||||
clip = video_effects.slidein_transition(clip, 1, shuffle_side)
|
||||
elif video_transition_mode.value == VideoTransitionMode.slide_out.value:
|
||||
clip = video_effects.slideout_transition(clip, 1, shuffle_side)
|
||||
elif video_transition_mode.value == VideoTransitionMode.shuffle.value:
|
||||
transition_funcs = [
|
||||
lambda c: video_effects.fadein_transition(c, 1),
|
||||
lambda c: video_effects.fadeout_transition(c, 1),
|
||||
lambda c: video_effects.slidein_transition(c, 1, shuffle_side),
|
||||
lambda c: video_effects.slideout_transition(c, 1, shuffle_side),
|
||||
]
|
||||
shuffle_transition = random.choice(transition_funcs)
|
||||
clip = shuffle_transition(clip)
|
||||
# 如果是第一个视频片段,不应用转场效果
|
||||
if is_first_clip:
|
||||
logger.info("First clip: no transition effect applied")
|
||||
# 不应用任何转场效果
|
||||
is_first_clip = False # 更新标志,后续片段将应用转场效果
|
||||
else:
|
||||
# 对后续视频片段应用转场效果
|
||||
shuffle_side = random.choice(["left", "right", "top", "bottom"])
|
||||
logger.info(f"Using transition mode: {video_transition_mode}")
|
||||
if video_transition_mode.value == VideoTransitionMode.none.value:
|
||||
clip = clip
|
||||
elif video_transition_mode.value == VideoTransitionMode.fade_in.value:
|
||||
clip = video_effects.fadein_transition(clip, 1)
|
||||
elif video_transition_mode.value == VideoTransitionMode.fade_out.value:
|
||||
clip = video_effects.fadeout_transition(clip, 1)
|
||||
elif video_transition_mode.value == VideoTransitionMode.slide_in.value:
|
||||
clip = video_effects.slidein_transition(clip, 1, shuffle_side)
|
||||
elif video_transition_mode.value == VideoTransitionMode.slide_out.value:
|
||||
clip = video_effects.slideout_transition(clip, 1, shuffle_side)
|
||||
elif video_transition_mode.value == VideoTransitionMode.shuffle.value:
|
||||
transition_funcs = [
|
||||
lambda c: video_effects.fadein_transition(c, 1),
|
||||
lambda c: video_effects.fadeout_transition(c, 1),
|
||||
lambda c: video_effects.slidein_transition(c, 1, shuffle_side),
|
||||
lambda c: video_effects.slideout_transition(c, 1, shuffle_side),
|
||||
]
|
||||
shuffle_transition = random.choice(transition_funcs)
|
||||
clip = shuffle_transition(clip)
|
||||
|
||||
if clip.duration > max_clip_duration:
|
||||
clip = clip.subclipped(0, max_clip_duration)
|
||||
|
||||
@ -762,7 +762,7 @@ with right_panel:
|
||||
|
||||
if params.subtitle_position == "custom":
|
||||
custom_position = st.text_input(
|
||||
tr("Custom Position (% from top)"), value="65.0"
|
||||
tr("Custom Position (% from top)"), value="85.0"
|
||||
)
|
||||
try:
|
||||
params.custom_position = float(custom_position)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user