我可以将自定义元标签添加到网络摄像头捕获的 JavaScript 图像文件中吗?

问题描述 投票:0回答:1

我的 JavaScript 代码中有一个函数,可以从视频流中捕获图像并将其保存为文件。在 mediaRecorder.onstop 事件处理程序中,我将捕获的图像转换为文件格式,然后转换为数据 URL。现在,我想操作该图像文件的元标记,并添加一个带有键“Source”和值“CameraTest”的自定义元标记。然而,我使用“piexif”库的尝试并没有成功。

在 mediaRecorder.onstop 事件处理程序中,将图像转换为文件和数据 URL 后,我尝试使用“piexif”库来操作 EXIF 数据并添加自定义元标记,但遇到了困难。有没有办法在 JavaScript 或任何其他库或方法中实现元标记的这种操作?

任何帮助或见解将不胜感激。谢谢!

功能:

    const captureImageManual = async () => {
        if (canvasRef && canvasRef.current && mediaStream && !captureTimer) {
            /* Record Video */
            const blobsRecorded: Blob[] = [];

            // Check if mime type is supported by browser
            for (let index = 0; index < mimeTypes.length; index += 1) {
                const isSupported = MediaRecorder.isTypeSupported(mimeTypes[index].mime);
                if (isSupported) {
                    supportedMimeType.current = mimeTypes[index];

                    break;
                }
            }

            if (!supportedMimeType?.current?.mime) {
                console.log('No valid video mime type supported by browser');
                toast.error('This browser is not supported for KYC. Please try again using a different browser.');
                Sentry.captureException({
                    error: new Error('No valid video mime type supported by browser'),
                    message: 'This browser is not supported for KYC. Please try again using a different browser.',
                });
                return;
            }

            // set MIME type of recording as the first supported mime type found
            const mediaRecorder = new MediaRecorder(mediaStream, { mimeType: supportedMimeType.current.mime });

            // event : new recorded video blob available
            mediaRecorder.ondataavailable = (event) => {
                console.log('event data: ', event.data);
                blobsRecorded.push(event.data);
            };

            // event : recording stopped & all blobs sent
            mediaRecorder.onstop = async () => {
                // // create local object URL from the recorded video blobs
                // const videoLocal = URL.createObjectURL(new Blob(blobsRecorded, { type: 'video/mp4' }));

                // Convert BLOB to File
                const recordedVideoFile = new File(blobsRecorded, 'video', { type: supportedMimeType.current?.mime });

                setVideoFile(recordedVideoFile);

                /* Capture Photo */
                // Add to canvas element
                // const xMultiplier = videoRef.current.videoWidth / videoRef.current.clientWidth;
                // const yMultiplier = videoRef.current.videoHeight / videoRef.current.clientHeight;
                canvasRef.current.height = videoRef?.current?.videoHeight;
                canvasRef.current.width = videoRef?.current?.videoWidth;
                canvasRef?.current
                    ?.getContext('2d')
                    ?.drawImage(videoRef.current, 0, 0, videoRef?.current?.videoWidth, videoRef?.current?.videoHeight);

                // const dimension = isDesktop ? (window.innerWidth / 100) * 20 : 260;
                // const dimension = holeRef?.current?.clientWidth;

                // canvasRef?.current?.getContext('2d')?.drawImage(
                //     videoRef.current, // image
                //     (videoRef.current.clientWidth / 2) * xMultiplier - (dimension / 2) * xMultiplier, // sx
                //     32 * yMultiplier, // sy
                //     dimension * xMultiplier, // sWidth
                //     dimension * yMultiplier, // sHeight
                //     0, // dx
                //     0, // dy
                //     canvasRef.current.width, // dWidth
                //     canvasRef.current.height, // dHeight
                // );
                const imageDataUrl = canvasRef.current.toDataURL('image/jpeg');
                setCapturedImageUrl(imageDataUrl);

                // Convert to File
                const res: Response = await fetch(imageDataUrl);
                const blob: Blob = await res.blob();
                const capturedImageFile = new File([blob], 'selfie', { type: 'image/jpeg' });

                //
                const exifIfd: any = {};
                exifIfd[piexif.ExifIFD.DateTimeOriginal] = '2010:10:10 10:10:10';
                exifIfd[piexif.ExifIFD.LensMake] = 'Lens Maker';
                exifIfd[piexif.ExifIFD.Sharpness] = 777;
                exifIfd[piexif.ExifIFD.LensSpecification] = [
                    [1, 1],
                    [1, 1],
                    [1, 1],
                    [1, 1],
                ];
                // exifIfd['Source'] = 'CameraTestPotlee';

                const exifBytes = piexif.dump({ Exif: exifIfd });
                const exifModified = piexif.insert(exifBytes, imageDataUrl);

                setSrc(exifModified);

                console.log({ exifModified });

                // const newFile = await writePNGtext(capturedImageFile, 'Source', 'CameraTestPotlee');
                // const buffer = new Uint8Array([newFile]);
                // const blobx = new Blob([buffer], { type: 'image/png' }); // Specify the file type
                // const filex = new File([blobx], 'selfie', { type: 'image/png' }); // Specify filename and type

                // const exifrParse = await exifr.parse(filex);
                // const metaTags = await EXIF.getAllTags(filex);
                // console.log({ metaTags });

                setSelfieFile(capturedImageFile);
            };
            // event : recording started
            mediaRecorder.onstart = () => {
                // Capture button timer
                setCaptureTimer(3);
                interval.current = setInterval(() => {
                    setCaptureTimer((state) => {
                        if (state > 0) {
                            return state - 1;
                        }
                        return state;
                    });
                }, 1000);

                // Stop recording after 3 seconds
                setTimeout(() => {
                    mediaRecorder.stop();
                }, 3000);
                setNewImage(true);
            };
            // start recording with each recorded blob having 1 second video
            mediaRecorder.start(1000);
        }
    };

