import streamlit as st import yt_dlp import os # Streamlit 제목 st.title('유튜브 영상 다운로드') st.write("
", unsafe_allow_html=True) # 1줄 띄어쓰기 st.write("사용방법") st.write("
", unsafe_allow_html=True) # 1줄 띄어쓰기 st.write("1. 다운받으려는 유튜브 영상의 링크를 입력해주세요") st.write("2. 링크를 입력하고 확인버튼을 누르면 해당 영상의 썸네일이 등장합니다") st.write("3. 썸네일 밑의 선택란을 통해 해상도와 영상 용량을 확인한 후 원하는 해상도를 선택하고 추출 버튼을 눌러주세요") st.write("4. 잠시 후 다운받으려는 영상이 밑에 등장하고 재생하거나 다운로드 받을 수 있습니다 (영상의 용량이 클수록 추출하는데 시간이 더 걸립니다. 20분 영상 추출하는데 1분내로 소요)") # 유저로부터 유튜브 링크 입력받기 col1, col2 = st.columns([4, 1]) with col1: youtube_url = st.text_input('Enter YouTube video URL') def fetch_video_info(youtube_url): ydl_opts = { 'nocheckcertificate': True, 'cookiefile': 'cookies.txt' # 쿠키 파일 경로 } with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(youtube_url, download=False) return info_dict def get_available_formats(info_dict): formats = {} for fmt in info_dict['formats']: if fmt.get('height') and fmt.get('ext') == 'mp4': filesize = fmt.get('filesize', 0) if filesize: filesize_mb = round(filesize / (1024 * 1024), 2) resolution = f"{fmt['height']}p" formats[resolution] = { 'id': fmt['format_id'], 'info': f"{resolution} - {filesize_mb} MB" } return formats def reset_session_state(): st.session_state.pop('info_dict', None) st.session_state.pop('thumbnail_url', None) st.session_state.pop('formats', None) st.session_state.pop('youtube_url', None) st.session_state.pop('confirmed', None) st.session_state.pop('selected_format_id', None) def delete_downloaded_video(): if os.path.exists('downloaded_video.mp4'): os.remove('downloaded_video.mp4') # "확인" 버튼을 누르면 처리할 로직 if st.button('확인'): if youtube_url: try: # 기존 다운로드된 영상 삭제 delete_downloaded_video() # 세션 상태 초기화 및 URL 변경 확인 if 'youtube_url' in st.session_state and st.session_state.youtube_url != youtube_url: reset_session_state() st.session_state.youtube_url = youtube_url info_dict = fetch_video_info(youtube_url) st.session_state.info_dict = info_dict st.session_state.thumbnail_url = info_dict.get('thumbnail') st.session_state.formats = get_available_formats(info_dict) st.session_state.confirmed = True except Exception as e: st.error(f"An error occurred: {e}") else: st.warning('Please enter a valid YouTube video URL') if 'confirmed' in st.session_state and st.session_state.confirmed: st.image(st.session_state.thumbnail_url, caption='Video Thumbnail', use_column_width=True) # 해상도 선택 format_options = [value['info'] for value in st.session_state.formats.values()] format_selection = st.selectbox('Select resolution', format_options) # 선택된 해상도의 format_id 저장 st.session_state.selected_format_id = next( (value['id'] for key, value in st.session_state.formats.items() if value['info'] == format_selection), None ) def download_video(youtube_url, format_id): ydl_opts = { 'format': f"{format_id}+bestaudio/best", 'merge_output_format': 'mp4', 'outtmpl': 'downloaded_video.%(ext)s', 'nocache': True, # 캐시 비활성화 'cookiefile': 'cookies.txt' # 쿠키 파일 경로 } with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([youtube_url]) # "추출" 버튼 추가 if st.button('추출'): format_id = st.session_state.selected_format_id if format_id is None: st.error('Selected format not found.') else: try: # 세션 상태의 youtube_url 사용 download_video(st.session_state.youtube_url, format_id) st.success('Video downloaded successfully!') st.video('downloaded_video.mp4') # 다운로드된 파일 제공 (optional) with open('downloaded_video.mp4', 'rb') as file: st.download_button( label="Download Video File", data=file, file_name='downloaded_video.mp4', mime='video/mp4' ) # 추출된 영상 정보 출력 st.write(f"**제목:** {st.session_state.info_dict['title']}") st.write(f"**채널명:** {st.session_state.info_dict['uploader']}") st.write(f"**업로드 날짜:** {st.session_state.info_dict['upload_date']}") # 다운로드 후 세션 상태 리셋 reset_session_state() except Exception as e: st.error(f"An error occurred during download: {e}")