반응형
<코드>
from pytube import YouTube #유튜브영상을 다운로드하기 위한 모듈
import os.path #경로를 설정하기 위한 모듈
import ffmpeg #미디어를 변환하기 위한 모듈
from getpass import getuser #기본 경로를 다운로드 폴더로 지정하기 위한 모듈
class Download:
'''
파일을 변환하기 위해선 ffmpeg란 프로그램을 별도로 설치해 컴퓨터 환경변수 설정을 마쳐야 함.
'''
def __init__(self, link):
#link 인자는 gui에서 입력된 값을 받을 때 사용
#컴퓨터 이용자명을 받아서 다운로드폴더를 기본폴더로 지정
self.parent_dir = f"C:\\Users\\{getuser()}\\Downloads"
self.yt = YouTube(link)
def getVideoName(self):
'''(GUI버전) 비디오 이름을 내보내는 함수'''
name = self.yt.title
return name
def downloadMp3(self):
'''mp3 파일로 다운로드하는 함수'''
#mp4형태지만 영상 없이 소리만 있는 파일 다운로드
stream = self.yt.streams.filter(only_audio=True).first()
stream.download(self.parent_dir)
src = stream.default_filename #mp4로 다운받은 영상제목(파일명과 같음)
dst = stream.default_filename[0:-3] + 'mp3' #mp3로 변환된 파일명
#mp4에서 mp3로 변환
ffmpeg.input(os.path.join(self.parent_dir, src)).output(os.path.join(self.parent_dir, dst)).run(overwrite_output=True)
#변환되기 전 mp4파일 삭제
os.remove(os.path.join(self.parent_dir, src))
return dst #저장한 파일명 리턴
def downloadMp4(self):
'''mp4 파일로 다운로드하는 함수'''
audio = self.downloadMp3() #mp3파일 다운로드
video = self.yt.streams.filter(adaptive=True, file_extension='mp4', fps = 30).first()
print(video)
video.download(self.parent_dir) #mp4파일 다운로드
#mp4로 해상도 높은 파일을 받으면 vcodec만 존재
#->비디오에 소리를 입히려면 acodec 있는 파일 받아 FFmpeg로 병합
#->downloadMp3로 mp3파일을 받고 오디오 소스로 사용
inputAudio = ffmpeg.input(os.path.join(self.parent_dir, audio))
inputVideo = ffmpeg.input(os.path.join(self.parent_dir, video.default_filename))
#영상에 소리 입혀 "new.mp4"파일로 내보내기
ffmpeg.output(inputAudio, inputVideo, os.path.join(self.parent_dir, "new.mp4"), vcodec='copy', acodec='aac').run(overwrite_output=True)
#변환이 끝나 더 이상 필요 없는 mp3, mp4 파일 지우기
os.remove(os.path.join(self.parent_dir, video.default_filename))
os.remove(os.path.join(self.parent_dir, audio))
#"new.mp4"를 영상 제목으로 바꾸기
os.rename(os.path.join(self.parent_dir, "new.mp4"), os.path.join(self.parent_dir, video.default_filename))
return video.default_filename #저장한 파일명 리턴
<pyqt5를 이용한 GUI>
import sys
from PyQt5.QtWidgets import QApplication, QTextBrowser, QWidget, QPushButton, QLineEdit, QLabel, QHBoxLayout, QVBoxLayout, QFileDialog
from YtDl import Download
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.UI()
def UI(self):
'''UI 세팅'''
#위젯 생성
self.linkInput = QLineEdit(self)
self.submitBtn = QPushButton('Submit', self)
self.fileRoute = QTextBrowser(self)
self.fileBtn = QPushButton('file...', self)
self.mp3Btn = QPushButton('mp3', self)
self.mp4Btn = QPushButton('mp4', self)
self.name = QTextBrowser(self)
self.status = QLabel(self)
#이벤트 연결
self.linkInput.returnPressed.connect(self.inputURL)
self.submitBtn.clicked.connect(self.inputURL)
self.fileBtn.clicked.connect(self.setFileRoute)
self.mp3Btn.clicked.connect(self.mp3Download)
self.mp4Btn.clicked.connect(self.mp4Download)
self.mp4Btn.clicked.connect(self.mp4Download)
#레이아웃 생성, 기본 설정
self.vbox = QVBoxLayout()
self.InputBox = QHBoxLayout()
self.fileRouteBox = QHBoxLayout()
self.titleBox = QHBoxLayout()
self.downloadbox = QHBoxLayout()
self.setLayout(self.vbox)
self.setWindowTitle('Youtube Download')
self.setGeometry(300, 300, 400, 200)
self.fileRoute.setMaximumHeight(60)
self.name.setMaximumHeight(60)
self.name.setMaximumWidth(195)
self.show()
#1: 주소 입력 박스
self.InputBox.addWidget(QLabel('동영상 주소 입력:', self))
self.InputBox.addWidget(self.linkInput)
self.InputBox.addWidget(self.submitBtn)
self.vbox.addLayout(self.InputBox)
#2: 파일 경로 박스
self.fileRouteBox.addWidget(QLabel(' 다운로드 경로: ', self))
self.fileRouteBox.addWidget(self.fileRoute)
self.fileRouteBox.addWidget(self.fileBtn)
self.vbox.addLayout(self.fileRouteBox)
#3: 영상 제목 박스
self.titleBox.addWidget(QLabel(' 영상 제목: ', self))
self.titleBox.addWidget(self.name)
self.titleBox.addStretch(1)
self.vbox.addLayout(self.titleBox)
#4: 다운로드 버튼 박스
self.downloadbox.addStretch(1)
self.downloadbox.addWidget(self.mp3Btn)
self.downloadbox.addWidget(self.mp4Btn)
self.downloadbox.addStretch(1)
self.vbox.addLayout(self.downloadbox)
self.vbox.addWidget(self.status)
#다운로드 버튼 비활성화
self.btnStatusFalse()
def btnStatusFalse(self):
'''버튼 비활성화'''
self.mp3Btn.setEnabled(False)
self.mp4Btn.setEnabled(False)
self.fileBtn.setEnabled(False)
def inputURL(self):
'''주소 입력 시 다운로드 모듈 실행,
버튼 활성화'''
self.btnStatusFalse()
self.status.setText('')
self.obj = Download(self.linkInput.text())
self.name.setText(self.obj.getVideoName())
self.fileRoute.setText(self.obj.parent_dir)
self.fileBtn.setEnabled(True)
self.mp3Btn.setEnabled(True)
self.mp4Btn.setEnabled(True)
def mp3Download(self):
'''mp3 다운로드'''
self.status.setText('downloading...')
self.obj.downloadMp3()
self.status.setText('complete!')
def mp4Download(self):
'''mp4 다운로드'''
self.status.setText('downloading...')
self.obj.downloadMp4()
self.status.setText('complete!')
def setFileRoute(self):
'''파일 다운로드 경로 지정'''
fname = QFileDialog.getExistingDirectory(self)
self.obj.parent_dir = fname
self.fileRoute.setText(self.obj.parent_dir)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
이 버전은 위젯 생성부터 모두 파이썬을 통해 실행한다. 그래서 클래스는 Qwidget을 상속받는다. 이 자체가 하나의 메인 위젯이기 때문이다.
위젯을 생성하고 배치하는 것까지 다 생각하며 하려니 상당히 감을 잡기 어려웠는데, 알고 보니 qt designer란 툴이 있었다.
이 툴을 이용해서 원하는 ui파일을 만들면 손쉽게 디자인이 가능하다.
<pyqt5를 이용한 GUI - qtdesigner 활용>
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QEventLoop, QObject, pyqtSignal
from PyQt5 import uic, QtGui
from YtDl import Download
from os import popen
#UI파일 연결
#단, UI파일은 Python 코드 파일과 같은 디렉토리에 위치해야한다.
mainUi = uic.loadUiType("project\PythonTool.ui")[0]
#화면을 띄우는데 사용되는 Class 선언
class WindowClass(QMainWindow, mainUi) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.menu3.clicked.connect(self.runMenu3)
def runMenu3(self):
Menu3(self)
class Menu3(QDialog):
def __init__(self, parent):
super(Menu3, self).__init__(parent)
menu3Ui = "project\YtDlDialog.ui"
uic.loadUi(menu3Ui, self)
self.show()
#이벤트 연결
self.adressLineEdit.returnPressed.connect(self.inputURL)
self.submitBtn.clicked.connect(self.inputURL)
self.pathBtn.clicked.connect(self.setFileRoute)
self.mp3Btn.clicked.connect(self.mp3Download)
self.mp4Btn.clicked.connect(self.mp4Download)
self.btnStatusFalse()
def btnStatusFalse(self):
'''버튼 비활성화'''
self.mp3Btn.setEnabled(False)
self.mp4Btn.setEnabled(False)
self.pathBtn.setEnabled(False)
def inputURL(self):
'''주소 입력 시 다운로드 모듈 실행,
버튼 활성화'''
self.btnStatusFalse()
self.obj = Download(self.adressLineEdit.text())
self.titleBrowser.setText(self.obj.getVideoName())
self.pathBrowser.setText(self.obj.parent_dir)
self.pathBtn.setEnabled(True)
self.mp3Btn.setEnabled(True)
self.mp4Btn.setEnabled(True)
def mp3Download(self):
'''mp3 다운로드'''
self.obj.downloadMp3()
def mp4Download(self):
'''mp4 다운로드'''
self.obj.downloadMp4()
def setFileRoute(self):
'''파일 다운로드 경로 지정'''
fname = QFileDialog.getExistingDirectory(self)
self.obj.parent_dir = fname
self.pathBrowser.setText(self.obj.parent_dir)
if __name__ == "__main__" :
#QApplication : 프로그램을 실행시켜주는 클래스
app = QApplication(sys.argv)
#WindowClass의 인스턴스 생성
myWindow = WindowClass()
#프로그램 화면을 보여주는 코드
myWindow.show()
#프로그램을 이벤트루프로 진입시키는(프로그램을 작동시키는) 코드
app.exec_()
팀 프로젝트 과제로 이 기능을 구현했는데, 여러 기능 중 하나였다.
기능을 선택하면 Qdialog를 띄워서 기능이 실행되도록 했던지라 메인 클래스는 qdialog를 상속받는다.
오직 다운로드 기능만 이용하겠다면
def run(self):
print("유튜브 동영상 링크를 입력하세요>>", end = " ")
video = input()
yt = YouTube(video)
print(yt.title)
print("mp3로 저장하려면 1, mp4로 저장하려면 2")
fileFormat = int(input())
if(fileFormat == 1): #mp3 다운로드
print("mp3로 다운로드합니다.")
fileName = self.downloadMp3(yt)
print(f"{fileName}을 다운로드했습니다.")
else: #mp4 다운로드
print("mp4로 다운로드합니다.")
fileName = self.downloadMp4(yt)
print(f"{fileName}을 다운로드했습니다.")
a = Download()
a.run()
이처럼 다운로드 클래스 내부에 run함수를 만들어 기능을 실행하면 된다.
반응형
'프로그래밍 > Python' 카테고리의 다른 글
[파이썬] str과 repr (0) | 2020.11.21 |
---|