Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: hands.Hands is not a constructor #3796

Closed
mwbouwkamp-mendix opened this issue Oct 25, 2022 · 27 comments
Closed

TypeError: hands.Hands is not a constructor #3796

mwbouwkamp-mendix opened this issue Oct 25, 2022 · 27 comments
Assignees
Labels
legacy:hands Hand tracking/gestures/etc platform:javascript MediaPipe Javascript issues type:support General questions

Comments

@mwbouwkamp-mendix
Copy link

System information (Please provide as much relevant information as possible)

  • React/typescript
  • @mediapipe/hands version 0.4.1646424915

Describe the current behavior:
When using the default code example, I get the error TypeError: hands.Hands is not a constructor

code:

        const hands = new mpHands.Hands({
            locateFile: (_file: string) => {
                return `https://cdn.jsdelivr.net/npm/@mediapipe/hands@0.4.1646424915/hands.js`;
            }
        });
@mwbouwkamp-mendix mwbouwkamp-mendix added the type:bug Bug in the Source Code of MediaPipe Solution label Oct 25, 2022
@kuaashish kuaashish added legacy:hands Hand tracking/gestures/etc platform:javascript MediaPipe Javascript issues labels Oct 26, 2022
@kuaashish
Copy link
Collaborator

Hi @mwbouwkamp-mendix,
Could you elaborate your query with complete details and steps followed to reproduce the issue from our end. Thank you!

@kuaashish kuaashish added the stat:awaiting response Waiting for user response label Oct 27, 2022
@mwbouwkamp-mendix
Copy link
Author

Hi, @kuaashish!

I am trying to use the mediapipe library in a Mendix widget. For this, I did the following:

My useEffect function:

    useEffect(() => {
        const videoElement = document.getElementById("input_video") as HTMLVideoElement;
        const canvasElement = document.getElementById("output_canvas") as HTMLCanvasElement;
        const canvasCtx = canvasElement.getContext("2d");

        if (!canvasCtx) {
            return;
        }

        const onResults = (results: mpHands.Results): void => {
            canvasCtx.save();
            canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
            canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);
            if (results.multiHandLandmarks) {
                for (const landmarks of results.multiHandLandmarks) {
                    drawingUtils.drawConnectors(canvasCtx, landmarks, mpHands.HAND_CONNECTIONS, {
                        color: "#00FF00",
                        lineWidth: 5
                    });
                    drawingUtils.drawLandmarks(canvasCtx, landmarks, { color: "#FF0000", lineWidth: 2 });
                }
            }
            canvasCtx.restore();
        };

        const hands = new mpHands.Hands({
            locateFile: (_file: string) => {
                return `https://cdn.jsdelivr.net/npm/@mediapipe/hands@${mpHands.VERSION}/${file}`;
            }
        });

        hands.setOptions({
            maxNumHands: 1,
            modelComplexity: 1,
            minDetectionConfidence: 0.5,
            minTrackingConfidence: 0.5
        });

        hands.onResults(onResults);

        const camera = new cameraUtils.Camera(videoElement, {
            onFrame: async () => {
                await hands.send({ image: videoElement });
            },
            width: 1280,
            height: 720
        });

        camera.start();

When using this widget in a Mendix app, I get the constructor error.

@google-ml-butler google-ml-butler bot removed the stat:awaiting response Waiting for user response label Oct 27, 2022
@kuaashish kuaashish assigned ayushgdev and unassigned kuaashish Dec 7, 2022
@ayushgdev
Copy link
Contributor

Hi @mwbouwkamp-mendix
Please try importing mediapipe as

import { useEffect } from 'react';
import { Camera } from '@mediapipe/camera_utils';
import { Hands, HAND_CONNECTIONS, Results } from '@mediapipe/hands';
import { drawConnectors, drawLandmarks } from '@mediapipe/drawing_utils';

and create the hands object like

const hands = new Hands({
      locateFile: (file) => {
        return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
      },
    });

@ayushgdev ayushgdev added type:support General questions stat:awaiting response Waiting for user response and removed type:bug Bug in the Source Code of MediaPipe Solution labels Dec 7, 2022
@google-ml-butler
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you.

@google-ml-butler
Copy link

Closing as stale. Please reopen if you'd like to work on this further.

@google-ml-butler
Copy link

Are you satisfied with the resolution of your issue?
Yes
No

@mwbouwkamp-mendix
Copy link
Author

Unfortunately, this is not solving my issue. I still get the same error as before that it is not a constructor.

Appology for the late resonse...

@ayushgdev
Copy link
Contributor

Okay. Would it be possible to provide the minimal example code to reproduce the issue at our end, may be create a temporary GitHub repo to clone and test the error?
Also, please provide the steps to reproduce the issue.

@ayushgdev ayushgdev added the stat:awaiting response Waiting for user response label Jan 13, 2023
@mwbouwkamp-mendix
Copy link
Author

mwbouwkamp-mendix commented Jan 16, 2023

To reproduce

import { ReactElement, createElement, useEffect } from "react";

import { Camera } from "@mediapipe/camera_utils";
import { Hands, HAND_CONNECTIONS } from "@mediapipe/hands";
import { drawConnectors, drawLandmarks } from "@mediapipe/drawing_utils";

export function HandTracking(): ReactElement {
    useEffect(() => {
        const videoElement = document.getElementsByClassName("input_video")[0] as HTMLVideoElement;
        const canvasElement = document.getElementsByClassName("output_canvas")[0] as HTMLCanvasElement;
        const canvasCtx = canvasElement.getContext("2d");

        function onResults(results: { image: CanvasImageSource; multiHandLandmarks: any }): void {
            if (!canvasCtx) {
                return;
            }

            canvasCtx.save();
            canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
            canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);
            if (results.multiHandLandmarks) {
                for (const landmarks of results.multiHandLandmarks) {
                    drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS, { color: "#00FF00", lineWidth: 5 });
                    drawLandmarks(canvasCtx, landmarks, { color: "#FF0000", lineWidth: 2 });
                }
            }
            canvasCtx.restore();
        }

        const hands = new Hands({
            locateFile: file => {
                return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
            }
        });
        hands.setOptions({
            maxNumHands: 2,
            modelComplexity: 1,
            minDetectionConfidence: 0.5,
            minTrackingConfidence: 0.5
        });
        hands.onResults(onResults);

        const camera = new Camera(videoElement, {
            onFrame: async () => {
                await hands.send({ image: videoElement });
            },
            width: 1280,
            height: 720
        });
        camera.start();
    }, []);

    return (
        <div className="container">
            <video className="input_video"></video>
            <canvas className="output_canvas" width="1280px" height="720px"></canvas>
        </div>
    );
}
  • Create a package with npm run build
  • Create a Mendix project
  • Add package to the widgets folder
  • Open Mendix project
  • Add widget to the homepage
  • Run the app
  • View the app
  • See how the widget is not displayed and the error message shows up in the console

