Python Moviepy – 코딩으로 동영상 만들기

사운드와 이미지 편집만 해봤는데 영상은 처음 만들어보는데 정말 재밌어요!

하는 방법을 간단히 소개하겠습니다.

영화 개요

https://github.com/Zulko/moviepy

GitHub – Zulko/moviepy: Python으로 동영상 편집하기

파이썬으로 영상편집. GitHub에서 계정을 만들어 Zulko/moviepy 개발에 기여하세요.

github.com

Python의 moviepy 패키지를 사용하면 인코딩으로 원하는 만큼 비디오를 만들 수 있습니다!

moviepy는 정말 좋은 프로젝트지만 그 개발은 의미가 없습니다. 3년 동안 패치를 하지 않은 프로젝트입니다.

비디오 편집에는 음성, 음성 효과, 텍스트, 이미지, 비디오, 비디오 효과, 디코딩, 인코딩, 포맷팅 등 다양한 지식이 필요합니다. Moviepy도 구현하기가 전혀 어렵기 때문에 다른 프로젝트를 Python과 함께 사용하기 위해 래핑하는 프로젝트입니다.

이 분야에서 여전히 널리 사용되고 있는 God 라이브러리 FFmpeg는 오디오, 이미지 및 비디오에 사용되었습니다.


텍스트는 아주 오래된 고전 신 라이브러리인 ImageMagick을 사용했습니다.


https://imagemagick.org/index.php

또한 대부분의 비디오 효과는 opencv를 사용했습니다.


설치하는 방법

설치 방법은 Windows용과 Mac용이 다릅니다.

다른 글도 많으니 자세한 설명은 생략하겠습니다.

*맥은 명령어로 모든 부분을 진행할 수 있었고,

*윈도우에서는 명령어를 지원하지 않기 때문에 사이트에서 직접 다운받아 직접 설치하고 환경변수를 설정해야 했습니다. (ffmpeg, imagemagick 등)

*참고: 시스템 글꼴이 아닌 사용자 정의 글꼴을 읽을 때는 ImageMagick에서 GhostScript로 생성된 글꼴 가이드 파일을 업데이트하고 사용해야 합니다. 다른 글꼴이 나오지 않는다고 말하지 마십시오. (장난도 잘 치는데.. ㅠ)

*주의할 또 다른 점. mp3의 경우 라이선스 문제가 있는지 확인하기 위해 별도로 설치해야 했습니다.

개발 전

1. ffmpeg를 사용하지만 GPU 가속이 부족하여 처리 시간이 오래 걸리는 경우가 많습니다.

2. CPU는 멀티 코어로 사용할 수 없습니다. 이것이 개별 클록 속도가 더 높은 CPU가 더 빠른 이유입니다. (인텔이 AMD보다 유리함)

3. 3분짜리 영상을 만드는 데 10분 정도 소요될 수 있습니다.

4. 다른 영상에서 참조되는 부분이 많을수록 RAM 소모가 많습니다.

5. 전처리 및 병합은 속도면에서 유리합니다.

6. 예쁘고 알록달록한 영상을 만들고 싶다면 영상 편집 도구가 좋다. 단순 반복 작업을 개선하는 방식으로 moviepy를 사용하세요.

7. Python은 코루틴이 되지만 moviepy에서 사용하는 함수는 외부 프로그램을 호출하도록 설계되었기 때문에 외부 프로그램을 동시에 실행할 수 없으므로 단일 스레드로 작동하게 됩니다.

