Quazim0t0 commited on
Commit
5a03d8c
·
verified ·
1 Parent(s): c3a7d92

Upload 36 files

Browse files
src/components/MultiSourceCaptioningView.tsx CHANGED
@@ -26,6 +26,8 @@ export default function MultiSourceCaptioningView() {
26
  const [webcamActive, setWebcamActive] = useState(false);
27
  const [uploadedFile, setUploadedFile] = useState<File | null>(null);
28
  const [uploadedUrl, setUploadedUrl] = useState<string>("");
 
 
29
 
30
  const videoRef = useRef<HTMLVideoElement | null>(null);
31
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
@@ -147,41 +149,39 @@ export default function MultiSourceCaptioningView() {
147
  };
148
  }, [mode, isLoaded, prompt, runInference]);
149
 
150
- // File mode: process uploaded image
151
- useEffect(() => {
152
- if (mode !== "File" || !isLoaded || !uploadedFile || !isImageFile(uploadedFile)) return;
153
  const img = imageRef.current;
154
  const canvas = canvasRef.current;
155
- if (!img || !canvas) return;
156
- img.onload = async () => {
157
- canvas.width = img.naturalWidth;
158
- canvas.height = img.naturalHeight;
159
- const ctx = canvas.getContext("2d");
160
- if (!ctx) return;
 
 
 
 
 
 
 
 
161
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
162
- try {
163
- setProcessing(true);
164
- setError(null);
165
- const fakeVideo = {
166
- videoWidth: canvas.width,
167
- videoHeight: canvas.height,
168
- getContext: () => ctx,
169
- } as unknown as HTMLVideoElement;
170
- const result = await runInference(fakeVideo, prompt);
171
- ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
172
- const boxes = extractJsonFromMarkdown(result) || [];
173
- drawBoundingBoxesOnCanvas(ctx, boxes);
174
- } catch (e) {
175
- setError(e instanceof Error ? e.message : String(e));
176
- } finally {
177
- setProcessing(false);
178
- }
179
- };
180
- }, [mode, isLoaded, prompt, runInference, uploadedFile]);
181
 
182
- // File mode: process uploaded video frames
183
  useEffect(() => {
184
- if (mode !== "File" || !isLoaded || !uploadedFile || !isVideoFile(uploadedFile)) return;
185
  let interval: ReturnType<typeof setInterval> | null = null;
186
  const processFrame = async () => {
187
  if (!videoRef.current || !canvasRef.current) return;
@@ -217,14 +217,21 @@ export default function MultiSourceCaptioningView() {
217
  return () => {
218
  if (interval) clearInterval(interval);
219
  };
220
- }, [mode, isLoaded, prompt, runInference, uploadedFile]);
221
 
222
  // Handle file upload
223
- const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
224
  const file = e.target.files?.[0] || null;
225
  setUploadedFile(file);
226
  setUploadedUrl(file ? URL.createObjectURL(file) : "");
227
  setError(null);
 
 
 
 
 
 
 
228
  };
229
 
230
  return (
@@ -360,6 +367,13 @@ export default function MultiSourceCaptioningView() {
360
  className="absolute top-0 left-0 w-full h-full pointer-events-none"
361
  style={{ zIndex: 10, pointerEvents: "none" }}
362
  />
 
 
 
 
 
 
 
363
  </div>
364
  )}
365
  {/* Show uploaded video */}
@@ -379,6 +393,12 @@ export default function MultiSourceCaptioningView() {
379
  className="absolute top-0 left-0 w-full h-full pointer-events-none"
380
  style={{ zIndex: 10, pointerEvents: "none" }}
381
  />
 
 
 
 
 
 
382
  </div>
383
  )}
384
  {/* Show example video if no file uploaded */}
 
26
  const [webcamActive, setWebcamActive] = useState(false);
27
  const [uploadedFile, setUploadedFile] = useState<File | null>(null);
28
  const [uploadedUrl, setUploadedUrl] = useState<string>("");
