feat: 支持全并行下载 (#1)

This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ
2023-11-22 20:45:21 +08:00
committed by GitHub
parent dfe198beca
commit 6f8b4afa1c
+30 -19
View File
@@ -7,6 +7,7 @@ import httpx
from asyncio import create_subprocess_exec from asyncio import create_subprocess_exec
from asyncio.subprocess import DEVNULL from asyncio.subprocess import DEVNULL
from loguru import logger from loguru import logger
import asyncio
async def download_content(url: str, path: Path): async def download_content(url: str, path: Path):
@@ -20,30 +21,44 @@ async def download_content(url: str, path: Path):
async def process(): async def process():
favorite_ids, tasks = [], []
for favorite_id in settings.favorite_ids: for favorite_id in settings.favorite_ids:
if favorite_id not in settings.path_mapper: if favorite_id not in settings.path_mapper:
logger.warning(f"Favorite {favorite_id} not in path mapper, ignored.") logger.warning(f"Favorite {favorite_id} not in path mapper, ignored.")
continue continue
try: favorite_ids.append(favorite_id)
tasks.append(process_favorite(favorite_id))
favorite_result = await asyncio.gather(*tasks, return_exceptions=True)
for idx, result in enumerate(favorite_result):
if isinstance(result, Exception):
logger.error("Failed to process favorite {}: {}", favorite_ids[idx], result)
continue
logger.info("Favorite {} processed successfully.", favorite_ids[idx])
async def process_favorite(favorite_id: int) -> None:
save_path = Path(settings.path_mapper[favorite_id]) save_path = Path(settings.path_mapper[favorite_id])
save_path.mkdir(parents=True, exist_ok=True) save_path.mkdir(parents=True, exist_ok=True)
favorite_video_list = await favorite_list.get_video_favorite_list_content( favorite_video_list = await favorite_list.get_video_favorite_list_content(
favorite_id, credential=credential favorite_id, credential=credential
) )
logger.info( logger.info("start to process favorite {}", favorite_video_list["info"]["title"])
"start to process favorite {}", favorite_video_list["info"]["title"] medias = favorite_video_list["medias"][:12]
) tasks = [process_video(save_path, media) for media in medias]
# TODO: video_result = await asyncio.gather(*tasks, return_exceptions=True)
# 1. 添加进度条 for idx, result in enumerate(video_result):
# 2. 翻页以下载全部内容 if isinstance(result, Exception):
# 3. 对接数据库 logger.error("Failed to process video {}: {}", medias[idx]["title"], result)
# 4. 构建 nfo
for media in favorite_video_list["medias"][:8]:
async def process_video(save_path: Path, media: dict) -> None:
title = media["title"] title = media["title"]
logger.info("start to process video {}", title)
final_path = save_path / f"{title}.mp4" final_path = save_path / f"{title}.mp4"
if final_path.exists(): if final_path.exists():
logger.info(f"{final_path} already exists, skipped.") logger.info(f"{final_path} already exists, skipped.")
continue return
v = video.Video(media["bvid"], credential=credential) v = video.Video(media["bvid"], credential=credential)
detector = video.VideoDownloadURLDataDetecter( detector = video.VideoDownloadURLDataDetecter(
await v.get_download_url(page_index=0) await v.get_download_url(page_index=0)
@@ -67,9 +82,10 @@ async def process():
save_path / f"{title}_video.m4s", save_path / f"{title}_video.m4s",
save_path / f"{title}_audio.m4s", save_path / f"{title}_audio.m4s",
) )
await download_content(streams[0].url, tmp_video_path) await asyncio.gather(
await download_content(streams[1].url, tmp_audio_path) download_content(streams[0].url, tmp_video_path),
# 混流 download_content(streams[1].url, tmp_audio_path),
)
process = await create_subprocess_exec( process = await create_subprocess_exec(
FFMPEG_COMMAND, FFMPEG_COMMAND,
"-i", "-i",
@@ -85,9 +101,4 @@ async def process():
await process.communicate() await process.communicate()
tmp_video_path.unlink() tmp_video_path.unlink()
tmp_audio_path.unlink() tmp_audio_path.unlink()
logger.info(f"{final_path} downloaded successfully.") logger.info(f"{final_path} downloaded successfully.")
except Exception:
logger.exception(f"Failed to process favorite {favorite_id}")
continue