Mbonea commited on
Commit
285564b
·
1 Parent(s): b48956d
Files changed (1) hide show
  1. App/Youtube/youtubeRouter.py +76 -19
App/Youtube/youtubeRouter.py CHANGED
@@ -1,10 +1,11 @@
1
  from fastapi import APIRouter, HTTPException, BackgroundTasks
2
- from subprocess import run
3
  import tempfile
4
  import os
5
  import logging
6
  import aiohttp
7
  import asyncio
 
 
8
  from .Schema import YouTubeUploadTask
9
 
10
  # Configure logging
@@ -15,28 +16,81 @@ router = APIRouter(prefix="/youtube", tags=["youtube"])
15
 
16
 
17
  async def download_file(url: str) -> str:
18
- """Download file from URL and save to temp directory."""
19
  try:
20
  async with aiohttp.ClientSession() as session:
21
  async with session.get(url) as response:
22
- if response.status != 200:
23
  raise HTTPException(
24
  status_code=400,
25
  detail=f"Failed to download file: HTTP {response.status}",
26
  )
27
 
28
- # Create temp file with appropriate extension
29
- content_type = response.headers.get("content-type", "")
30
- ext = ".mp4" if "video" in content_type else ".tmp"
31
-
32
- fd, temp_path = tempfile.mkstemp(suffix=ext)
33
 
34
  # Write content to temp file
35
- with os.fdopen(fd, "wb") as tmp:
36
  while chunk := await response.content.read(8192):
37
- tmp.write(chunk)
38
-
39
- return temp_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  except Exception as e:
41
  logger.error(f"Error downloading file: {str(e)}")
42
  raise HTTPException(status_code=500, detail=f"File download failed: {str(e)}")
@@ -71,20 +125,24 @@ async def upload_video_background(task: YouTubeUploadTask):
71
  command.extend(["-thumbnail", task.thumbnail])
72
 
73
  logger.info("Executing upload command")
74
- result = run(command, capture_output=True, text=True)
 
 
 
 
 
75
 
76
- if result.returncode != 0:
77
- logger.error(f"Upload failed: {result.stderr}")
78
- raise Exception(f"Upload failed: {result.stderr}")
79
 
80
  logger.info("Upload completed successfully")
81
- logger.debug(f"Upload output: {result.stdout}")
82
 
83
  except Exception as e:
84
  logger.error(f"Error in upload process: {str(e)}")
85
  raise
86
  finally:
87
- # Clean up temp file
88
  if temp_file and os.path.exists(temp_file):
89
  try:
90
  os.remove(temp_file)
@@ -104,7 +162,6 @@ async def upload_video_to_youtube(
104
  try:
105
  background_tasks.add_task(upload_video_background, task)
106
  return {"message": "Upload task started", "status": "processing"}
107
-
108
  except Exception as e:
109
  logger.error(f"Error initiating upload task: {str(e)}")
110
  raise HTTPException(status_code=500, detail=str(e))
 
1
  from fastapi import APIRouter, HTTPException, BackgroundTasks
 
2
  import tempfile
3
  import os
4
  import logging
5
  import aiohttp
6
  import asyncio
7
+ import aiofiles
8
+ import subprocess
9
  from .Schema import YouTubeUploadTask
10
 
11
  # Configure logging
 
16
 
17
 
18
  async def download_file(url: str) -> str:
19
+ """Download file from URL and save to temp directory with correct extension based on metadata."""
20
  try:
21
  async with aiohttp.ClientSession() as session:
22
  async with session.get(url) as response:
23
+ if response.status not in (200, 206):
24
  raise HTTPException(
25
  status_code=400,
26
  detail=f"Failed to download file: HTTP {response.status}",
27
  )
28
 
29
+ # Create temp file with .tmp extension
30
+ fd, temp_path = tempfile.mkstemp(suffix=".tmp")
 
 
 
31
 
32
  # Write content to temp file
33
+ async with aiofiles.open(fd, "wb") as tmp:
34
  while chunk := await response.content.read(8192):
35
+ await tmp.write(chunk)
36
+
37
+ # Determine file format using ffprobe
38
+ try:
39
+ # Get codec information
40
+ codec_cmd = [
41
+ "ffprobe",
42
+ "-v",
43
+ "error",
44
+ "-select_streams",
45
+ "v:0",
46
+ "-show_entries",
47
+ "stream=codec_name",
48
+ "-of",
49
+ "default=noprint_wrappers=1:nokey=1",
50
+ temp_path,
51
+ ]
52
+ codec_result = subprocess.run(
53
+ codec_cmd, capture_output=True, text=True
54
+ )
55
+ codec = codec_result.stdout.strip().lower()
56
+
57
+ # Get container format
58
+ format_cmd = [
59
+ "ffprobe",
60
+ "-v",
61
+ "error",
62
+ "-show_entries",
63
+ "format=format_name",
64
+ "-of",
65
+ "default=noprint_wrappers=1:nokey=1",
66
+ temp_path,
67
+ ]
68
+ format_result = subprocess.run(
69
+ format_cmd, capture_output=True, text=True
70
+ )
71
+ format_name = format_result.stdout.strip().lower()
72
+
73
+ # Determine extension based on codec and container
74
+ if "mp4" in format_name or codec in ("h264", "aac"):
75
+ ext = ".mp4"
76
+ elif "webm" in format_name or codec == "vp9":
77
+ ext = ".webm"
78
+ elif "avi" in format_name:
79
+ ext = ".avi"
80
+ else:
81
+ # Fallback to content-type if metadata unavailable
82
+ content_type = response.headers.get("content-type", "")
83
+ ext = ".mp4" if "video" in content_type else ".tmp"
84
+ except Exception:
85
+ # Fallback if ffprobe fails
86
+ content_type = response.headers.get("content-type", "")
87
+ ext = ".mp4" if "video" in content_type else ".tmp"
88
+
89
+ # Rename file with correct extension
90
+ new_temp_path = f"{temp_path[:-4]}{ext}"
91
+ os.rename(temp_path, new_temp_path)
92
+
93
+ return new_temp_path
94
  except Exception as e:
95
  logger.error(f"Error downloading file: {str(e)}")
96
  raise HTTPException(status_code=500, detail=f"File download failed: {str(e)}")
 
125
  command.extend(["-thumbnail", task.thumbnail])
126
 
127
  logger.info("Executing upload command")
128
+ process = await asyncio.create_subprocess_exec(
129
+ *command,
130
+ stdout=asyncio.subprocess.PIPE,
131
+ stderr=asyncio.subprocess.PIPE,
132
+ )
133
+ stdout, stderr = await process.communicate()
134
 
135
+ if process.returncode != 0:
136
+ logger.error(f"Upload failed: {stderr.decode()}")
137
+ raise Exception(f"Upload failed: {stderr.decode()}")
138
 
139
  logger.info("Upload completed successfully")
140
+ logger.debug(f"Upload output: {stdout.decode()}")
141
 
142
  except Exception as e:
143
  logger.error(f"Error in upload process: {str(e)}")
144
  raise
145
  finally:
 
146
  if temp_file and os.path.exists(temp_file):
147
  try:
148
  os.remove(temp_file)
 
162
  try:
163
  background_tasks.add_task(upload_video_background, task)
164
  return {"message": "Upload task started", "status": "processing"}
 
165
  except Exception as e:
166
  logger.error(f"Error initiating upload task: {str(e)}")
167
  raise HTTPException(status_code=500, detail=str(e))