2025, Oct 20 13:17

Как ускорить видео в MoviePy без AttributeError: правильное применение MultiplySpeed

Избавляемся от AttributeError в MoviePy при ускорении видео: как правильно применить эффект MultiplySpeed и корректно вызвать write_videofile на практике.

Ускорение видео в MoviePy может неожиданно оказаться сложным, если обращаться с эффектами так, будто это клипы. Частая ловушка — присвоить MultiplySpeed напрямую переменной и затем вызвать для неё write_videofile, что заканчивается AttributeError. Если вы увидели сообщение о том, что у объекта MultiplySpeed нет атрибута write_videofile, вы по адресу.

Демонстрация проблемы

Фрагмент ниже пытается ускорить видео, но терпит неудачу, потому что эффект не применяется к клипу:

from moviepy import *
import moviepy.video.fx as vfx
from moviepy.video.fx import MultiplySpeed

# загружаем, а затем по ошибке заменяем клип объектом эффекта
media_in = VideoFileClip(r"xxx.mp4")
media_in = MultiplySpeed(2)
media_in.write_videofile("fast_export.mp4", codec="libx264")

Это приводит к AttributeError, потому что в переменной, где раньше был клип, теперь находится экземпляр эффекта.

Что происходит на самом деле

MultiplySpeed — это эффект. Он сам по себе не превращается в видео; его нужно применить к существующему клипу. Когда вы перезаписываете переменную клипа значением MultiplySpeed(2), вы теряете доступ к методам клипа, таким как write_videofile. Правильная схема — держать в переменной настоящий клип и накладывать эффект либо через apply(), либо через with_effects() у самого клипа. В документации описано применение объекта эффекта методом apply(), а исходный код показывает, что доступен и with_effects() на клипе.

Рабочее решение и исправленный код

Первый вариант: применить объект эффекта к клипу.

from moviepy import *
import moviepy.video.fx as vfx
from moviepy.video.fx import MultiplySpeed

source_clip = VideoFileClip(r"xxx.mp4")
faster_clip = MultiplySpeed(2).apply(source_clip)
faster_clip.write_videofile("output_fast.mp4", codec="libx264")

Альтернативный подход: подключить эффект через with_effects() у клипа.

from moviepy import *
import moviepy.video.fx as vfx
from moviepy.video.fx import MultiplySpeed

src = VideoFileClip(r"xxx.mp4")
accelerated = src.with_effects([MultiplySpeed(2)])
accelerated.write_videofile("output_fast.mp4", codec="libx264")

Ниже практический вариант: скорость умножается на четыре, результат пишется по вложенному пути:

from moviepy import *
import moviepy.video.fx as vfx
from moviepy.video.fx import MultiplySpeed

video_pathname = r"xxxxxx.mp4"
base = VideoFileClip(video_pathname)
boosted = base.with_effects([MultiplySpeed(4)])
boosted.write_videofile("Random/output_fast.mp4", codec="libx264")

Почему это важно

Понимание границы между «клипом» и «эффектом» экономит время и избавляет от путаных ошибок. API клипа остаётся доступным только если в переменной хранится корректный VideoFileClip (или производный клип), а эффекты применяются к нему, а не наоборот. Что вам ближе — явный apply() у эффекта или лаконичный with_effects() у клипа — оба пути делают конвейер предсказуемым, а код — понятным.

Вывод

Когда нужно ускорить видео в MoviePy, не переопределяйте переменную клипа объектом эффекта. Сначала загрузите клип, затем примените MultiplySpeed через apply() или with_effects(), и только после этого рендерьте через write_videofile. Эта небольшая деталь устраняет AttributeError и поддерживает пайплайн чистым и удобным в сопровождении.

Статья основана на вопросе на StackOverflow от Sharks Charlatans и ответе пользователя furas.