코딩 연습

동영상 음원추출 - 파이썬 moviepy 사용

good4me 2024. 11. 7. 23:23

동영상에서 오디오 음원을 추출하고 싶을 때 파이썬 moviepy 라이브러리를 사용하니 아주 쉽게 영상 음원 추출이 가능했어요. 내 영상을 웹 사이트에 올릴 필요 없이 PC에 있는 동영상을 선택만 하면 바로 mp3로 만들어 준답니다.

 

 

동영상 음원추출

 

동영상 음원추출 파이썬 코드로 작성해서 사용하기

유튜브 동영상을 다운로드 받는 프로그램을 사용해서 영상을 받았는데, 오디오 음원 추출이 하고 싶을 때가 있습니다.

 

유튜브 영상 다운로드 프로그램 받기

 

보통은 웹 사이트에 영상을 올려서 동영상 음원 추출을 하곤 하는데, 파이썬의 movepy 라이브러리를 사용하면 간편하게 영상 음원 추출이 가능합니다.

 

이 라이브러리와 Tkinter를 사용하면 아주 간단하게 동영상 오디오 추출 프로그램을 만들 수 있습니다.

 

파이썬 moviepy 라이브러리 사용 코드

from moviepy.editor import VideoFileClip

def extract_audio_from_video(video_path, output_path):
    video_clip = VideoFileClip(video_path)
    audio_clip = video_clip.audio
    audio_clip.write_audiofile(output_path)  # 추출 audio file 저장
    audio_clip.close()

    print(f'\nAudio Saves as {output_path}')


video_path = './audio from movie/50대이상이 들으면 좋아할 노래.mp4'
output_path = './audio from movie/50대이상이 들으면 좋아할 노래.mp3'
extract_audio_from_video(video_path, output_path)

 

이 코드로 바로 동영상에서 음원 추출이 가능합니다.

 

 

 

tkinter와 함께 영상 음원 추출 코드 작성하기

파이썬 gui 라이브러리 tkinter와 같이 사용해서 코드를 작성해봤습니다.

 

import os
from tkinter import *
import tkinter.messagebox as msgbox
from tkinter import filedialog
from moviepy.editor import VideoFileClip


root = Tk()
root.title('동영상에서 오디오 추출')
root.geometry('450x400+700+100')
root.resizable(False, False)


def extract_audio_from_video(video_path, output_path):
    file_name = os.path.basename(video_path)
    file_name_without_ext = os.path.splitext(file_name)[0]  # 확장자 제거
    audio_file_name = file_name_without_ext + ".mp3"
    output_audio_path_file = os.path.join(output_path, audio_file_name)

    # 동영상 정보 가져오기
    video = VideoFileClip(video_path)
    video_size = video.size  # (width, height)
    video_duration = video.duration  # 길이(초 단위)
    video_fps = video.fps  # 프레임 레이트

    list_content_view.delete(0, END)  # 리스트박스 내 모든 item 제거
    list_content_view.insert(END, '오디오 음원 추출중입니다. 하단 "실행중..." 표시가')
    list_content_view.insert(END, '"추출 작업 완료!"로 변경될 때까지 조금만 기다리세요!')
    list_content_view.insert(END, "-------------------------------------------------------")
    list_content_view.insert(END, f'파일명 : {file_name}')
    list_content_view.insert(END, f"동영상 크기(W,H) : {video_size}")
    list_content_view.insert(END, f"동영상 길이(FPS) : {video_duration}초 ({float(video_fps):.1f} FPS)")
    list_content_view.update()

    try:
        video_clip = VideoFileClip(video_path)
        audio_clip = video_clip.audio
        audio_clip.write_audiofile(output_audio_path_file)
        # audio_clip.write_audiofile(output_audio_path_file, codec="libmp3lame")  # 오디오 파일로 저장 (MP3 코덱 지정 시) 
        audio_clip.close()
        # msgbox.showinfo('성공', f'오디오가 {output_audio_path_file}에 저장되었습니다.')
    except Exception as e:
        msgbox.showerror('오류', f'오디오 추출 중 오류가 발생했습니다: {e}')

    return True


def select_video_file():
    file_path = filedialog.askopenfilename(
        title="동영상 파일 선택", 
        filetypes=(("mp4 파일", "*.mp4"), ("모든 파일", "*.*"))
    )
    if file_path:
        txt_video_path.config(state=NORMAL)  # Entry 위젯 활성화
        txt_video_path.delete(0, END)
        txt_video_path.insert(0, file_path)
        txt_video_path.config(state=DISABLED)  # Entry 위젯 비활성화

def select_output_path():
    file_path = filedialog.askdirectory(
        title="오디오 파일 저장 경로 선택",
    )
    if file_path:
        txt_output_path.config(state=NORMAL)  # Entry 위젯 활성화
        txt_output_path.delete(0, END)
        txt_output_path.insert(0, file_path)
        txt_output_path.config(state=DISABLED)  # Entry 위젯 비활성화

def func_quit():
    # sys.exit() 
    root.quit()  # root.destroy()


# 시작 버튼
def start():
    # 영상 파일과 경로 선택 값 가져오기
    video_path = txt_video_path.get()
    output_path = txt_output_path.get()

    # 입력란이 비었는지 확인
    if not len(video_path):  # len(txt_dest_path.get()) == 0:
        msgbox.showwarning('Info', '동영상 파일을 선택해 주세요!')
        return
    if not len(output_path):  # len(txt_dest_path.get()) == 0:
        msgbox.showwarning('Info', '추출한 오디오 파일을 저장할 폴더를 선택하세요!')
        return

    if len(txt_video_path.get()) and len(txt_output_path.get()):
        state_var.set(f'실행중.....')
        root.update_idletasks()
        down_result = extract_audio_from_video(video_path, output_path)  # 함수 호출
        if down_result:
            state_var.set('추출 작업 완료..!!')
        else:
            state_var.set('중지됨..!!')
    else:
        msgbox.showerror('오류', '동영상 파일 또는 저장 경로를 다시 확인하세요!')
        return