8. 무비피 검색하면 나오는 문서로 정말 다 해결된다. (https://zulko.github.io/moviepy/ref/AudioClip.html)

기본 사상

1. 길이: 비디오 또는 오디오의 전체 길이를 의미합니다.

2. 위치: 영상에서는 좌표, 음성에서는 특정 시간을 의미합니다. 왼쪽 상단은 0,0에서 시작합니다.

3. 클립: 비디오, 오디오, 이미지 또는 텍스트와 같은 미디어 개체입니다.

4. 서브클립: 미디어 단위로 편집된 작은 단위를 말한다.

5. fx: 함수, 효과함수(x)는 주로 약칭한다.

6. AudioFileClip : 오디오 파일 클립

7. ImageClip: 이미지 파일 클립

8. VideoFileClip : 비디오 파일 클립

9. TextClip: 텍스트 클립

10. 처리 시간: 합성 명령(CompositeAudioClip, CompositeVideoClip)을 사용하거나 내보낼 때만 처리가 발생합니다. 그때까지는 클립에 명령을 수집하고 저장하는 작업이 계속됩니다.

11. ImageClip, TextClip 및 VideoFileClip을 CompositeVideoClip 명령으로 결합할 수 있습니다.

모든 코딩을 설명하기는 어려우므로 간단한 예제를 통해 보여드리겠습니다.

1. 여러 음성 결합

bg_audio_clip = AudioFileClip("./edit_video/dreams.mp3")
bg_audio_clip = afx.audio_loop(bg_audio_clip, duration=voice_clip_duration)
bg_audio_clip = bg_audio_clip.subclip(0,voice_clip_duration)
bg_audio_clip = bg_audio_clip.set_start(0)
bg_audio_clip = bg_audio_clip.set_end(voice_clip_duration)
bg_audio_clip = bg_audio_clip.volumex(0.2)  
bg_audio_clip = bg_audio_clip.fx(afx.audio_fadeout, 0.5)
main_audio_clip = CompositeAudioClip((bg_audio_clip, voice_clip))

끝없는 배경 소음 루프를 만들고,

말하는 시간과 동일하게 배경음을 잘라냅니다.

클립의 시작 및 종료 시간을 직접 설정하십시오. (다른 클립과 결합할 때 기본값입니다.)

볼륨을 조절하고 서서히 소리를 줄여보세요.

CompositeAudioClip 기능을 통해 배경음과 음성을 결합합니다.

2. 동영상을 원하는 크기로 자르기

# clip
video_clip = VideoFileClip(file_path)
print(f'original clip duration:{video_clip.duration}') 

# 동영상의 가로 사이즈 맞추기
if video_clip.size(0) < MAX_SIZE(0):
    w_ratio = MAX_SIZE(0)/video_clip.size(0)
    (w,h) = video_clip.size
    video_clip = video_clip.resize((w*w_ratio, h*w_ratio)) 
    video_clip.set_position('center') #중심으로 변경

# 동영상 중심 맞춰서 자르기 
if video_clip.size(0) != MAX_SIZE(0) or video_clip.size(1) != MAX_SIZE(1):
    (w,h) = video_clip.size 
    video_clip = crop(video_clip, width=MAX_SIZE(0), height=MAX_SIZE(1), x_center=w/2, y_center=h/2)

# 음성제거
if without_audio:
    video_clip = video_clip.without_audio()

영화를 비디오 클립으로 만드십시오.

원하는 크기로 조정합니다.

set_position을 호출하여 화면 중앙을 예약합니다. (즉시 변환되지 않습니다.)

최대 크기를 초과하지 않도록 비디오를 자릅니다.

오디오를 별도로 준비했기 때문에 영상에 포함된 오디오는 제거합니다. (즉시 삭제되지 않습니다.)

3. 여러 동영상 합치기

 for path in folder_file_list:

        # 파일 선택
        temp_path = f"{video_resource_folder_path}/{path}"
        file_size = os.path.getsize(temp_path)
        if file_size == 0:
            continue


        # 일관된 형태로 변경
        video_clip = convert_video(temp_path)
        video_clip = video_clip.fx(vfx.speedx, SPEED) # 배속효과
        video_clip_duration = video_clip.duration
        video_clip = video_clip.set_start(total_video_clip_duration)
        video_clip = video_clip.set_end(total_video_clip_duration+video_clip_duration)

        # 비디오 선택
        bg_video_clip_list.append(video_clip)
        print(f'selected video path:{temp_path}')
        total_video_clip_duration += video_clip_duration 
         
    # 영상만들기
    bg_video_clip_list.extend(verse_video_clip_list)
    main_video_clip = CompositeVideoClip(bg_video_clip_list)
    main_video_clip = main_video_clip.subclip(0, verse_voice_clip_duration) 
    main_video_clip.audio = main_audio_clip
    main_video_clip.write_videofile(full_file_path, threads=32, fps=24)

파일에서 비디오를 가져옵니다.

배속을 적용합니다.

2배속을 적용한 후 시간을 얻으면 2배속을 적용한 시간을 반환한다.

동영상을 하나씩 연결하려면 누적 및 증가 시간을 시작점으로 설정합니다.

비디오 클립의 종료 시간은 시작 지점 이후의 시점으로 영화의 길이에 의해 결정됩니다.

모든 비디오 클립은 이와 같이 다른 시간으로 설정됩니다.

CompositeVideoClip을 호출하여 단일 클립으로 변환하면 파일 변환이 시작됩니다.

주문을 위해 비디오를 서브클립합니다.

사전 제작된 오디오로 설정,

24fps로 비디오를 추출합니다. 이 시점에서 32개의 스레드가 사용 중입니다. 실제로 그렇게 사용되지는 않습니다.

스레드 수는 실행 중인 CPU의 코어 수만큼 사용할 수 있습니다.

4. 텍스트 클립 만들기

txt_clip2 = TextClip(
    txt, 
    fontsize=45, color="white", font=FONT, method='caption', stroke_color="#a8a8a8", stroke_width=2,
    size=(MAX_SIZE(0), MAX_SIZE(1)*0.1)
) 
txt_clip2 = txt_clip2.set_duration(duration)
txt_clip2 = txt_clip2.set_start(offset_start-FADE_TIME).crossfadein(FADE_TIME)
txt_clip2 = txt_clip2.set_end(offset_start+duration+FADE_TIME).crossfadeout(FADE_TIME)
txt_clip2 = txt_clip2.set_position(('center','bottom'))

텍스트(txt), 크기(글꼴 크기), 색상(색상), stroke_color, stroke_width 속성을 지정하여 텍스트 클립을 생성할 수 있습니다.

여기서 핵심은 방법입니다.

방법으로 설정할 수 있는 두 가지 옵션이 있습니다: Caption 및 Label.

caption은 캡션이고 label은 레이블(광고 텍스트)입니다.

캡션은 자막이고 가로 크기는 size 속성으로 설정하기 때문에 다음 줄로 이동할 때 텍스트가 가로 크기를 초과하면 세로 크기가 커집니다.

라벨은 이렇게 원하는 문구를 적을 때 주로 사용하며, 사이즈가 작지 않고 제작 후 치수 재어 놓을 때 사용합니다.

5. 오디오 파일 클립 출력

voice_clip.write_audiofile(export_temp_path, 44100, 2, 2000, "mp3")

오디오 파일을 출력할 때 다양한 매개 변수가 사용됩니다.

출력 파일 위치, 초당 프레임 수, 채널 수, 버퍼 크기 및 코덱을 입력합니다.

초당 프레임 수는 사람이 들을 수 있는 가청 주파수 대역에 따라 48000 또는 44100을 입력합니다.

주로 왼쪽과 오른쪽을 따로 듣고 있기 때문에 채널을 스피커로 출력되는 개수로 생각하고 2로 적어주시면 됩니다. 신호를 16비트 또는 32비트 음성으로 처리할 때 읽기 단위를 말합니다.

버퍼 크기는 2000보다 작습니다.

코덱은 일반적인 mp3로 설정되어 있습니다.

6. 이미지 클립

# 타이틀 (그림)
title_image_clip = ImageClip('./edit_video/short-title.png')
title_image_clip = title_image_clip.set_duration(OPENING_DURATION)
title_image_clip = title_image_clip.set_start(0).crossfadein(FADE_TIME)
title_image_clip = title_image_clip.set_end(OPENING_DURATION).crossfadeout(FADE_TIME)
title_image_clip_scale = 1
if title_image_clip.w < MAX_SIZE(0):
    title_image_clip_scale = MAX_SIZE(0) / title_image_clip.w
if title_image_clip.h < MAX_SIZE(1):
    temp_title_image_clip_scale = MAX_SIZE(1) / title_image_clip.h
    if title_image_clip_scale < temp_title_image_clip_scale:
        title_image_clip_scale = temp_title_image_clip_scale
title_image_clip = title_image_clip.resize(title_image_clip_scale)
title_image_clip = title_image_clip.set_position(('center','center'))

이미지 클립 생성

길이, 시작 시간, 종료 시간, 페이드 인 및 페이드 아웃을 설정하여 비디오 병합을 준비합니다.

그런 다음 이미지 크기를 최대화하기 위해 크기 조정이 적용됩니다.

그리고 이미지를 합칠 때 중심을 유지하려면 set_position을 (가로 중심, 세로 중심)으로 설정합니다.

끝.

생각보다 쉽지만 실제로 파일을 생성하고 재생하기 전까지는 디버깅이 어렵습니다.

그러나 디버깅에 많은 시간이 걸렸습니다.

그럼에도 불구하고 영상을 프로그래밍하고 편집할 수 있다는 점이 매우 매력적이었습니다.

요즘 웹상에서 paas, saas 등 동영상을 편집할 수 있는 것들이 많이 있습니다.

개발자도 서버 측에서 이와 같은 것을 개발하는지 궁금합니다.

막히면 댓글 달아주세요.

아는게 있으면 바로 답변해드리겠습니다! 아니면 함께 생각해 봅시다!

ps 이런 오류도 있습니다.

https://dalgonakit.221

Python moviepy audiofileclip 오류입니다. 소음.

Moviepy 소개 Python으로 동영상을 편집할 때 매우 유용한 moviepy라는 라이브러리가 있습니다. 비디오와 오디오를 편집하고 다양한 효과 효과를 직접 인코딩할 수 있습니다. 효과 효과

dalgonakit.tistory.com