mattdesl / mp4-h264

[project suspended] MP4 + H264 encoding for the browser with WASM
MIT License
223 stars 12 forks source link

Module parse failed: Unexpected token (2:25) #9

Open Luxapodular opened 3 years ago

Luxapodular commented 3 years ago

I've been unable to test the build as I am getting a few errors while importing.

When attempting to import the node version into my project, I am getting this error:

Module parse failed: Unexpected token (2:25)
You may need an appropriate loader to handle this file type.
| var Module = function () {
>   var _scriptDir = import.meta.url;
|   return function (Module) {
|     Module = Module || {};

The import looks identical to the example in the README:

const loadEncoder = require("mp4-h264");

After searching around a bit, it looks like this may be an issue with how the js is compiled, but to be honest I'm a bit lost here!

I'm attempting to import this into an app created with create-react-app, so I'm not sure if that has anything to do with it. Any help would be appreciated! Was just able to jump in and take a look while researching how to include audio...

mattdesl commented 3 years ago

Hey Luca, it seems like there's trouble importing the ES module build with Webpack, because they don't yet support import.meta.url (part of browser's ES module spec).

I'm not too familiar with Webpack, but basically it seems like you:

Would be happy to get this module in a place that is a bit easier with Webpack/etc, feel free to let me know if you see better options.

Luxapodular commented 3 years ago

Ah, being able to use this with Webpack would be great as it is used in React.js' create-react-app by default! (I am a bundling novice, so I'm not quite sure what the best steps are here).

I found this babel plugin that supposedly rewrites import.meta.url's, at the cost of a bit bundling speed, here.

It also looks like there might be a few wasm loaders that could be appropriate.

If there are resources you know of that you could direct me to in the meantime, would be happy to take a look and see if I come up with something.

yaakov123 commented 3 years ago

Here is how I approached this: 1) Download mp4-encoder.js and mp4-encoder.wasm into your project 2) Inside mp4-encoder.js change the import.meta.url -> http://localhost:8080/mp4-encoder.js (or whatever url you can use to reference the file) 3) Done

This can be improved by modifying mp4-encoder.js to accept a parameter which is the url that points to the file to work with different environments,

ericrinaldo commented 3 years ago

I let webpack ignore the import and use relative path :

(async () => {
  const path = './mp4-encoder.js'; // *.wasm in same dir
  const { default: loadEncoder } = await import(/* webpackIgnore: true */ path);
  window.loadEncoder = loadEncoder;
})();

If loadEncoder() accepted the path to *.wasm then mp4-encoder.js could be bundled by Webpack.

Luxapodular commented 3 years ago

So I'm learning a bit about bundling this week...

Thank you @yaakov123 and @ericrinaldo for your help so far. I was able to get the js file to load, but still had issues with the wasm file.

Since I'm using create-react-app, my webpack configuration is hidden. There's a nifty project called react-app-rewired that should allow me to have control over the configuration, and loaders. I've also looked into webpack 5, and it seems that they've begun to add support for import.meta, but webpack 4 wil not get a compatible upgrade because it requires a number of underlying changes.

Relevant webpack issue/PR: https://github.com/webpack/webpack/issues/6719 https://github.com/webpack/webpack/pull/11075

Apparently available since webpack v5.0.0-beta.21!

Will update on what i find in relation to create-react-app

yaakov123 commented 3 years ago

Can't you run npm run eject to expose the webpack configuration?

DanielHauschildt commented 3 years ago

@mattdesl I ran into the import.meta.url issue before and I am pretty confident that you can workaround this in emscripten with the compiler/linker flag -s USE_ES6_IMPORT_META=0

mattdesl commented 3 years ago

Hey @DanielHauschildt that works except then the .wasm file can't be found automatically via import() unfortunately, as the document.currentScript code returns undefined. So I think I need import.meta.url for it to smoothly import the file correctly, and not force the user to always specify the path.

I had another look today at this, and create-react-app doesn't seem to support WASM out of the box. You most likely have to eject and use a more customized config. I've pushed to this repo a test with asm.js (non-WASM), and it loads fine with Webpack/CRA, but performs horribly compared to WASM so I most likely won't cut a new release with it.

Still open to other ideas...

mattdesl commented 3 years ago

I'm using this module now in Parcel and running into bundler issues as well, so to get around them I'm doing something like this:

<script type='module'>
    import { simd } from "https://unpkg.com/wasm-feature-detect@1.2.9/dist/esm/index.js?module";
    import loadEncoder from "https://unpkg.com/mp4-h264@1.0.8/build/mp4-encoder.js";
    window[Symbol.for('mp4-h264')] = loadEncoder;
    window[Symbol.for('wasm-feature-detect-simd')] = simd;
</script>
<script src="your-main-src.js"></script>

In your bundled JS app somewhere

const simd = window[Symbol.for('wasm-feature-detect-simd')];
const loadEncoder = window[Symbol.for('mp4-h264')];

// .. now use these as regular

Just thought I'd put it here for reference until there is a proper solution for webpack/parcel/etc.