@@ -180,7 +180,7 @@ def modify_image_url(imageUrl, new_quality):
180180async def optimize_image_quality (image_url , max_size_bytes = 50 * 1000 , min_quality = 1 , max_quality = 99 , extra_quality_reduction = 10 ):
181181 """
182182 優化圖片品質,返還品質最低(quality 最小)但大小不超過 max_size_bytes 嘅圖片 URL。
183- 如果原始圖片或 quality=max_quality 嘅圖片 ≤ max_size_bytes,會將 quality 再調低 extra_quality_reduction。
183+ 如果 x-upstream-response-length 或 quality=max_quality 嘅圖片 ≤ max_size_bytes,會將 quality 再調低 extra_quality_reduction。
184184
185185 :param image_url: 原始圖片 URL
186186 :param max_size_bytes: 目標圖片大小(預設 50KB = 50,000 字節)
@@ -189,79 +189,74 @@ async def optimize_image_quality(image_url, max_size_bytes=50*1000, min_quality=
189189 :param extra_quality_reduction: 額外減低嘅 quality 值(預設 10)
190190 :return: 優化後嘅圖片 URL
191191 """
192- # 先獲取原始圖片(quality=max_quality)嘅大小
193- original_image_url = modify_image_url (image_url , max_quality )
194- try :
195- response = await get_response (original_image_url , method = 'HEAD' , session = session )
196- original_size = int (response .headers .get ('Content-Length' , 0 )) if response .ok else None
197- except Exception as e :
198- logger .error (f"獲取原始圖片大小失敗: { e } " )
199- original_size = None
200-
201192 low , high = min_quality , max_quality
202193 best_image_url = None
203- best_quality = max_quality + 1 # 初始值設為 max_quality + 1,確保可以更新
204-
205- # 二分搜索搵 quality 最小嘅圖片
206- while low <= high :
207- mid_quality = (low + high ) // 2
208- current_image_url = modify_image_url (image_url , mid_quality )
209-
210- try :
211- response = await get_response (current_image_url , method = 'HEAD' , session = session )
212- if response .status_code >= 400 and response .status_code < 600 :
213- logger .warning (f"HTTP 錯誤: { response .status_code } , URL: { current_image_url } " )
214- low = mid_quality + 1
215- continue
216-
217- if response .ok :
218- current_size = int (response .headers .get ('Content-Length' , 0 ))
219- logger .info (f"圖片大小: { current_size } bytes, quality: { mid_quality } , URL: { current_image_url } " )
220-
221- # 檢查圖片大小同原始圖片
222- if current_size > max_size_bytes or (original_size is not None and current_size > original_size ):
194+ best_quality = max_quality + 1
195+ upstream_response_length = None # 原始圖片大小
196+
197+ # 假設 get_response 同 modify_image_url 已定義,session 係外部傳入嘅 aiohttp session
198+ async with aiohttp .ClientSession () as session :
199+ # 二分搜索搵 quality 最小嘅圖片
200+ while low <= high :
201+ mid_quality = (low + high ) // 2
202+ current_image_url = modify_image_url (image_url , mid_quality )
203+
204+ try :
205+ response = await get_response (current_image_url , method = 'HEAD' , session = session )
206+ if response .status >= 400 and response .status < 600 :
207+ logger .warning (f"HTTP 錯誤: { response .status } , URL: { current_image_url } " )
223208 low = mid_quality + 1
209+ continue
210+
211+ if response .ok :
212+ current_size = int (response .headers .get ('Content-Length' , 0 ))
213+ upstream_response_length = int (response .headers .get ('x-upstream-response-length' , 0 )) # 獲取原始圖片大小
214+ logger .info (f"圖片大小: { current_size } bytes, quality: { mid_quality } , upstream_response_length: { upstream_response_length } , URL: { current_image_url } " )
215+
216+ # 檢查圖片大小
217+ if current_size > max_size_bytes :
218+ high = mid_quality - 1
219+ else :
220+ if mid_quality < best_quality :
221+ best_image_url = current_image_url
222+ best_quality = mid_quality
223+ low = mid_quality + 1
224224 else :
225- if mid_quality < best_quality :
226- best_image_url = current_image_url
227- best_quality = mid_quality
228- high = mid_quality - 1
229- else :
230- logger .warning (f"響應不成功: { response .status_code } , URL: { current_image_url } " )
231- low = mid_quality + 1
225+ logger .warning (f"響應不成功: { response .status } , URL: { current_image_url } " )
226+ low = mid_quality + 1
232227
233- except Exception as e :
234- logger .error (f"獲取圖片大小失敗, URL: { current_image_url } , 錯誤: { e } " )
235- low = mid_quality + 1
228+ except Exception as e :
229+ logger .error (f"獲取圖片大小失敗, URL: { current_image_url } , 錯誤: { e } " )
230+ low = mid_quality + 1
236231
237- # 如果搵唔到符合條件嘅 URL,返 min_quality 嘅 URL
238- if best_image_url is None :
239- best_image_url = modify_image_url (image_url , min_quality )
240- logger .warning (f"搵唔到大小 ≤ { max_size_bytes } bytes 嘅圖片,返 min_quality={ min_quality } 嘅 URL: { best_image_url } " )
241- return best_image_url
232+ # 如果搵唔到符合條件嘅 URL,返 min_quality 嘅 URL
233+ if best_image_url is None :
234+ best_image_url = modify_image_url (image_url , min_quality )
235+ logger .warning (f"搵唔到大小 ≤ { max_size_bytes } bytes 嘅圖片,返 min_quality={ min_quality } 嘅 URL: { best_image_url } " )
236+ return best_image_url
242237
243- # 檢查原始圖片或 quality=max_quality
244- if (original_size is not None and original_size <= max_size_bytes ) or \
245- (content_length_q99 is not None and content_length_q99 <= max_size_bytes ):
246- # 如果原始圖片或 quality=max_quality ≤ max_size_bytes,調低 quality
247- adjusted_quality = max (min_quality , best_quality - extra_quality_reduction )
248- best_image_url = modify_image_url (image_url , adjusted_quality )
249- logger .info (f"原始圖片或 quality=max_quality ≤ { max_size_bytes } bytes,調低 quality 至 { adjusted_quality } , URL: { best_image_url } " )
250- else :
251238 # 獲取 quality=max_quality 嘅圖片大小
252239 max_quality_url = modify_image_url (image_url , max_quality )
253240 try :
254241 response = await get_response (max_quality_url , method = 'HEAD' , session = session )
255242 if response .ok :
256243 max_quality_size = int (response .headers .get ('Content-Length' , 0 ))
257- if max_quality_size <= max_size_bytes :
258- adjusted_quality = max (min_quality , best_quality - extra_quality_reduction )
259- best_image_url = modify_image_url (image_url , adjusted_quality )
260- logger .info (f"quality=max_quality 嘅圖片 ≤ { max_size_bytes } bytes,調低 quality 至 { adjusted_quality } , URL: { best_image_url } " )
244+ upstream_response_length = int (response .headers .get ('x-upstream-response-length' , 0 ))
245+ else :
246+ max_quality_size = None
261247 except Exception as e :
262248 logger .error (f"獲取 quality=max_quality 圖片大小失敗: { e } " )
249+ max_quality_size = None
263250
264- return best_image_url
251+ # 檢查 x-upstream-response-length 或 quality=max_quality
252+ if (upstream_response_length is not None and upstream_response_length <= max_size_bytes ) or \
253+ (max_quality_size is not None and max_quality_size <= max_size_bytes ):
254+ # 如果 x-upstream-response-length 或 quality=max_quality ≤ max_size_bytes,調低 quality
255+ adjusted_quality = max (min_quality , best_quality - extra_quality_reduction )
256+ best_image_url = modify_image_url (image_url , adjusted_quality )
257+ logger .info (f"x-upstream-response-length 或 quality=max_quality ≤ { max_size_bytes } bytes,調低 quality 至 { adjusted_quality } , URL: { best_image_url } " )
258+
259+ return best_image_url
265260
266261# ------------------------------
267262# HTTP 請求函數:支援緩存與錯誤重試
0 commit comments