При склеивании видео через Moviepy: AttributeError: 'str' object has no attribute 'duration'
Я пытаюсь нарезать видео на фрагменты, потом склеить эти фрагменты в новое видео. Нарезка на фрагменты проходит успешно, а вот при склеивании выдает исключение:
Traceback (most recent call last):
File "D:\dev\video_cut\main.py", line 53, in <module>
main()
File "D:\dev\video_cut\main.py", line 49, in main
video.video_cut_and_merge('final')
File "D:\dev\video_cut\main.py", line 38, in video_cut_and_merge
merge_final = concatenate_videoclips(clip_merge)
File "D:\dev\video_cut\venv\lib\site-packages\moviepy\video\compositing\concatenate.py", line 71, in concatenate_videoclips
tt = np.cumsum([0] + [c.duration for c in clips])
File "D:\dev\video_cut\venv\lib\site-packages\moviepy\video\compositing\concatenate.py", line 71, in <listcomp>
tt = np.cumsum([0] + [c.duration for c in clips])
AttributeError: 'str' object has no attribute 'duration'
Сам код:
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from moviepy.editor import concatenate_videoclips
from colorama import Fore
from colorama import init
import os
import sys
from dataclasses import dataclass
init()
working_dir = os.path.sep.join(sys.argv[0].split(os.path.sep)[:-1])
@dataclass
class VideoEditor:
"""Basic VideoEditor Class."""
path_file: str
def video_cut_and_merge(self, name_file):
time_range = [(20, 30), (45, 55), (70, 90), (110, 120), (155, 170)]
print(Fore.CYAN + 'Начинаю вырезку фрагмента видео')
clip_merge = []
for i, (start_time, end_time) in enumerate(time_range):
output_path = f'{working_dir}\\sample\\clip_{i}.mp4'
ffmpeg_extract_subclip(self.path_file, start_time, end_time, targetname=output_path)
print(Fore.YELLOW + f'Длительность фрагмента: {end_time - start_time} секунд')
print(Fore.CYAN + 'Начинаю вырезку фрагмента видео')
clip_merge.append(output_path)
print(Fore.GREEN + f'\n[+] Видео сохранено в папку: {working_dir}\\sample')
if len(clip_merge) <= 1:
print(Fore.RED + '[-] В указанной директории нечего объединять')
else:
print(Fore.YELLOW + f'[+] Найдено фалов: {len(clip_merge)}')
merge_final = concatenate_videoclips(clip_merge)
merge_final.write_videofile(os.path.join(os.getcwd(), f'{name_file}.mp4'))
print(Fore.GREEN + '\n[+] Объединение файлов завершено')
def add_audio(self):
pass
def main() -> None:
"""Main Function."""
video = VideoEditor('D:\\dev\\video_cut\\Logic - Lightsabers (Official Music Video).mp4')
video.video_cut_and_merge('final')
if __name__ == "__main__":
main()
Ответы (1 шт):
Автор решения: CrazyElf
→ Ссылка
Пример использования функции concatenate_videoclips:
from moviepy.editor import VideoFileClip, concatenate_videoclips
clip1 = VideoFileClip("myvideo.mp4")
clip2 = VideoFileClip("myvideo2.mp4").subclip(50,60)
clip3 = VideoFileClip("myvideo3.mp4")
final_clip = concatenate_videoclips([clip1,clip2,clip3])
final_clip.write_videofile("my_concatenation.mp4")
Как видно из примера, в функцию concatenate_videoclips нужно передавать объекты типа VideoFileClip, а не пути к файлам, как у вас:
clip_merge = []
...
output_path = f'{working_dir}\\sample\\clip_{i}.mp4'
clip_merge.append(output_path)
...
merge_final = concatenate_videoclips(clip_merge)
Наверное, достаточно будет поменять одну строку:
clip_merge.append(VideoFileClip(output_path))
^^^^^^^^^^^^^^ ^