# 사용법 표시 들어갈 공간
lbl_use_frame = Frame(root)
lbl_use_frame.pack(fill='x', padx=2, pady=2)

# 동영상 파일 선택 Frame
video_frame = LabelFrame(root, text="동영상 파일 선택")
video_frame.pack(fill="x", padx=10, pady=5, ipady=5)

# 동영상 파일 경로 레이블 및 입력란
lbl_video = Label(video_frame, text='파일 경로 :', width=10, font=('Arial', 10, 'bold'))
lbl_video.pack(side='left', padx=5, pady=5)

txt_video_path = Entry(video_frame, state=DISABLED)
txt_video_path.pack(side='left', fill='x', expand=True, padx=5, pady=5)

# 동영상 파일 선택 버튼
btn_select_video = Button(video_frame, text="파일 선택", command=select_video_file)
btn_select_video.pack(side='right', padx=5, pady=5)

# 오디오 파일 저장 경로 선택 Frame
output_frame = LabelFrame(root, text="오디오 파일 저장 경로")
output_frame.pack(fill="x", padx=10, pady=5, ipady=5)

# 오디오 파일 경로 레이블 및 입력란
lbl_output = Label(output_frame, text='저장 경로 :', width=10, font=('Arial', 10, 'bold'))
lbl_output.pack(side='left', padx=5, pady=5)

txt_output_path = Entry(output_frame, state=DISABLED)
txt_output_path.pack(side='left', fill='x', expand=True, padx=5, pady=5)

# 오디오 파일 저장 경로 선택 버튼
btn_select_output = Button(output_frame, text="경로 선택", command=select_output_path)
btn_select_output.pack(side='right', padx=5, pady=5)

# 리스트 프레임 - 데이터 추출 시 보이게 하는 Listbox 공간의 프레임
list_frame = Frame(root)
list_frame.pack(fill='both', padx=10, pady=5)

# 리스트박스 우측 스크롤
scrollbar = Scrollbar(list_frame)
scrollbar.pack(side='right', fill='y')

# 리스트박스 - 데이터 출력 현황 보이게 하는 곳
list_content_view = Listbox(list_frame, height=6, yscrollcommand=scrollbar.set)
list_content_view.pack(side='left', fill='both', expand=True)
scrollbar.config(command=list_content_view.yview)

# 프로그램 실행 표시 들어갈 공간
lbl_execute_frame = Frame(root)
lbl_execute_frame.pack(fill='x', padx=5, pady=5)

state_var = StringVar()
state_var.set(' ')
lbl_state_txt = Label(lbl_execute_frame, textvariable=state_var)
lbl_state_txt.configure(font=('Arial', 12, 'bold', 'italic'))
lbl_state_txt.pack(side='right', fill='x', padx=5, pady=5)

# 실행 프레임 - 시작, 닫기
frame_run = Frame(root)
frame_run.pack(fill='x', padx=10, pady=5)

btn_close = Button(frame_run, padx=5, pady=5, text='닫기', width=12, fg='black', cursor='hand2', command=func_quit)
btn_close.pack(side='right', padx=5, pady=5)

btn_start = Button(frame_run, padx=5, pady=5, text='추출 시작', width=12, fg='black', cursor='hand2', command=start)
btn_start.configure(font=('Arial', 10, 'bold'))
btn_start.pack(side='right', padx=5, pady=5)

root.mainloop()

 

 

동영상 mp3 추출, 동영상 오디오 추출 코드 실행 시

 

프로그램 실행 메인 화면

프로그램 실행 메인 화면

 

파일선택, 저장 폴거 경로선택
파일선택, 저장 폴거 경로선택

 

"파일선택" 버튼을 클릭하여 동영상이 있는 폴더를 선택한 후 파일을 선택하고, 추출한 오디오 음원 파일을 저장하기 위해 "경로선택" 버튼을 클릭해서 폴더를 선택합니다. 이때 파일이 있는 폴더를 그대로 선택해도 됩니다.

 

 

파일 및 저장 폴더 선택한 결과
파일 및 저장 폴더 선택한 결과

 

동영상 음원 추출을 위해서 '추출 시작' 버튼을 클릭합니다.

 

동영상 음원 추출중
동영상 음원 추출중

 

영상 음원 추출중이면 가운데 흰색 창 부분에 영상 파일명, 크기(가로,세로) , 길이(초 단위, 프레임)가 표시되고,  '실행중...'이라는 글자가 보입니다. 

 

음원 추출 완료
동영상 음원 추출 완료

 

영상 음원 추출이 완료되면 '추출 작업 완료..!' 라고 표시됩니다.

 

 

저장 폴더에 추출된 mp3 파일이 있습니다.

 

영상 음원 추출 완료
영상 음원 추출 완료

 

계속해서 mp3 음원을 추출하려면 위 절차를 반복하면 됩니다.

즉, "파일 선택" 버튼을 클릭하고 파일을 선택한 후 '추출 시작' 버튼을 클릭하면 다시 동영상 mp3 오디오 파일 추출이 시작됩니다.

 

 

 

유튜브 영상 음원 추출, 쉽게 따라하는 3가지 방법

유튜브 영상 음원 추출하여 개인 감상용으로 편집하고 싶을 때 사용하는 방법 3가지. HitPaw Edimakor, AdGuard와 y2mate 조합, 4K Video Downloader와 필모라를 활용하는 간단한 방법을 소개합니다. 각 프로그

life365.itssu.kr