Here is the repo https://github.com/mwbouwkamp-mendix/handTrackingWidget

@phongchainos
Copy link

I also face this issue but only in production build, it happens with Camera in camera_utils too. For now i get Camera and Hands from cdn link instead of npm package and it work, the versions are same but npm package doesnt work in build

@taha-azzabi
Copy link

i confirm have the same problem in production environnement only

@taha-azzabi
Copy link

I'm facing the same error on production with a Vite Nuxt project ,i will try to reproduce with a CodePen

@google-ml-butler
Copy link

Closing as stale. Please reopen if you'd like to work on this further.

@google-ml-butler
Copy link

Are you satisfied with the resolution of your issue?
Yes
No

@kuaashish kuaashish removed stat:awaiting response Waiting for user response stale labels Feb 16, 2023
@ayushgdev ayushgdev reopened this Feb 16, 2023
@ayushgdev
Copy link
Contributor

Hello @taha-azzabi @nohr

This seems to be happening due to the Rollup CommonJS plugin, since this plugin can't work with obfuscated packages and the JS source code for MediaPipe is not public. Rollup uses static analysis to determine its exports.

We are working on a solution to unveal the JS code so that this issue does not arise. Meanwhile, can you refer to #2883 (comment) and let us know if this works for you?
PS: The link by the author has changed to this link

@ayushgdev ayushgdev added the stat:awaiting response Waiting for user response label Feb 16, 2023
@google-ml-butler
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you.

@mwbouwkamp-mendix
Copy link
Author

The workaround is not working for me. Could you please provide me with an indication when this may be fixed?

We are working on a solution to unveal the JS code so that this issue does not arise.

@ayushgdev
Copy link
Contributor

@mwbouwkamp-mendix Thanks for letting us know the workaround no longer works. On the fix, we don't have any timeline yet, but I would suggest to expect a wait of around a month.

@ayushgdev ayushgdev added stat:awaiting response Waiting for user response and removed stat:awaiting response Waiting for user response stale labels Feb 28, 2023
@schmidt-sebastian
Copy link
Collaborator

We are in the process of creating new JS libraries that should not have this issue, as they are built using ESM. While they have not yet reached feature parity, you can find them here: https://www.npmjs.com/package/@mediapipe/tasks-vision, https://www.npmjs.com/package/@mediapipe/tasks-text, https://www.npmjs.com/package/@mediapipe/tasks-audio. The libraries are also open sourced in this repo: https://github.com/google/mediapipe/tree/master/mediapipe/tasks/web

Due to our existing infrastructure, it is difficult for us to release the existing libraries using ESM.

@google-ml-butler
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you.

@google-ml-butler
Copy link

Closing as stale. Please reopen if you'd like to work on this further.

@google-ml-butler
Copy link

Are you satisfied with the resolution of your issue?
Yes
No

@ayushgdev ayushgdev removed stat:awaiting response Waiting for user response stalled labels Mar 23, 2023
@spencer17x
Copy link

Maybe you can use vite-plugin-mediapipe:https://github.com/Spencer17x/arca/tree/main/packages/vite-plugin/vite-plugin-mediapipe

@MadeWithStone
Copy link

per @schmidt-sebastian we used the new apis, @mediapipe/tasks-vision, which works properly in vite locally and in production. Over at Kinetix ML we have it working locally with vite and in production with vercel deploy after facing similar issues with the face landmarks api. You can checkout our implementation here https://github.com/Kinetix-ML/kml-pipe-ts/blob/main/src/operations/faceMeshDetect.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy:hands Hand tracking/gestures/etc platform:javascript MediaPipe Javascript issues type:support General questions
Projects
None yet
Development

No branches or pull requests

10 participants