ly0303521

1M以上的图片将会被压缩之后上传

1 import { TURBO_DIFFUSION_API_URL } from '../constants'; 1 import { TURBO_DIFFUSION_API_URL } from '../constants';
2 import { VideoStatus } from '../types'; 2 import { VideoStatus } from '../types';
3 3
  4 +const compressImage = async (file: File): Promise<File> => {
  5 + return new Promise((resolve, reject) => {
  6 + const reader = new FileReader();
  7 + reader.readAsDataURL(file);
  8 + reader.onload = (event) => {
  9 + const img = new Image();
  10 + img.src = event.target?.result as string;
  11 + img.onload = () => {
  12 + const canvas = document.createElement('canvas');
  13 + let width = img.width;
  14 + let height = img.height;
  15 + const MAX_SIZE = 1024;
  16 +
  17 + if (width > height) {
  18 + if (width > MAX_SIZE) {
  19 + height *= MAX_SIZE / width;
  20 + width = MAX_SIZE;
  21 + }
  22 + } else {
  23 + if (height > MAX_SIZE) {
  24 + width *= MAX_SIZE / height;
  25 + height = MAX_SIZE;
  26 + }
  27 + }
  28 +
  29 + canvas.width = width;
  30 + canvas.height = height;
  31 + const ctx = canvas.getContext('2d');
  32 + ctx?.drawImage(img, 0, 0, width, height);
  33 +
  34 + canvas.toBlob((blob) => {
  35 + if (blob) {
  36 + const compressedFile = new File([blob], file.name, {
  37 + type: 'image/jpeg',
  38 + lastModified: Date.now(),
  39 + });
  40 + resolve(compressedFile);
  41 + } else {
  42 + reject(new Error('Canvas is empty'));
  43 + }
  44 + }, 'image/jpeg', 0.85);
  45 + };
  46 + img.onerror = (error) => reject(error);
  47 + };
  48 + reader.onerror = (error) => reject(error);
  49 + });
  50 +};
  51 +
4 /** 52 /**
5 * Submits a video generation job to the backend. 53 * Submits a video generation job to the backend.
6 * @returns The task ID for the submitted job. 54 * @returns The task ID for the submitted job.
7 */ 55 */
8 export const submitVideoJob = async (prompt: string, image: File, authorId: string, seed: number): Promise<string> => { 56 export const submitVideoJob = async (prompt: string, image: File, authorId: string, seed: number): Promise<string> => {
  57 + let finalImage = image;
  58 + if (image.size > 1024 * 1024) {
  59 + finalImage = await compressImage(image);
  60 + }
  61 +
9 const formData = new FormData(); 62 const formData = new FormData();
10 formData.append('prompt', prompt); 63 formData.append('prompt', prompt);
11 - formData.append('image', image, image.name); 64 + formData.append('image', finalImage, finalImage.name);
12 formData.append('author_id', authorId); 65 formData.append('author_id', authorId);
13 formData.append('seed', seed.toString()); 66 formData.append('seed', seed.toString());
14 67
@@ -44,7 +97,10 @@ export const pollVideoStatus = ( @@ -44,7 +97,10 @@ export const pollVideoStatus = (
44 try { 97 try {
45 const res = await fetch(`${TURBO_DIFFUSION_API_URL}/status/${taskId}`); 98 const res = await fetch(`${TURBO_DIFFUSION_API_URL}/status/${taskId}`);
46 if (!res.ok) { 99 if (!res.ok) {
47 - // Stop polling on HTTP error 100 + if (res.status === 502 || res.status === 504) {
  101 + console.warn(`Gateway timeout (${res.status}), retrying poll...`);
  102 + return;
  103 + }
48 clearInterval(interval); 104 clearInterval(interval);
49 reject(new Error(`HTTP error! status: ${res.status}`)); 105 reject(new Error(`HTTP error! status: ${res.status}`));
50 return; 106 return;