diff --git a/app/__init__.py b/app/__init__.py index 807e025..0ebc639 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,4 +1,4 @@ -# from app.main import app +from app.main import app -# __all__ = ["app"] +__all__ = ["app"] diff --git a/app/api/v1/endpoints/youtube.py b/app/api/v1/endpoints/youtube.py new file mode 100644 index 0000000..285aabd --- /dev/null +++ b/app/api/v1/endpoints/youtube.py @@ -0,0 +1,12 @@ +from fastapi import APIRouter +from app.services import YouTubeService +from app.schemas import DownloadResponse +from app.schemas import DownloadRequest + +router = APIRouter() + + +@router.post("/", response_model=DownloadResponse) +async def download_video(data: DownloadRequest): + response_data = YouTubeService.download(data) + return response_data diff --git a/app/api/v1/router.py b/app/api/v1/router.py index e69de29..0b3eb7d 100644 --- a/app/api/v1/router.py +++ b/app/api/v1/router.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter +from app.api.v1.endpoints import youtube + + +router = APIRouter() + + +router.include_router(youtube.router, prefix="/youtube", tags=["YouTube"]) diff --git a/app/main.py b/app/main.py index 818629b..11098cd 100644 --- a/app/main.py +++ b/app/main.py @@ -1,25 +1,11 @@ -from app.utils.downloader import HttpStreamingDownloader -from app.utils.uploader import DiskChunkUploadBackend -from app.utils.youtube import YtDlpInfo +from fastapi import FastAPI +from app.api.v1.router import router as v1_router + +app = FastAPI() + +app.include_router(v1_router, prefix="/api/v1") -def download(url: str): - upload_backend = DiskChunkUploadBackend("trash_holder") - downloader = HttpStreamingDownloader(upload_backend) - youtube = YtDlpInfo(url) - video_url = youtube.get_video_url("480p") - video_name = youtube.title + ".mp4" - audio_url = youtube.get_audio_url() - audio_name = youtube.title + ".mp4a" - - # downloader.download(video_url, video_name) - downloader.download(audio_url, audio_name) - - -def main(): - url = "https://youtu.be/OSAOh4L41Wg" - download(url) - - -if __name__ == "__main__": - main() +@app.get("/ping") +async def ping() -> str: + return "Pong" diff --git a/app/schemas.py b/app/schemas.py index 0d8ebdb..56edd73 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -3,6 +3,9 @@ from pydantic import BaseModel class DownloadRequest(BaseModel): url: str - quality: str - codec: str - identifier: str + quality: int + + +class DownloadResponse(BaseModel): + video: str + audio: str diff --git a/app/services.py b/app/services.py index e69de29..329290d 100644 --- a/app/services.py +++ b/app/services.py @@ -0,0 +1,13 @@ +from app.utils.youtube import YtDlpManager +from app.utils.uploader import S3ChunkUploadBackend +from app.schemas import DownloadRequest, DownloadResponse + +class YouTubeService: + @staticmethod + def download(data: DownloadRequest): + key_prefix = f"{data.url}@{data.quality}@" + s3 = S3ChunkUploadBackend(key_prefix) + manager = YtDlpManager(data.url, s3) + video_url = manager.download_video(data.quality) + audio_url = manager.download_audio() + return DownloadResponse(video=video_url, audio=audio_url) diff --git a/app/utils/uploader.py b/app/utils/uploader.py index 9f4a070..0dea822 100644 --- a/app/utils/uploader.py +++ b/app/utils/uploader.py @@ -15,7 +15,7 @@ class ChunkUploadBackend(ABC): """Загрузка очередного чанка""" @abstractmethod - def finish(self) -> any: + def finish(self) -> str: """Завершение загрузки""" @abstractmethod @@ -109,7 +109,7 @@ class S3ChunkUploadBackend(ChunkUploadBackend): ) # Сбрасываем части self.parts = [] - return response + return response["Location"] def abort(self) -> None: if self.upload_id: diff --git a/app/utils/youtube.py b/app/utils/youtube.py index 2e9a35f..af7a6f8 100644 --- a/app/utils/youtube.py +++ b/app/utils/youtube.py @@ -5,6 +5,9 @@ from dataclasses import dataclass from app.utils.uploader import ChunkUploadBackend +RESOLUTIONS = [240, 360, 480, 720, 1080, 1440, 2160] + + @dataclass class MediaContent: url: str @@ -36,7 +39,9 @@ class YtDlpManager: """Возвращает title видео""" return self.info.get("title", "unknown") - def download_video(self, size: Literal[240, 360, 480, 720, 1080, 1440, 2160]): + def download_video(self, size: int): + if size not in RESOLUTIONS: + raise RuntimeError("Unsupported quality") command = [ "yt-dlp", "-f", diff --git a/test.py b/test.py index 4aaddeb..2de5173 100644 --- a/test.py +++ b/test.py @@ -4,15 +4,16 @@ from app.utils.youtube import YtDlpManager def download(url: str): + from pprint import pprint # upload_backend = DiskChunkUploadBackend("trash_holder") - upload_backend = S3ChunkUploadBackend("2") + upload_backend = S3ChunkUploadBackend("3") youtube = YtDlpManager(url, upload_backend) print("Download Video") res = youtube.download_video(360) - print(res) + pprint(res) print("Download Audio") res = youtube.download_audio() - print(res) + pprint(res) print("Success") def main():