File size: 4,499 Bytes
0978387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a909c5f
0978387
a909c5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0978387
 
 
 
 
 
 
a909c5f
0978387
f74ada5
 
 
 
a909c5f
 
0978387
 
 
 
 
a909c5f
0978387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285564b
 
 
 
 
 
0978387
285564b
 
 
0978387
 
285564b
0978387
 
 
 
 
a909c5f
 
0978387
a909c5f
 
 
 
0978387
a909c5f
0978387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from fastapi import APIRouter, HTTPException, BackgroundTasks
import tempfile
import os
import logging
import asyncio
from .Schema import YouTubeUploadTask

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

router = APIRouter(prefix="/youtube", tags=["youtube"])


async def download_file(url: str) -> str:
    """Download file from URL using aria2c."""
    try:
        # Create temp directory for download
        temp_dir = tempfile.mkdtemp()
        temp_path = os.path.join(
            temp_dir, "video"
        )  # aria2c will add extension automatically

        # Build aria2c command
        command = [
            "aria2c",
            "--allow-overwrite=true",
            "--auto-file-renaming=false",
            "--max-connection-per-server=16",
            "--split=16",
            "--dir",
            temp_dir,
            "--out",
            "video",
            url,
        ]

        logger.info(f"Starting download with aria2c: {url}")
        process = await asyncio.create_subprocess_exec(
            *command,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await process.communicate()

        if process.returncode != 0:
            raise Exception(f"Download failed: {stderr.decode()}")

        # Find the downloaded file (aria2c adds extension automatically)
        downloaded_files = os.listdir(temp_dir)
        if not downloaded_files:
            raise Exception("No file downloaded")

        downloaded_file = os.path.join(temp_dir, downloaded_files[0])
        logger.info(f"Download completed: {downloaded_file}")
        return downloaded_file

    except Exception as e:
        logger.error(f"Error downloading file: {str(e)}")
        raise HTTPException(status_code=500, detail=f"File download failed: {str(e)}")


async def upload_video_background(task: YouTubeUploadTask):
    """Background task to handle video upload."""
    temp_dir = None
    try:
        # Convert HttpUrl to string
        url = str(task.filename)
        logger.info(f"Starting download for video: {url}")
        downloaded_file = await download_file(url)
        temp_dir = os.path.dirname(downloaded_file)
        logger.info(f"Download complete. Saved to: {downloaded_file}")

        # Build the command
        command = [
            "/srv/youtube/youtubeuploader",
            "-filename",
            downloaded_file,
            "-title",
            task.title,
            "-description",
            task.description,
            "-categoryId",
            task.category_id,
            "-privacy",
            task.privacy,
            "-tags",
            task.tags,
        ]

        if task.thumbnail:
            command.extend(["-thumbnail", task.thumbnail])

        logger.info("Executing upload command")
        process = await asyncio.create_subprocess_exec(
            *command,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await process.communicate()

        if process.returncode != 0:
            logger.error(f"Upload failed: {stderr.decode()}")
            raise Exception(f"Upload failed: {stderr.decode()}")

        logger.info("Upload completed successfully")
        logger.debug(f"Upload output: {stdout.decode()}")

    except Exception as e:
        logger.error(f"Error in upload process: {str(e)}")
        raise
    finally:
        # Clean up temp directory and its contents
        if temp_dir and os.path.exists(temp_dir):
            try:
                for file in os.listdir(temp_dir):
                    os.remove(os.path.join(temp_dir, file))
                os.rmdir(temp_dir)
                logger.info(f"Cleaned up temporary directory: {temp_dir}")
            except Exception as e:
                logger.error(f"Failed to clean up temp directory: {str(e)}")


@router.post("/upload")
async def upload_video_to_youtube(
    task: YouTubeUploadTask, background_tasks: BackgroundTasks
):
    """
    Endpoint to handle YouTube video upload requests.
    The actual upload is performed as a background task.
    """
    try:
        background_tasks.add_task(upload_video_background, task)
        return {"message": "Upload task started", "status": "processing"}
    except Exception as e:
        logger.error(f"Error initiating upload task: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))