29
+ const [videoProcessing, setVideoProcessing] = useState(false);
30
+ const [imageProcessed, setImageProcessed] = useState(false);
31
 
32
  const videoRef = useRef<HTMLVideoElement | null>(null);
33
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
 
149
  };
150
  }, [mode, isLoaded, prompt, runInference]);
151
 
152
+ // File mode: process uploaded image (only on button click)
153
+ const handleProcessImage = async () => {
154
+ if (!isLoaded || !uploadedFile || !isImageFile(uploadedFile) || !imageRef.current || !canvasRef.current) return;
155
  const img = imageRef.current;
156
  const canvas = canvasRef.current;
157
+ canvas.width = img.naturalWidth;
158
+ canvas.height = img.naturalHeight;
159
+ const ctx = canvas.getContext("2d");
160
+ if (!ctx) return;
161
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
162
+ try {
163
+ setProcessing(true);
164
+ setError(null);
165
+ const fakeVideo = {
166
+ videoWidth: canvas.width,
167
+ videoHeight: canvas.height,
168
+ getContext: () => ctx,
169
+ } as unknown as HTMLVideoElement;
170
+ const result = await runInference(fakeVideo, prompt);
171
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
172
+ const boxes = extractJsonFromMarkdown(result) || [];
173
+ drawBoundingBoxesOnCanvas(ctx, boxes);
174
+ setImageProcessed(true);
175
+ } catch (e) {
176
+ setError(e instanceof Error ? e.message : String(e));
177
+ } finally {
178
+ setProcessing(false);
179
+ }
180
+ };
 
 
 
 
 
 
 
 
 
 
181
 
182
+ // File mode: process uploaded video frames (start/stop)
183
  useEffect(() => {
184
+ if (mode !== "File" || !isLoaded || !uploadedFile || !isVideoFile(uploadedFile) || !videoProcessing) return;
185
  let interval: ReturnType<typeof setInterval> | null = null;
186
  const processFrame = async () => {
187
  if (!videoRef.current || !canvasRef.current) return;
 
217
  return () => {
218
  if (interval) clearInterval(interval);
219
  };
220
+ }, [mode, isLoaded, prompt, runInference, uploadedFile, videoProcessing]);
221
 
222
  // Handle file upload
223
+ const handleFileChange = (e: any) => {
224
  const file = e.target.files?.[0] || null;
225
  setUploadedFile(file);
226
  setUploadedUrl(file ? URL.createObjectURL(file) : "");
227
  setError(null);
228
+ setImageProcessed(false);
229
+ setVideoProcessing(false);
230
+ };
231
+
232
+ // Handle start/stop for video processing
233
+ const handleToggleVideoProcessing = () => {
234
+ setVideoProcessing((prev) => !prev);
235
  };
236
 
237
  return (
 
367
  className="absolute top-0 left-0 w-full h-full pointer-events-none"
368
  style={{ zIndex: 10, pointerEvents: "none" }}
369
  />
370
+ <button
371
+ className="mt-4 px-6 py-2 rounded-lg bg-blue-600 text-white font-semibold"
372
+ onClick={handleProcessImage}
373
+ disabled={processing}
374
+ >
375
+ {processing ? "Processing..." : imageProcessed ? "Reprocess Image" : "Process Image"}
376
+ </button>
377
  </div>
378
  )}
379
  {/* Show uploaded video */}
 
393
  className="absolute top-0 left-0 w-full h-full pointer-events-none"
394
  style={{ zIndex: 10, pointerEvents: "none" }}
395
  />
396
+ <button
397
+ className="mt-4 px-6 py-2 rounded-lg bg-blue-600 text-white font-semibold"
398
+ onClick={handleToggleVideoProcessing}
399
+ >
400
+ {videoProcessing ? "Stop Processing" : "Start Processing"}
401
+ </button>
402
  </div>
403
  )}
404
  {/* Show example video if no file uploaded */}