파이썬 활용한 유튜브 동영상 업로드

유튜브에 동영상을 업로드하는 작업을 자동화할 수 있다면, 콘텐츠 크리에이터로서 시간을 크게 절약할 수 있을 것입니다. 이 블로그에서는 제가 직접 경험한 파이썬을 활용한 유튜브 동영상 업로드 방법을 자세히 설명합니다. 처음 이 작업을 시도할 때는 몇 가지 어려움이 있었지만, 반복적인 실습을 통해 완벽히 익히게 되었습니다. 이 글을 통해 여러분도 손쉽게 유튜브 API를 이용해 동영상을 업로드할 수 있기를 바랍니다.

파이썬 활용한 유튜브 동영상 업로드

1. Google Cloud Console 유튜브 API 활성화

1.1 프로젝트 생성

유튜브 API를 사용하려면 먼저 Google Cloud Console에서 프로젝트를 생성해야 합니다. 저도 처음 이 작업을 할 때는 어디서부터 시작해야 할지 막막했지만, 프로젝트 생성 가이드를 참고하여 차근차근 해결할 수 있었습니다.

먼저, Google Cloud Console에 접속하여 새로운 프로젝트를 만듭니다. 프로젝트 이름은 "YouTube API 프로젝트"로 지정했습니다. 프로젝트 이름은 후에 쉽게 찾을 수 있도록 의미 있는 이름으로 설정하는 것이 좋습니다.

1.2 유튜브 API 활성화

프로젝트를 생성한 후, 라이브러리(Library) 섹션으로 이동하여 YouTube Data API v3를 활성화합니다. 이 단계는 매우 중요합니다. API를 활성화하지 않으면, 이후의 모든 작업이 제대로 진행되지 않기 때문입니다.

처음에는 API를 찾는 과정이 다소 혼란스러울 수 있지만, 'YouTube'라는 키워드로 검색하여 YouTube Data API v3를 찾아 Enable 버튼을 클릭하면 간단하게 설정할 수 있습니다.

YouTube Data API v3


2. OAuth 2.0 클라이언트 설정 및 인증서 생성

2.1 OAuth 2.0 클라이언트 생성

API를 활성화한 후, 유튜브 계정에 접근하기 위해서는 OAuth 2.0 인증이 필요합니다. 이 과정에서 조금 헷갈릴 수 있지만, OAuth 2.0 가이드를 참고하여 차근차근 따라가면 어렵지 않게 진행할 수 있습니다.

Credentials 섹션에서 Create Credentials를 클릭한 후, OAuth 클라이언트 ID를 생성합니다. 이때 애플리케이션 유형으로 Desktop App을 선택합니다. 이 과정에서 생성한 클라이언트 ID는 이후 동영상 업로드 과정에서 중요한 역할을 합니다.

2.2 인증서 다운로드 및 설정

생성된 클라이언트 ID는 JSON 파일로 다운로드됩니다. 이 파일을 프로젝트 폴더에 추가해야 하며, 저는 파일명을 client_secret.json으로 변경하여 저장했습니다. 이 파일을 통해 파이썬 코드가 유튜브 API에 접근할 수 있게 됩니다.

이 파일을 올바르게 설정하지 않으면, API에 접근할 수 없기 때문에 꼭 프로젝트 디렉토리에 올바르게 저장해야 합니다. 개인적으로 이 부분에서 실수를 몇 번 했었지만, 이름과 경로를 정확하게 확인한 후 문제를 해결할 수 있었습니다.

3. 파이썬 코드를 이용한 동영상 업로드

3.1 코드 구조 설명

이제 API를 사용하여 유튜브에 동영상을 업로드하는 파이썬 코드를 작성할 차례입니다. 처음에는 코드 작성이 다소 복잡하게 느껴졌지만, 전체적인 흐름을 이해하면 YouTube Data API v3 문서를 참고하여 어렵지 않게 따라 할 수 있습니다.

기본적인 코드 구조는 다음과 같습니다.

  • 인증서 불러오기: JSON 파일을 불러와 유튜브 API에 접근할 수 있는 자격 증명을 얻습니다.
  • API 서비스 생성: 자격 증명을 바탕으로 유튜브 API 서비스를 생성합니다.
  • 동영상 업로드 함수: 동영상을 업로드하는 함수를 작성하고, 업로드할 파일 경로를 지정합니다.

