Showing
1 changed file
with
58 additions
and
2 deletions
| 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; |
-
Please register or login to post a comment