feat: Add reusable video modal component with Alist-style UI

This commit is contained in:
2026-01-04 15:36:52 +09:00
parent 4c20f96cef
commit 150a3a9fb0
19 changed files with 859 additions and 215 deletions

View File

@@ -223,11 +223,28 @@ class FfmpegQueue(object):
# 다운로드 방법 확인
download_method = P.ModelSetting.get(f"{self.name}_download_method")
# .ytdl 파일이 있거나, ytdlp/aria2c 모드인 경우 '파일 있음'으로 건너뛰지 않음 (이어받기 허용)
# 미완성 다운로드 감지 (Frag 파일, .ytdl 파일, .part 파일)
# 이런 파일이 있으면 이어받기 허용
is_ytdlp = download_method in ['ytdlp', 'aria2c']
has_ytdl_file = os.path.exists(filepath + ".ytdl")
has_part_file = os.path.exists(filepath + ".part")
if os.path.exists(filepath) and not (is_ytdlp or has_ytdl_file):
# Frag 파일 존재 여부 확인 (같은 폴더에 Frag* 파일이 있으면 미완성)
has_frag_files = False
try:
import glob
dirname = os.path.dirname(filepath)
if dirname and os.path.exists(dirname):
frag_pattern = os.path.join(dirname, "*Frag*")
has_frag_files = len(glob.glob(frag_pattern)) > 0
if has_frag_files:
logger.info(f"[Resume] Found Frag files in {dirname}, allowing re-download")
except Exception as e:
logger.debug(f"Frag check error: {e}")
is_incomplete = has_ytdl_file or has_part_file or has_frag_files
if os.path.exists(filepath) and not (is_ytdlp or is_incomplete):
logger.info(f"File already exists: {filepath}")
entity.ffmpeg_status = 8 # COMPLETED_EXIST
entity.ffmpeg_status_kor = "파일 있음"
@@ -589,8 +606,22 @@ class FfmpegQueue(object):
ret["ret"] = "refresh"
elif cmd == "reset":
if self.download_queue is not None:
with self.download_queue.mutex:
self.download_queue.queue.clear()
# 큐 비우기 (표준 Queue와 gevent Queue 모두 호환)
try:
# 표준 Queue의 경우
if hasattr(self.download_queue, 'mutex'):
with self.download_queue.mutex:
self.download_queue.queue.clear()
else:
# gevent Queue의 경우 - 하나씩 꺼내서 비우기
while not self.download_queue.empty():
try:
self.download_queue.get_nowait()
except:
break
except Exception as e:
logger.debug(f"Queue clear error (non-critical): {e}")
for _ in self.entity_list:
# 다운로드중 상태인 경우에만 중지 시도
if _.ffmpeg_status == 5:

View File

@@ -172,17 +172,11 @@ class YtdlpDownloader:
# 주의: --external-downloader aria2c는 HLS 프래그먼트에서 오버헤드가 크므로 제거함
# 1.5 환경별 브라우저 위장 설정 (Impersonate)
# macOS에서는 고급 위장 기능을 사용하되, 종속성 문제가 잦은 Linux/Docker에서는 UA 수동 지정
is_mac = platform.system() == 'Darwin'
if is_mac:
cmd += ['--impersonate', 'chrome-120']
logger.debug("Using yt-dlp --impersonate chrome-120 (macOS detected)")
else:
# Docker/Linux: impersonate 라이브러리 부재 가능하므로 UA 수동 설정
user_agent = self.headers.get('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
cmd += ['--user-agent', user_agent]
logger.debug(f"Using manual User-Agent on {platform.system()}: {user_agent}")
# 1.5 브라우저 위장 설정 (User-Agent)
# --impersonate 옵션은 curl-impersonate 라이브러리가 필요하므로 수동 UA 사용
user_agent = self.headers.get('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
cmd += ['--user-agent', user_agent]
logger.debug(f"Using manual User-Agent: {user_agent}")
# 2. 프록시 설정
if self.proxy:
@@ -342,10 +336,14 @@ class YtdlpDownloader:
elapsed = time.time() - self.start_time
self.elapsed_time = self.format_time(elapsed)
# [최적화] 진행률이 1% 이상 차이나거나, 100%인 경우에만 콜백 호출 (로그 부하 감소)
# [최적화] 10% 단위로만 로그 출력 (로그 부하 감소)
if self.callback and (int(new_percent) > int(self.percent) or new_percent >= 100):
old_tens = int(self.percent) // 10
new_tens = int(new_percent) // 10
self.percent = new_percent
logger.info(f"[yt-dlp progress] {int(self.percent)}% speed={self.current_speed}")
# 10% 단위가 변경되었거나 100%일 때만 로그 출력
if new_tens > old_tens or new_percent >= 100:
logger.info(f"[yt-dlp] {int(self.percent)}% speed={self.current_speed}")
self.callback(percent=int(self.percent), current=int(self.percent), total=100, speed=self.current_speed, elapsed=self.elapsed_time)
else:
self.percent = new_percent