3.2 동영상 업로드 과정

코드를 작성한 후, 업로드하려는 동영상 파일의 경로를 지정합니다. 개인적으로 이 부분에서 경로 설정에 실수가 있었습니다. 파일 경로를 정확하게 설정하지 않으면 API가 파일을 찾지 못하므로, 경로 설정에 주의해야 합니다.

코드가 실행되면 API를 통해 동영상이 유튜브에 업로드됩니다. 업로드 상태는 콘솔에 출력되며, 성공적으로 업로드되었는지 확인할 수 있습니다. 저의 경우, 초기 시도에서는 오류가 발생했지만, 오류 메시지를 바탕으로 문제를 해결하고 최종적으로 성공할 수 있었습니다.

3.3 유튜브 업로드 파이썬 코드 

#googleapiclient #패키지 설치
#oauth2client
#httplib2
#pytz
import os
import sys
import httplib2
import gdown  # Google Drive에서 파일을 다운로드하기 위한 모듈
from tkinter import Tk, filedialog  # 파일 선택 대화 상자를 사용하기 위한 Tkinter 모듈
from oauth2client.client import flow_from_clientsecrets  # OAuth 2.0 클라이언트 흐름을 위한 모듈
from oauth2client.file import Storage  # 자격 증명을 파일로 저장/불러오기 위한 모듈
from oauth2client.tools import run_flow  # OAuth 2.0 인증 흐름 실행을 위한 도구
from googleapiclient import discovery  # Google API 서비스 객체 생성을 위한 모듈
from googleapiclient.http import MediaFileUpload  # 파일 업로드를 처리하기 위한 모듈
from googleapiclient.errors import HttpError  # API 호출 중 발생할 수 있는 에러 처리 모듈
import pytz  # 시간대 처리를 위한 모듈
from datetime import datetime, timedelta  # 날짜와 시간을 처리하기 위한 모듈

# 현재 작업 디렉토리 설정: 실행 파일이 있는 경로를 기준으로 설정
if getattr(sys, 'frozen', False):
    # EXE로 패키징된 경우
    work_dir = os.path.dirname(sys.executable)
else:
    # 스크립트로 실행되는 경우
    work_dir = os.path.dirname(os.path.abspath(__file__))

# 경로를 표준화하여 Windows와 Unix 계열 OS 모두에서 사용할 수 있도록 함
work_dir = work_dir.replace('\\', '/')
if not work_dir.endswith('/'):
    work_dir += '/'

# 작업 디렉토리 경로를 출력하여 확인
print(f"Recognized work directory: {work_dir}")

# 현재 디렉토리에서 JSON 파일 목록을 가져옴
json_files = [file for file in os.listdir(work_dir) if file.endswith('.json')]
print(f"JSON files found: {json_files}")

# OAuth 2.0 클라이언트 시크릿 파일 선택
client_secrets_file = None
for file in json_files:
    if file.startswith("client_secret"):
        client_secrets_file = os.path.join(work_dir, file)
        break

# 선택된 클라이언트 시크릿 파일 출력
if client_secrets_file:
    print(f"Using client secret file: {client_secrets_file}")
else:
    # 클라이언트 시크릿 파일이 없으면 예외 발생
    raise FileNotFoundError("OAuth 클라이언트 JSON 파일을 찾을 수 없습니다. 'client_secret'으로 시작하는 파일을 디렉토리에 두십시오.")

# 클라이언트 시크릿 파일이 실제로 존재하는지 확인
if not os.path.exists(client_secrets_file):
    raise FileNotFoundError(f"Client secret file not found: {client_secrets_file}")

