jpjp9292's picture
Update app.py
4300b25 verified
# import streamlit as st
# import yt_dlp
# import os
# from pathlib import Path
# import random
# import time
# # ํŽ˜์ด์ง€ ์„ค์ •
# st.set_page_config(page_title="Simple YouTube Downloader", page_icon="๐Ÿ“บ")
# st.title("Simple YouTube Downloader ๐Ÿ“บ")
# # ์Šคํƒ€์ผ ์„ค์ •
# st.markdown("""
# <style>
# .stButton > button {
# width: 100%;
# height: 60px;
# }
# </style>
# """, unsafe_allow_html=True)
# # ๋‹ค์šด๋กœ๋“œ ํด๋” ์ƒ์„ฑ
# output_dir = Path("downloads")
# output_dir.mkdir(exist_ok=True)
# def download_video(url, progress_bar, status_text):
# try:
# user_agents = [
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15',
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0'
# ]
# ydl_opts = {
# 'format': 'best',
# 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
# 'quiet': True,
# 'no_warnings': True,
# 'cookiefile': 'youtube.com_cookies.txt',
# 'user_agent': random.choice(user_agents),
# 'referer': 'https://www.youtube.com/',
# 'http_chunk_size': random.randint(10000000, 15000000),
# 'retries': 3,
# 'sleep_interval': 3,
# 'max_sleep_interval': 8,
# 'headers': {
# 'Accept-Language': 'en-US,en;q=0.9',
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# },
# }
# def progress_hook(d):
# if d['status'] == 'downloading':
# try:
# progress = d['downloaded_bytes'] / d['total_bytes']
# progress_bar.progress(progress)
# status_text.text(f"๋‹ค์šด๋กœ๋“œ ์ค‘: {progress:.1%}")
# except:
# status_text.text("๋‹ค์šด๋กœ๋“œ ์ค‘...")
# elif d['status'] == 'finished':
# progress_bar.progress(1.0)
# status_text.text("์ฒ˜๋ฆฌ ์™„๋ฃŒ!")
# ydl_opts['progress_hooks'] = [progress_hook]
# for attempt in range(3):
# try:
# with yt_dlp.YoutubeDL(ydl_opts) as ydl:
# info = ydl.extract_info(url, download=True)
# filename = ydl.prepare_filename(info)
# return filename
# except yt_dlp.utils.ExtractorError as e:
# if "Sign in to confirm you're not a bot" in str(e):
# status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/3)")
# time.sleep(random.uniform(3, 5))
# continue
# raise e
# except Exception as e:
# if attempt < 2:
# status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/3)")
# time.sleep(2)
# continue
# raise e
# except Exception as e:
# st.error(f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
# return None
# # ์ฟ ํ‚ค ํŒŒ์ผ ์ฒดํฌ
# if not os.path.exists('youtube.com_cookies.txt'):
# st.warning("โš ๏ธ 'youtube.com_cookies.txt' ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. YouTube์— ๋กœ๊ทธ์ธ๋œ ์ฟ ํ‚ค ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
# uploaded_file = st.file_uploader("์ฟ ํ‚ค ํŒŒ์ผ ์—…๋กœ๋“œ", type=['txt'])
# if uploaded_file is not None:
# with open('youtube.com_cookies.txt', 'wb') as f:
# f.write(uploaded_file.getvalue())
# st.success("โœ… ์ฟ ํ‚ค ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
# st.rerun()
# # ๋ฉ”์ธ UI
# if 'video_url' not in st.session_state:
# st.session_state.video_url = ""
# video_url = st.text_input("YouTube URL ์ž…๋ ฅ:",
# value=st.session_state.video_url,
# placeholder="https://www.youtube.com/watch?v=...")
# # ๋ฒ„ํŠผ์„ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜
# col1, col2 = st.columns(2)
# with col1:
# download_button = st.button("๋‹ค์šด๋กœ๋“œ", type="primary", key="download_btn", use_container_width=True)
# with col2:
# reset_button = st.button("์ดˆ๊ธฐํ™”", key="reset_btn", use_container_width=True)
# # ๋‹ค์šด๋กœ๋“œ ๋กœ์ง
# if download_button:
# if video_url:
# progress_bar = st.progress(0)
# status_text = st.empty()
# downloaded_file = download_video(video_url, progress_bar, status_text)
# if downloaded_file and os.path.exists(downloaded_file):
# with open(downloaded_file, 'rb') as file:
# st.download_button(
# label="โฌ‡๏ธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ",
# data=file,
# file_name=os.path.basename(downloaded_file),
# mime="video/mp4",
# use_container_width=True
# )
# else:
# st.warning("โš ๏ธ YouTube URL์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
# # ์ดˆ๊ธฐํ™” ๋กœ์ง
# if reset_button:
# st.session_state.video_url = ""
# st.rerun()
# import streamlit as st
# import yt_dlp
# import os
# from pathlib import Path
# import random
# import time
# # ํŽ˜์ด์ง€ ์„ค์ •
# st.set_page_config(page_title="Simple YouTube Downloader", page_icon="๐Ÿ“บ")
# st.title("Simple YouTube Downloader ๐Ÿ“บ")
# # ์Šคํƒ€์ผ ์„ค์ •
# st.markdown("""
# <style>
# .stButton > button {
# width: 100%;
# height: 60px;
# }
# </style>
# """, unsafe_allow_html=True)
# # ๋‹ค์šด๋กœ๋“œ ํด๋” ์ƒ์„ฑ
# output_dir = Path("downloads")
# output_dir.mkdir(exist_ok=True)
# def download_video(url, progress_bar, status_text):
# try:
# user_agents = [
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15',
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0'
# ]
# ydl_opts = {
# 'format': 'best',
# 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
# 'quiet': True,
# 'no_warnings': True,
# 'cookiefile': 'youtube.com_cookies.txt',
# 'user_agent': random.choice(user_agents),
# 'referer': 'https://www.youtube.com/',
# 'http_chunk_size': random.randint(10000000, 15000000),
# 'retries': 5, # ์žฌ์‹œ๋„ ํšŸ์ˆ˜๋ฅผ 5๋กœ ๋Š˜๋ฆผ
# 'sleep_interval': 3,
# 'max_sleep_interval': 8,
# 'headers': {
# 'Accept-Language': 'en-US,en;q=0.9',
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# },
# }
# def progress_hook(d):
# if d['status'] == 'downloading':
# try:
# progress = d['downloaded_bytes'] / d['total_bytes']
# progress_bar.progress(progress)
# status_text.text(f"๋‹ค์šด๋กœ๋“œ ์ค‘: {progress:.1%}")
# except:
# status_text.text("๋‹ค์šด๋กœ๋“œ ์ค‘...")
# elif d['status'] == 'finished':
# progress_bar.progress(1.0)
# status_text.text("์ฒ˜๋ฆฌ ์™„๋ฃŒ!")
# ydl_opts['progress_hooks'] = [progress_hook]
# for attempt in range(5): # ์žฌ์‹œ๋„ ํšŸ์ˆ˜๋ฅผ 5๋กœ ์„ค์ •
# try:
# with yt_dlp.YoutubeDL(ydl_opts) as ydl:
# info = ydl.extract_info(url, download=True)
# filename = ydl.prepare_filename(info)
# return filename
# except yt_dlp.utils.ExtractorError as e:
# if "Sign in to confirm you're not a bot" in str(e):
# status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/5)")
# time.sleep(random.uniform(3, 5))
# continue
# status_text.text(f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
# st.error(f"๋‹ค์šด๋กœ๋“œ ์‹คํŒจ: {str(e)}") # ์‹คํŒจ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
# st.info("๋ฌธ์ œ๊ฐ€ ์ง€์†๋  ๊ฒฝ์šฐ URL์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”.") # ์ถ”๊ฐ€ ๋ฉ”๋ชจ
# return None
# except Exception as e:
# if attempt < 4:
# status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/5)")
# time.sleep(2)
# continue
# status_text.text(f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
# st.error(f"๋‹ค์šด๋กœ๋“œ ์‹คํŒจ: {str(e)}") # ์‹คํŒจ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
# st.info("๋ฌธ์ œ๊ฐ€ ์ง€์†๋  ๊ฒฝ์šฐ URL์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”.") # ์ถ”๊ฐ€ ๋ฉ”๋ชจ
# return None
# except Exception as e:
# st.error(f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
# return None
# # ์ฟ ํ‚ค ํŒŒ์ผ ์ฒดํฌ
# if not os.path.exists('youtube.com_cookies.txt'):
# st.warning("โš ๏ธ 'youtube.com_cookies.txt' ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. YouTube์— ๋กœ๊ทธ์ธ๋œ ์ฟ ํ‚ค ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
# uploaded_file = st.file_uploader("์ฟ ํ‚ค ํŒŒ์ผ ์—…๋กœ๋“œ", type=['txt'])
# if uploaded_file is not None:
# with open('youtube.com_cookies.txt', 'wb') as f:
# f.write(uploaded_file.getvalue())
# st.success("โœ… ์ฟ ํ‚ค ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
# st.rerun()
# # ๋ฉ”์ธ UI
# if 'video_url' not in st.session_state:
# st.session_state.video_url = ""
# video_url = st.text_input("YouTube URL ์ž…๋ ฅ:",
# value=st.session_state.video_url,
# placeholder="https://www.youtube.com/watch?v=...")
# # ๋ฒ„ํŠผ์„ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜
# col1, col2 = st.columns(2)
# with col1:
# download_button = st.button("๋‹ค์šด๋กœ๋“œ", type="primary", key="download_btn", use_container_width=True)
# with col2:
# reset_button = st.button("์ดˆ๊ธฐํ™”", key="reset_btn", use_container_width=True)
# # ๋‹ค์šด๋กœ๋“œ ๋กœ์ง
# if download_button:
# if video_url:
# progress_bar = st.progress(0)
# status_text = st.empty()
# downloaded_file = download_video(video_url, progress_bar, status_text)
# if downloaded_file and os.path.exists(downloaded_file):
# with open(downloaded_file, 'rb') as file:
# st.download_button(
# label="โฌ‡๏ธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ",
# data=file,
# file_name=os.path.basename(downloaded_file),
# mime="video/mp4",
# use_container_width=True
# )
# else:
# st.warning("โš ๏ธ YouTube URL์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
# # ์ดˆ๊ธฐํ™” ๋กœ์ง
# if reset_button:
# st.session_state.video_url = ""
# st.rerun()
import streamlit as st
import yt_dlp
import os
from pathlib import Path
import random
import time
import logging
# ๋กœ๊น… ์„ค์ •
logging.basicConfig(level=logging.ERROR, filename='error.log')
# ํŽ˜์ด์ง€ ์„ค์ •
st.set_page_config(page_title="Simple YouTube Downloader", page_icon="๐Ÿ“บ")
st.title("Simple YouTube Downloader ๐Ÿ“บ")
# ์Šคํƒ€์ผ ์„ค์ •
st.markdown("""
<style>
.stButton > button {
width: 100%;
height: 60px;
}
</style>
""", unsafe_allow_html=True)
# ๋‹ค์šด๋กœ๋“œ ํด๋” ์ƒ์„ฑ
output_dir = Path("downloads")
output_dir.mkdir(exist_ok=True)
def download_video(url, progress_bar, status_text):
try:
user_agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0'
]
ydl_opts = {
'format': 'best',
'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
'quiet': True,
'no_warnings': True,
'cookiefile': 'youtube.com_cookies.txt',
'user_agent': random.choice(user_agents),
'referer': 'https://www.youtube.com/',
'http_chunk_size': random.randint(100000000, 150000000),
'retries': 5, # ์žฌ์‹œ๋„ ํšŸ์ˆ˜
'sleep_interval': 4,
'max_sleep_interval': 8,
'headers': {
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
},
}
def progress_hook(d):
if d['status'] == 'downloading':
try:
progress = d['downloaded_bytes'] / d['total_bytes']
progress_bar.progress(progress)
status_text.text(f"๋‹ค์šด๋กœ๋“œ ์ค‘: {progress:.1%}")
except Exception as e:
logging.error(f"Progress Hook Error: {e}")
status_text.text("๋‹ค์šด๋กœ๋“œ ์ค‘...")
elif d['status'] == 'finished':
progress_bar.progress(1.0)
status_text.text("์ฒ˜๋ฆฌ ์™„๋ฃŒ!")
ydl_opts['progress_hooks'] = [progress_hook]
for attempt in range(5): # ์žฌ์‹œ๋„ ํšŸ์ˆ˜๋ฅผ 5๋กœ ์„ค์ •
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
return filename
except yt_dlp.utils.ExtractorError as e:
if "Sign in to confirm you're not a bot" in str(e):
status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/5)")
time.sleep(random.uniform(3, 5))
continue
logging.error(f"Extractor Error: {str(e)}")
st.info("๋ฌธ์ œ๊ฐ€ ์ง€์†๋  ๊ฒฝ์šฐ URL์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”.")
return None
except Exception as e:
logging.error(f"Download Error: {str(e)}")
if attempt < 4:
status_text.text(f"์žฌ์‹œ๋„ ์ค‘... ({attempt + 1}/5)")
time.sleep(2)
continue
st.info("๋ฌธ์ œ๊ฐ€ ์ง€์†๋  ๊ฒฝ์šฐ ๋‹ค๋ฅธ URL์„ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.")
return None
except Exception as e:
logging.error(f"General Error: {str(e)}")
st.info("๋ฌธ์ œ๊ฐ€ ์ง€์†๋  ๊ฒฝ์šฐ ๋‹ค๋ฅธ URL์„ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.")
return None
# ์ฟ ํ‚ค ํŒŒ์ผ ์ฒดํฌ
if not os.path.exists('youtube.com_cookies.txt'):
st.warning("โš ๏ธ 'youtube.com_cookies.txt' ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. YouTube์— ๋กœ๊ทธ์ธ๋œ ์ฟ ํ‚ค ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
uploaded_file = st.file_uploader("์ฟ ํ‚ค ํŒŒ์ผ ์—…๋กœ๋“œ", type=['txt'])
if uploaded_file is not None:
with open('youtube.com_cookies.txt', 'wb') as f:
f.write(uploaded_file.getvalue())
st.success("โœ… ์ฟ ํ‚ค ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
st.rerun()
# ๋ฉ”์ธ UI
if 'video_url' not in st.session_state:
st.session_state.video_url = ""
video_url = st.text_input("YouTube URL ์ž…๋ ฅ:",
value=st.session_state.video_url,
placeholder="https://www.youtube.com/watch?v=...")
# ๋ฒ„ํŠผ์„ ๊ฐ™์€ ์ค„์— ๋ฐฐ์น˜
col1, col2 = st.columns(2)
with col1:
download_button = st.button("๋‹ค์šด๋กœ๋“œ", type="primary", key="download_btn", use_container_width=True)
with col2:
reset_button = st.button("์ดˆ๊ธฐํ™”", key="reset_btn", use_container_width=True)
# ๋‹ค์šด๋กœ๋“œ ๋กœ์ง
if download_button:
if video_url:
progress_bar = st.progress(0)
status_text = st.empty()
downloaded_file = download_video(video_url, progress_bar, status_text)
if downloaded_file and os.path.exists(downloaded_file):
with open(downloaded_file, 'rb') as file:
st.download_button(
label="โฌ‡๏ธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ",
data=file,
file_name=os.path.basename(downloaded_file),
mime="video/mp4",
use_container_width=True
)
else:
st.warning("โš ๏ธ YouTube URL์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
# ์ดˆ๊ธฐํ™” ๋กœ์ง
if reset_button:
st.session_state.video_url = ""
st.rerun()