google-ai-edge / mediapipe

Cross-platform, customizable ML solutions for live and streaming media.
https://ai.google.dev/edge/mediapipe
Apache License 2.0
27.42k stars 5.15k forks source link

Changing wasmBinaryPath always fails to load #4819

Closed satoren closed 1 year ago

satoren commented 1 year ago

Have I written custom code (as opposed to using a stock example script provided in MediaPipe)

Yes

OS Platform and Distribution

Web

MediaPipe Tasks SDK version

0.10.6

Task name (e.g. Image classification, Gesture recognition etc.)

ObjectDetector, ImageSegmenter etc.

Programming Language and version (e.g. C++, Python, Java)

Typescript

Describe the actual behavior

If change wasmBinaryPath, <<document_root>>/vision_wasm_internal.wasm will be loaded.

Describe the expected behaviour

want the wasm file specified by wasmBinaryPath to be loaded

Standalone code/steps you may have used to try to get what you need

https://codepen.io/satoren/pen/bGOYJbR?editors=0011

  const vision = await FilesetResolver.forVisionTasks(
    "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.6/wasm"
  );
  vision.wasmBinaryPath = "https://mydomain/wasm/vision_wasm_internal-added_hash.wasm";

The path specified in "wasmBinaryPath" is ignored and a request is made to https://cdpn.io/satoren/fullembedgrid/vision_wasm_internal.wasm (This one does not exist).

Until 0.10.4, wasm was loaded from the specified path.

Other info / Complete Logs

No response

ayushgdev commented 1 year ago

Hello @satoren Would you please check if the codepen URL you provided still works? We have checked the following URLs and getting 404 error: https://cdpn.io/satoren/fullembedgrid/ https://codepen.io/satoren/fullembedgrid/ https://cdpn.io/satoren/

satoren commented 1 year ago

Hello @ayushgdev You are correct that that URL is not provided. The URL specified in wasmBinaryPath is ignored and a request is made to a non-existent URL. https://cdpn.io/satoren/fullembedgrid/ is the base path of the page in the codepen iframe. This seems to change each time the code is edited and is not fixed.

ayushgdev commented 1 year ago

In that case, please try hosting the WASM file in a permanent CDN first and then replicate the issue. For simplicity of the context of the issue, I limited the replication to the issue of wasmBinaryPath changed after FilsetResolver is initialized. The following code in the context is working:

const vision = await FilesetResolver.forVisionTasks("");
vision.wasmBinaryPath = "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.6/wasm";

So I provided blank string as initial argument and then changed it. So changing the wasmBinaryPath works.

satoren commented 1 year ago

@ayushgdev I see, it seems like changing the file name won't work. In '0.10.4', file name changes were accepted. When using npm packages, I don't want to specify the version separately in the cdn in order to align the package version and wasm version. That's why I want to include files by bundler. I also want to change the file name so that a different file is not used in the cache when the version is updated. It is common for bundler to add a hash to the file name.

Thank you for reply. It's a hassle, but there is a workaround, so if this is the specification, I'll accept it.

ayushgdev commented 1 year ago

Okay @satoren . Can we mark the issue as resolved and close?

artemjackson commented 1 year ago

I have the same issue, but when the wasmBinaryPath is pointing to the URL created by URL.createObjectURL().

My use-case is the following: I want to track the vision_wasm_internal.wasm fetch progress to show a loading progress indicator. To accomplish this, I fetch the vision_wasm_internal.wasm manually, convert the fetch response to Blob, create an object URL, and pass it to the wasmFileste.wasmBinaryPath option.

Pseudocode:

const wasmLoader = await fetch("/node_modules/@mediapipe/tasks-vision/wasm/vision_wasm_internal.js").then(r => r.blob())
const wasmBinary = await fetch("/node_modules/@mediapipe/tasks-vision/wasm/vision_wasm_internal.wasm").then(r => r.blob())
const modelAsset = await fetch("/path/to/locally-downloaded/face_landmarker.task").then(r => r.blob())

const wasmLoaderPath = URL.createObjectURL(wasmLoader)
const wasmBinaryPath = URL.createObjectURL(wasmBinary)
const modelAssetPath = URL.createObjectURL(modelAsset)

const landmarker = await FaceLandmarker.createFromOptions(
    { wasmLoaderPath, wasmBinaryPath },
    { baseOptions: { modelAssetPath } },
)    

I‘ve figured out that the issue is caused by the

fileset.wasmBinaryPath.includes("vision_wasm_internal.wasm")

check in the FileLocator.locateFile function: if the wasmFileste.wasmBinaryPath does not include "vision_wasm_internal.wasm" - the plain "vision_wasm_internal.wasm" is returned from the FileLocator.locateFile.

satoren commented 1 year ago

@ayushgdev Could you please tell me what the specifications are for wasmBinaryPath? If we can only specify the base path, what is the role of FilesetResolver?

schmidt-sebastian commented 1 year ago

Sorry this is indeed a regression. Fix pending review.

google-ml-butler[bot] commented 1 year ago

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