feat: Add subtitle download and VTT to SRT conversion, refactor Linkkf queue to class-level, improve video URL extraction, and introduce downloader factory.
This commit is contained in:
126
lib/downloader_factory.py
Normal file
126
lib/downloader_factory.py
Normal file
@@ -0,0 +1,126 @@
|
||||
import logging
|
||||
import os
|
||||
import traceback
|
||||
from typing import Optional, Callable, Dict, Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class BaseDownloader:
|
||||
"""Base interface for all downloaders"""
|
||||
def download(self) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def cancel(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
class FfmpegDownloader(BaseDownloader):
|
||||
"""Wrapper for SupportFfmpeg to provide a standard interface"""
|
||||
def __init__(self, support_ffmpeg_obj):
|
||||
self.obj = support_ffmpeg_obj
|
||||
|
||||
def download(self) -> bool:
|
||||
# SupportFfmpeg.start() returns data but runs in its own thread.
|
||||
# We start and then join to make it a blocking download() call.
|
||||
self.obj.start()
|
||||
if self.obj.thread:
|
||||
self.obj.thread.join()
|
||||
|
||||
# Check status from SupportFfmpeg.Status
|
||||
from support.expand.ffmpeg import SupportFfmpeg
|
||||
return self.obj.status == SupportFfmpeg.Status.COMPLETED
|
||||
|
||||
def cancel(self):
|
||||
self.obj.stop()
|
||||
|
||||
class DownloaderFactory:
|
||||
@staticmethod
|
||||
def get_downloader(
|
||||
method: str,
|
||||
video_url: str,
|
||||
output_file: str,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
callback: Optional[Callable] = None,
|
||||
proxy: Optional[str] = None,
|
||||
threads: int = 16,
|
||||
**kwargs
|
||||
) -> Optional[BaseDownloader]:
|
||||
"""
|
||||
Returns a downloader instance based on the specified method.
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Creating downloader for method: {method}")
|
||||
|
||||
if method == "cdndania":
|
||||
from .cdndania_downloader import CdndaniaDownloader
|
||||
# cdndania needs iframe_src, usually passed in headers['Referer']
|
||||
# or as a separate kwarg from the entity.
|
||||
iframe_src = kwargs.get('iframe_src')
|
||||
if not iframe_src and headers:
|
||||
iframe_src = headers.get('Referer')
|
||||
|
||||
if not iframe_src:
|
||||
iframe_src = video_url
|
||||
|
||||
return CdndaniaDownloader(
|
||||
iframe_src=iframe_src,
|
||||
output_path=output_file,
|
||||
referer_url=kwargs.get('referer_url', "https://ani.ohli24.com/"),
|
||||
callback=callback,
|
||||
proxy=proxy,
|
||||
threads=threads,
|
||||
on_download_finished=kwargs.get('on_download_finished')
|
||||
)
|
||||
|
||||
elif method == "ytdlp" or method == "aria2c":
|
||||
from .ytdlp_downloader import YtdlpDownloader
|
||||
return YtdlpDownloader(
|
||||
url=video_url,
|
||||
output_path=output_file,
|
||||
headers=headers,
|
||||
callback=callback,
|
||||
proxy=proxy,
|
||||
cookies_file=kwargs.get('cookies_file'),
|
||||
use_aria2c=(method == "aria2c"),
|
||||
threads=threads
|
||||
)
|
||||
|
||||
elif method == "hls":
|
||||
from .hls_downloader import HlsDownloader
|
||||
return HlsDownloader(
|
||||
m3u8_url=video_url,
|
||||
output_path=output_file,
|
||||
headers=headers,
|
||||
callback=callback,
|
||||
proxy=proxy
|
||||
)
|
||||
|
||||
elif method == "ffmpeg" or method == "normal":
|
||||
from support.expand.ffmpeg import SupportFfmpeg
|
||||
# SupportFfmpeg needs some global init but let's assume it's done index.py/plugin.py
|
||||
dirname = os.path.dirname(output_file)
|
||||
filename = os.path.basename(output_file)
|
||||
|
||||
# We need to pass callback_function that adapts standard callback (percent, current, total...)
|
||||
# to what SupportFfmpeg expects if necessary.
|
||||
# However, SupportFfmpeg handling is usually done via listener in ffmpeg_queue_v1.py.
|
||||
# So we might return the SupportFfmpeg object itself wrapped.
|
||||
|
||||
ffmpeg_obj = SupportFfmpeg(
|
||||
url=video_url,
|
||||
filename=filename,
|
||||
save_path=dirname,
|
||||
headers=headers,
|
||||
proxy=proxy,
|
||||
callback_id=kwargs.get('callback_id'),
|
||||
callback_function=kwargs.get('callback_function')
|
||||
)
|
||||
return FfmpegDownloader(ffmpeg_obj)
|
||||
|
||||
else:
|
||||
logger.error(f"Unknown download method: {method}")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create downloader: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return None
|
||||
Reference in New Issue
Block a user