我尝试使用不同的库,例如:piexifjs、exif-js、exifr、image-metadata-editor 但大多数情况下我无法添加任何自定义标签。

reactjs image-processing metadata exif xmp
1个回答
0
投票

是的,您可以使用 JavaScript 将自定义元标记添加到从网络摄像头捕获的图像文件中。然而,需要注意的是,JavaScript 本身并不直接提供操作图像文件元数据的方法。相反,您通常需要结合使用 JavaScript 和服务器端技术来实现此目的。

这是完成此任务的一般方法:

捕获图像:使用 JavaScript 从网络摄像头捕获图像,使用 getUserMedia() 函数等 API 来访问用户的相机和 Canvas 来绘制捕获的图像。

创建元数据:收集要添加到图像的自定义元数据。这可能包括用户姓名、时间戳、位置或任何其他相关数据等信息。

将图像和元数据发送到服务器:使用 JavaScript 将捕获的图像数据以及自定义元数据发送到服务器。您可以使用 AJAX 请求或表单提交等技术来异步发送数据。

服务器端处理:在服务器端(使用Node.js、PHP、Python等服务器端语言)接收图像和元数据。使用库或工具来操作图像文件的元数据。例如,在 Node.js 中,您可以使用 exiftool 或 exifr 等库来添加或修改元数据。

使用元数据保存图像:将元数据添加到图像文件后,将修改后的图像文件保存到您所需的位置,例如数据库或文件系统。

提供带有元数据的图像:最后,如果需要,可以将带有添加的元数据的图像文件提供给请求它的客户端。

请记住,由于安全限制和浏览器 API 的限制,单独在客户端(使用 JavaScript)操作图像元数据可能是不可能的。因此,通常最好在服务器端处理此任务,这样您可以更好地控制和访问适当的图像处理工具和库。

© www.soinside.com 2019 - 2024. All rights reserved.