""" 유튜브 자막 가져오기
pip install youtube-transcript-api
-- 최신 버전으로 업데이트
pip install --upgrade youtube-transcript-api
https://www.youtube.com/watch?v=XyljmT8dGA4
자막있는 동영상 : https://www.youtube.com/watch?v=zRz9q8dPjC4
"""
from youtube_transcript_api import YouTubeTranscriptApi
# youtube_transcript_api._errors 에서 TooManyRequests를 제외하고 임포트합니다.
# TooManyRequests는 더 이상 직접 임포트할 수 없는 것으로 보입니다.
from youtube_transcript_api._errors import NoTranscriptFound, TranscriptsDisabled, VideoUnavailable
def get_youtube_transcript(video_id, languages=['ko', 'en']):
"""
주어진 YouTube 동영상 ID와 언어 목록에 대해 자막을 가져옵니다.
자동 생성 자막과 공식 자막을 모두 시도합니다.
"""
try:
# 우선 공식 자막을 시도
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
# 사용 가능한 언어 목록에서 요청한 언어 중 하나를 찾아 가져옵니다.
chosen_transcript = None
for lang_code in languages:
for transcript in transcript_list:
if transcript.language_code == lang_code:
chosen_transcript = transcript
break
if chosen_transcript:
break
if chosen_transcript:
print(f"[{video_id}] {chosen_transcript.language} ({chosen_transcript.language_code}) 자막을 가져옵니다.")
# fetch()는 이제 FetchedTranscript 객체를 반환하며, 이는 이터러블합니다.
transcript_segments = chosen_transcript.fetch()
return transcript_segments
else:
raise NoTranscriptFound(
f"No suitable official transcript found for video {video_id} in languages {languages}.",
video_id
)
except NoTranscriptFound:
print(f"[{video_id}] 공식 자막을 찾을 수 없습니다. 자동 생성 자막을 시도합니다.")
try:
for lang_code in languages:
try:
# get_transcript() 역시 이터러블한 객체를 반환하는 것으로 가정합니다.
transcript_segments = YouTubeTranscriptApi.get_transcript(video_id, languages=[lang_code], preserve_formatting=True)
print(f"[{video_id}] {lang_code} 자동 생성 자막을 가져왔습니다.")
return transcript_segments
except NoTranscriptFound:
continue # 다음 언어로 시도
print(f"[{video_id}] 요청된 언어 ({languages})로 자동 생성 자막도 찾을 수 없습니다.")
return None # 적합한 자막을 찾지 못함
except TranscriptsDisabled:
print(f"[{video_id}] 이 동영상은 자막이 비활성화되어 있습니다.")
return None
except VideoUnavailable:
print(f"[{video_id}] 동영상을 사용할 수 없거나 비공개/삭제되었습니다.")
return None
except Exception as e: # TooManyRequests를 포함한 모든 예외를 잡습니다.
# 이 부분에서 TooManyRequests 에러를 포함하여 일반적인 오류를 처리합니다.
print(f"[{video_id}] 자막을 가져오는 중 예기치 않은 오류가 발생했습니다: {e}")
return None
except TranscriptsDisabled:
print(f"[{video_id}] 이 동영상은 자막이 비활성화되어 있습니다.")
return None
except VideoUnavailable:
print(f"[{video_id}] 동영상을 사용할 수 없거나 비공개/삭제되었습니다.")
return None
except Exception as e: # TooManyRequests를 포함한 모든 예외를 잡습니다.
# 이 부분에서 TooManyRequests 에러를 포함하여 일반적인 오류를 처리합니다.
print(f"[{video_id}] 자막을 가져오는 중 예기치 않은 오류가 발생했습니다: {e}")
return None
if __name__ == "__main__":
# 예시 동영상 ID (실제 존재하는 동영상 ID로 변경해야 합니다)
# 제가 추천해 드렸던 URL에서 ID를 추출했습니다.
video_id_with_subtitle = "XyljmT8dGA4" # "모바일 유튜브 자동번역 한글자막 보는 방법"
video_id_auto_caption = "XyljmT8dGA4" # 짧은 영상 (자동 생성 자막 가능성)
#video_id_invalid = "invalid_video_id_123"
video_id_invalid = "XyljmT8dGA4"
print("--- 예제 1: 자막이 있는 동영상 ---")
transcript_data = get_youtube_transcript(video_id_with_subtitle, languages=['ko', 'en'])
if transcript_data:
# segment.start, segment.duration, segment.text와 같이 속성으로 접근합니다.
for i, segment in enumerate(transcript_data[:5]): # 슬라이싱은 여전히 가능해야 합니다.
print(f"[{segment.start:.2f}-{segment.start + segment.duration:.2f}] {segment.text}")
print(f"... (총 {len(list(transcript_data))}개 세그먼트)") # len()을 위해 list로 변환
# 전체 자막 텍스트만 추출하고 싶다면:
full_text = " ".join([segment.text for segment in transcript_data])
print("\n--- 전체 자막 텍스트 (예제 1) ---")
print(full_text[:500] + "...")
else:
print("자막을 가져오지 못했습니다.")
print("\n--- 예제 2: 자동 생성 자막을 시도할 수 있는 동영상 ---")
transcript_data_auto = get_youtube_transcript(video_id_auto_caption, languages=['en', 'ko'])
if transcript_data_auto:
for i, segment in enumerate(transcript_data_auto[:5]):
print(f"[{segment.start:.2f}-{segment.start + segment.duration:.2f}] {segment.text}")
print(f"... (총 {len(list(transcript_data_auto))}개 세그먼트)")
else:
print("자막을 가져오지 못했습니다.")
print("\n--- 예제 3: 존재하지 않는 동영상 ID ---")
transcript_data_invalid = get_youtube_transcript(video_id_invalid)
if transcript_data_invalid:
print("자막을 가져왔습니다.")
else:
print("자막을 가져오지 못했습니다.")
"이 기분을 잊지 말렴. 네가 태어난 건 정말 기적같은 일이란 걸 한시도 잊지 말거라. 그리고 네가 태어나서 온 세상이 기뻐하고 있다는 것도 꼭 기억해! 매일 살아 있음이 얼마나 놀라운 일인지, 모든 곳에 친척과 친구가 있음이 얼마나 놀라운 일인지, 네가 꼭 알기를 바란다. 인간, 동물, 식물, 돌도 다 우리의 친구란다. 이제 알겠니? 진정한 마법이 무엇인지?
- 디르크 그로서, 제니 아펠의《너는 절대 혼자가 아니야》중에서 -
* 친구 하나를 얻는 것도 마법 같은 일입니다. 하물며 한 생명이 탄생한다는 것은 그 자체만으로 마법입니다. 또 하나의 작은 우주가 태어난다는 뜻이니까요. 자연물도 같습니다. '꽃을 한 송이 꺾으면 지구가 전율한다'는 시구는 과장된 표현이 아닙니다. 한 알의 모래알에서 우주를 보고 영원을 읽어야 합니다. 모든 것은 친구처럼 더불어 살아가며, 더불어 기뻐합니다.
잊지 마렴, 네가 태어난 건 기적이야!
"이 기분을 잊지 말렴. 네가 태어난 건 정말 기적 같은 일이란 걸 한시도 잊지 말거라. 그리고 네가 태어나서 온 세상이 기뻐하고 있다는 것도 꼭 기억해!"
이 아름다운 문장은 디르크 그로서와 제니 아펠의 《너는 절대 혼자가 아니야》에 나오는 구절입니다. 우리는 이 세상에 태어난 순간부터 이미 기적 그 자체였습니다. 우리가 존재한다는 것만으로 온 세상이 기뻐하고 있다는 사실, 늘 기억해야 할 소중한 진실이죠.
살아있음의 놀라운 마법
매일 숨 쉬며 살아간다는 것, 그 자체로 얼마나 놀라운 일인가요? 우리 주변에 있는 가족, 친구들과 함께한다는 것은 또 얼마나 감사한 일인가요. 인간뿐만 아니라 동물, 식물, 심지어 길가의 돌멩이 하나까지도 모두 우리의 친구입니다. 이 모든 존재와 더불어 살아가는 것이 바로 진정한 마법이 아닐까요?
작고 사소한 것에서 우주를 보다
친구 한 명을 얻는 것조차 마법 같은 일인데, 한 생명이 탄생한다는 것은 그야말로 우주가 새로 생겨나는 것과 같습니다. 이렇듯 자연의 모든 것도 마찬가지입니다. **'꽃을 한 송이 꺾으면 지구가 전율한다'**는 시구는 결코 과장된 표현이 아닙니다.
우리는 한 알의 모래알에서 우주를 보고 영원을 읽을 수 있어야 합니다. 모든 존재는 서로 친구처럼 더불어 살아가며, 함께 기뻐하는 놀라운 연결고리를 가지고 있습니다. 작은 것 하나에서도 큰 의미를 발견하는 삶, 그것이 바로 우리가 누릴 수 있는 가장 큰 행복일 것입니다.