def getScheduleDateTime(days=0):
    """
    동영상 게시 시간을 설정하는 함수

    Args:
        days (int): 현재 날짜로부터 며칠 후에 게시할지 지정 (기본값 0은 오늘)

    Returns:
        str: UTC 시간대의 ISO 8601 형식의 문자열
    """
    # 미국 로스앤젤레스 시간대를 설정
    eastern_tz = pytz.timezone('America/Los_Angeles')
    # 현재 시간을 해당 시간대로 설정
    publish_time = datetime.now(eastern_tz)

    # days 값이 0보다 크면 해당 일수를 추가
    if days > 0:
        publish_time = datetime.now(eastern_tz) + timedelta(days)

    # 시간을 오후 2시로 설정 (14:00:00)
    publish_time = publish_time.replace(hour=14, minute=0, second=0, microsecond=0)
    # UTC 시간대로 변환하여 반환
    publish_time_utc = publish_time.astimezone(pytz.utc).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
    return publish_time_utc

def authorize_credentials():
    """
    OAuth 2.0 인증을 통해 Google API에 접근할 자격 증명을 얻는 함수

    Returns:
        Credentials: 인증된 자격 증명 객체
    """
    SCOPE = 'https://www.googleapis.com/auth/youtube'  # YouTube API 접근 범위 설정
    STORAGE = Storage(os.path.join(work_dir, 'credentials.storage'))  # 자격 증명을 저장할 위치 설정

    credentials = STORAGE.get()  # 저장된 자격 증명 가져오기

    if credentials is None or credentials.invalid:
        # 자격 증명이 없거나 유효하지 않다면 OAuth 2.0 흐름을 실행하여 새로운 자격 증명 생성
        flow = flow_from_clientsecrets(client_secrets_file, scope=SCOPE)
        http = httplib2.Http()
        credentials = run_flow(flow, STORAGE, http=http)  # 인증 후 자격 증명 저장

    return credentials

def getYoutubeService():
    """
    YouTube API에 접근하기 위한 서비스 객체를 생성하는 함수

    Returns:
        Resource: YouTube API 서비스 객체
    """
    credentials = authorize_credentials()  # 자격 증명 획득
    http = credentials.authorize(httplib2.Http())  # 자격 증명으로 HTTP 객체 생성
    discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest'  # YouTube API URL
    service = discovery.build('youtube', 'v3', http=http, discoveryServiceUrl=discoveryUrl)  # YouTube 서비스 객체 생성
    return service

def upload_video(file_path, title, description='', tags=[], privacy_status='public', day=0):
    """
    동영상을 YouTube에 업로드하는 함수

    Args:
        file_path (str): 업로드할 동영상 파일의 경로
        title (str): 동영상의 제목
        description (str, optional): 동영상 설명 (기본값은 빈 문자열)
        tags (list, optional): 동영상에 추가할 태그 목록 (기본값은 빈 리스트)
        privacy_status (str, optional): 동영상의 공개 상태 ('public', 'private', 'unlisted')
        day (int, optional): 동영상을 예약할 일 수 (기본값은 0)

    Raises:
        Exception: HTTP 에러가 발생했을 때 예외 발생
    """
    print("Uploading...")  # 업로드 진행 상황 출력

    youtube = getYoutubeService()  # YouTube API 서비스 객체 생성

    try:
        # 동영상 업로드를 위한 메타데이터 설정
        body = {
            'snippet': {
                'title': title,  # 동영상 제목
                'description': description,  # 동영상 설명
                'tags': tags,  # 태그
            },
            'status': {
                'privacyStatus': privacy_status  # 공개 상태 설정
            }
        }

        # 동영상이 비공개 상태일 경우, 게시 시간을 예약
        if privacy_status == 'private':
            body['status']['publishAt'] = getScheduleDateTime(day)

        # 동영상 파일을 업로드할 수 있도록 MediaFileUpload 객체 생성
        media_file = MediaFileUpload(file_path)

        # YouTube API의 videos.insert 메서드를 호출하여 동영상 업로드
        videos = youtube.videos()
        response = videos.insert(
            part='snippet,status',
            body=body,
            media_body=media_file
        ).execute()

        # 업로드 완료 후 결과 출력
        print('Video uploaded successfully!\n')
        print(f'Title: {response["snippet"]["title"]}')
        print(f'URL: https://www.youtube.com/watch?v={response["id"]}')

    except HttpError as e:
        # HTTP 에러가 발생할 경우 예외 처리
        raise Exception(f"An HTTP error {e.resp.status} occurred: {e.content.decode('utf-8')}")

