1
+ import asyncio
2
+ import gc
1
3
import mimetypes
2
4
import time
3
5
from pathlib import Path
4
6
from typing import Union
5
7
6
- import aiofiles
8
+ import httpx
7
9
from httpx import AsyncClient
8
10
from loguru import logger
9
11
from tenacity import retry , stop_after_attempt , wait_random
17
19
OSSPresignedURLRequest ,
18
20
OSSPresignedURLResponse ,
19
21
PingResponse ,
22
+ RetryMergeRequest ,
23
+ RetryMergeResponse ,
20
24
StartTaskRequest ,
21
25
StartTaskResponse ,
22
26
TaskNotCompletedError ,
@@ -67,6 +71,14 @@ async def _get_oss_presigned_url(self, data: OSSPresignedURLRequest) -> OSSPresi
67
71
logger .error (f"Error getting presigned URL: { e } , { data } " )
68
72
raise e
69
73
74
+ async def _retry_merge (self , data : RetryMergeRequest ) -> RetryMergeResponse :
75
+ try :
76
+ response = await self .client .post ("/api/v1/task/retry/merge" , params = data .model_dump ())
77
+ return RetryMergeResponse (** response .json ())
78
+ except Exception as e :
79
+ logger .error (f"Error retrying merge: { e } , { data } " )
80
+ raise e
81
+
70
82
async def check_task_exist (self , video_key : str ) -> bool :
71
83
try :
72
84
get_task_progress_response = await self ._get_task_progress (GetTaskProgressRequest (video_key = video_key ))
@@ -85,6 +97,27 @@ async def check_task_completed(self, video_key: str) -> bool:
85
97
logger .error (f"Error checking task completed: { e } , video_key: { video_key } " )
86
98
return False
87
99
100
+ async def check_task_all_clips_done (self , video_key : str ) -> bool :
101
+ try :
102
+ get_task_progress_response = await self ._get_task_progress (GetTaskProgressRequest (video_key = video_key ))
103
+ if not get_task_progress_response .success :
104
+ logger .error (f"Error getting task progress: { get_task_progress_response .error .message } " ) # type: ignore
105
+ return False
106
+
107
+ for clip in get_task_progress_response .data .progress : # type: ignore
108
+ if not clip .completed :
109
+ return False
110
+
111
+ return True
112
+ except Exception as e :
113
+ logger .error (f"Error checking task all clips done: { e } , video_key: { video_key } " )
114
+ return False
115
+
116
+ async def retry_merge (self , video_key : str ) -> None :
117
+ retry_merge_response = await self ._retry_merge (RetryMergeRequest (video_key = video_key ))
118
+ if not retry_merge_response .success :
119
+ logger .error (f"Error retrying merge: { retry_merge_response .error .message } " ) # type: ignore
120
+
88
121
@retry (wait = wait_random (min = 3 , max = 5 ), stop = stop_after_attempt (5 ))
89
122
async def upload_and_new_task (self , video_path : Union [str , Path ]) -> None :
90
123
"""
@@ -102,36 +135,50 @@ async def upload_and_new_task(self, video_path: Union[str, Path]) -> None:
102
135
103
136
# gen oss presigned url
104
137
video_key = Path (video_path ).name
105
- oss_presigned_url_response = await self ._get_oss_presigned_url (OSSPresignedURLRequest (video_key = video_key ))
106
- if not oss_presigned_url_response .success :
107
- logger .error (f"Error getting presigned URL: { oss_presigned_url_response .error .message } " ) # type: ignore
108
- raise ValueError (f"Error getting presigned URL: { oss_presigned_url_response .error .message } " ) # type: ignore
109
-
110
138
try :
111
- content_type = mimetypes .guess_type (video_path )[0 ]
112
- except Exception :
113
- content_type = "application/octet-stream"
114
-
115
- # upload file
116
- try :
117
- logger .info (f"Uploading file: { video_path } " )
118
- t0 = time .time ()
119
- async with aiofiles .open (video_path , mode = "rb" ) as v :
120
- video_content = await v .read ()
121
-
122
- response = await self .client .put (
123
- url = oss_presigned_url_response .data .url , # type: ignore
124
- content = video_content ,
125
- headers = {"Content-Type" : content_type },
126
- timeout = 60 * 60 ,
127
- )
128
- if response .status_code != 200 :
129
- raise IOError (f"Error uploading file: { response .text } " )
130
- logger .info (f"Upload file Successfully! path: { video_path } time: { time .time () - t0 :.2f} s" )
139
+ oss_presigned_url_response = await self ._get_oss_presigned_url (OSSPresignedURLRequest (video_key = video_key ))
140
+ if not oss_presigned_url_response .success :
141
+ logger .error (f"Error getting presigned URL: { oss_presigned_url_response .error .message } " ) # type: ignore
142
+ raise ValueError (f"Error getting presigned URL: { oss_presigned_url_response .error .message } " ) # type: ignore
131
143
except Exception as e :
132
- logger .error (f"Error in uploading file: { video_path } : { e } " )
144
+ logger .error (f"Error getting presigned URL : { e } " )
133
145
raise e
134
146
147
+ if not oss_presigned_url_response .data .exist : # type: ignore
148
+ try :
149
+ content_type = mimetypes .guess_type (video_path )[0 ]
150
+ except Exception :
151
+ content_type = "application/octet-stream"
152
+
153
+ # upload file
154
+ try :
155
+ logger .info (f"Uploading file: { video_path } " )
156
+ t0 = time .time ()
157
+
158
+ # 这里不要用异步,会内存泄漏
159
+ def _upload_file () -> None :
160
+ with open (video_path , mode = "rb" ) as v :
161
+ video_content = v .read ()
162
+ logger .info (f"Read file Successfully! path: { video_path } time: { time .time () - t0 :.2f} s" )
163
+ response = httpx .put (
164
+ url = oss_presigned_url_response .data .url , # type: ignore
165
+ content = video_content ,
166
+ headers = {"Content-Type" : content_type },
167
+ timeout = 60 * 60 ,
168
+ )
169
+ if response .status_code != 200 :
170
+ raise IOError (f"Error uploading file: { response .text } " )
171
+
172
+ _upload_file ()
173
+ del _upload_file
174
+ gc .collect ()
175
+ logger .info (f"Upload file Successfully! path: { video_path } time: { time .time () - t0 :.2f} s" )
176
+ except Exception as e :
177
+ logger .error (f"Error in uploading file: { video_path } : { e } " )
178
+ raise e
179
+
180
+ await asyncio .sleep (2 )
181
+
135
182
# new task
136
183
new_task_response = await self ._new_task (NewTaskRequest (video_key = video_key ))
137
184
if not new_task_response .success :
@@ -168,5 +215,5 @@ async def download_completed_task(self, video_key: str, save_path: Union[str, Pa
168
215
if response .status_code != 200 :
169
216
raise IOError (f"Error downloading file: { response .text } " )
170
217
171
- async with aiofiles . open (save_path , mode = "wb" ) as v :
172
- await v .write (response .content )
218
+ with open (save_path , mode = "wb" ) as v :
219
+ v .write (response .content )
0 commit comments