# Tkinter를 사용하여 파일 선택 대화상자 열기
def select_video_file():
    """
    사용자가 업로드할 동영상 파일을 선택하도록 파일 선택 대화상자를 띄우는 함수

    Returns:
        str: 선택된 동영상 파일의 경로
    """
    root = Tk()
    root.withdraw()  # Tkinter 기본 창 숨기기
    file_path = filedialog.askopenfilename(
        initialdir=work_dir,  # 초기 디렉토리 설정
        title="Select video file",  # 대화상자 제목
        filetypes=(("MP4 files", "*.mp4"), ("All files", "*.*"))  # 선택 가능한 파일 형식
    )
    return file_path

# 동영상 파일을 선택하여 YouTube에 업로드
video_file_path = select_video_file()
if video_file_path:
    # 파일이 정상적으로 선택된 경우, 업로드 함수 호출
    upload_video(video_file_path, title='유튜브 제목', description='유튜브 정보', tags=['유튜브 테그'], privacy_status='public')
else:
    # 파일이 선택되지 않은 경우 메시지 출력
    print("No video file was selected.")

4. 결과 확인 및 오류 처리

4.1 업로드 상태 확인

동영상이 성공적으로 업로드되었는지 확인하려면, 유튜브 채널을 새로고침하여 업로드된 동영상이 있는지 확인합니다. 코드 내에서 업로드 결과를 출력하거나, 유튜브 URL을 통해 직접 확인할 수 있습니다. 유튜브 업로드 확인 방법도 참고하세요.

저도 첫 업로드 시도에서 결과 확인을 통해 작은 실수를 발견하고 수정할 수 있었습니다. 이를 통해 모든 작업이 잘 이루어졌음을 확인할 수 있었습니다.

4.2 오류 처리

업로드 과정에서 발생할 수 있는 오류는 코드 내에서 적절히 처리해야 합니다. 예를 들어, 잘못된 파일 경로나 권한 문제로 인해 업로드가 실패할 수 있으며, 이러한 경우 오류 메시지를 출력하고 문제를 해결합니다.

저는 처음에 파일 경로 설정에서 문제가 있었지만, 이를 수정한 후 오류를 해결할 수 있었습니다. 또한, API 사용 중에 발생하는 다양한 문제들을 해결하며, 전체 프로세스를 더 깊이 이해하게 되었습니다. Stack Overflow에서 유튜브 API 관련 문제 해결도 많은 도움이 됩니다.

5. 결론: 파이썬과 유튜브 API를 통한 동영상 업로드 자동화

이 글에서는 파이썬을 활용해 유튜브 동영상을 업로드하는 방법을 실습과 함께 상세히 설명했습니다. 처음에는 다소 복잡해 보일 수 있지만, 각 단계를 따라가다 보면 생각보다 쉽게 작업을 수행할 수 있습니다.

유튜브 API를 활용해 동영상 업로드를 자동화하면, 매번 수작업으로 동영상을 업로드하는 번거로움을 덜 수 있습니다. 저 역시 이 방법을 통해 콘텐츠 제작 시간을 크게 절약할 수 있었으며, 여러분도 이 과정을 통해 자동화의 이점을 경험해보시기 바랍니다.

추가적으로, 유튜브 API에 대한 최신 정보나 파이썬 관련 문제 해결 방법을 지속적으로 탐색하고 학습하는 것이 중요합니다. Google Cloud 및 YouTube API의 공식 문서 외에도, Reddit의 파이썬 학습 커뮤니티와 같은 다양한 온라인 커뮤니티에서 다른 개발자들과 소통하며 최신 정보를 얻을 수 있습니다.

추가 자료 및 참고 링크

이처럼 유용한 자료들을 통해 학습을 계속하고, 실습을 반복함으로써 더욱 깊이 있는 지식을 쌓을 수 있습니다. 이 글이 여러분의 유튜브 API 활용 및 동영상 업로드 자동화에 도움이 되길 바랍니다. 성공적인 프로젝트 진행을 기원합니다!

  • 카카오톡 메시지

댓글 쓰기

다음 이전