thekevinscott / UpscalerJS

Enhance Images with Javascript and AI. Increase resolution, retouch, denoise, and more. Open Source, Browser & Node Compatible, MIT License.
https://upscalerjs.com
MIT License
791 stars 74 forks source link

STATUS CODE 404 error when trying to import models using script tags (every model except "default-model") #1117

Closed AntiProSkills closed 1 year ago

AntiProSkills commented 1 year ago

Bug Description When trying to import any upscaling model (except the default model) using script tags, the script that imports the model throws a 404 error in the webpage's console, and the model fails to import.

To Reproduce Below is HTML code that demonstrates the error. If you open the console when running it, you can see the 404 error.

<html>
  <body>
    <div id="example-image"></div>
  </body>

  <!-- Importing TensorFlow -->
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>

  <!-- Importing the ESRGAN-Medium model and UpscalerJS -->
  <script src="https://cdn.jsdelivr.net/npm/@upscalerjs/esrgan-medium@latest/dist/umd/index.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/upscaler@latest/dist/browser/umd/upscaler.min.js"></script>

  <script type="text/javascript">
    const imageURL =
      "https://images.unsplash.com/photo-1546842931-886c185b4c8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=492.5&q=100";
    const upscaler = new Upscaler({
      model: ESRGANMedium2x,
    });
    upscaler.upscale(imageURL).then((upscaledImage) => {
      document
        .getElementById("example-image")
        .insertAdjacentHTML(
          "afterbegin",
          `<img src="${upscaledImage}" alt="Example Image"/>`
        );
    });
  </script>
</html>

Expected behavior The model should be successfully imported from the server, and the upscaled image should appear on the webpage.

Below is a working code snippet using the default-model, the only model which successfully imports using script tags.

<html>
  <body>
    <div id="example-image"></div>
  </body>

  <!-- Importing TensorFlow -->
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>

  <!-- Importing the Default model and UpscalerJS -->
  <script src="https://cdn.jsdelivr.net/npm/@upscalerjs/default-model@latest/dist/umd/index.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/upscaler@latest/dist/browser/umd/upscaler.min.js"></script>

  <script type="text/javascript">
    const imageURL =
      "https://images.unsplash.com/photo-1546842931-886c185b4c8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=492.5&q=100";
    const upscaler = new Upscaler({
      model: DefaultUpscalerJSModel,
    });
    upscaler.upscale(imageURL).then((upscaledImage) => {
      document
        .getElementById("example-image")
        .insertAdjacentHTML(
          "afterbegin",
          `<img src="${upscaledImage}" alt="Example Image"/>`
        );
    });
  </script>
</html>

Screenshots Below is a screenshot of the error message I got in the console. Error 404 in Console

Additional context It seems as if the source URL in the script that imports the model is broken or the file that was once there has moved. When you visit that URL in the browser, you get the message:

Couldn't find the requested file /dist/umd/index.min.js in @upscalerjs/esrgan-medium.

In contrast, when you try to do this with the source URL for the default-model, it seems to work properly. When you visit that URL in the browser, you get the code:

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DefaultUpscalerJSModel=t()}(this,function(){"use strict";function c(e){return r(e)?e[0]:e}var o,e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},t={},n={},u=e&&e.__extends||(o=function(e,t){return(o=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(e,t){e.__proto__=t}:function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}))(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),a=e&&e.__assign||function(){return(a=Object.assign||function(e){for(var t,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e}).apply(this,arguments)},i=e&&e.__rest||function(e,t){var n={};for(r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]]);return n},r=(Object.defineProperty(n,"__esModule",{value:!0}),n.getESRGANModelDefinition=void 0,function(e){return Array.isArray(e)}),e=(n.getESRGANModelDefinition=function(e){var s=e.scale,t=e.name,n=e.version,o=e.meta,r=o.architecture,o=i(o,["architecture"]),e=e.path||"models/".concat(s,"x/model.json");return"rdn"===r?{scale:s,modelType:"layers",_internals:{path:e,name:t,version:n},meta:a({architecture:r},o),inputRange:[0,255],outputRange:[0,255]}:{setup:function(t){var n,e=t.layers.Layer,o=.2;function r(){var e=n.call(this,{})||this;return e.beta=o,e}u(r,n=e),r.prototype.call=function(e){return t.mul(c(e),this.beta)},r.className="MultiplyBeta";var a,i;function l(){var e=i.call(this,{})||this;return e.scale=a,e}[r,(a=s,u(l,i=e),l.prototype.computeOutputShape=function(e){return[e[0],e[1],e[2],3]},l.prototype.call=function(e){return t.depthToSpace(c(e),this.scale,"NHWC")},l.className="PixelShuffle".concat(s,"x"),l)].forEach(function(e){t.serialization.registerClass(e)})},scale:s,modelType:"layers",_internals:{path:e,name:t,version:n},meta:a({architecture:r},o),inputRange:[0,1],outputRange:[0,1]}},{});Object.defineProperty(e,"__esModule",{value:!0}),e.VERSION=e.NAME=void 0,e.NAME="@upscalerjs/default-model",e.VERSION="1.0.0-beta.15",Object.defineProperty(t,"__esModule",{value:!0});n=(0,n.getESRGANModelDefinition)({scale:2,name:e.NAME,version:e.VERSION,path:"models/model.json",meta:{C:1,D:2,G:4,G0:64,T:10,architecture:"rdn",patchSize:128,size:"slim",artifactReducing:!1,sharpening:!1,dataset:"div2k",modelFileName:"rdn-C1-D2-G4-G064-T10-x2-patchsize128-compress100-sharpen0-datadiv2k-vary_cFalse_best-val_loss_epoch494"}});return t.default=n});

I'm not sure if that helps, but I thought I'd include it just in case.


Thank you in advance for your help.

thekevinscott commented 1 year ago

Thank you for reporting this. You're correct, we're not making minified index files available for the non-default models.

Specific models are made available via files matching their names:

https://cdn.jsdelivr.net/npm/@upscalerjs/esrgan-medium@latest/dist/umd/2x.min.js

Where the name corresponds to the key in the exports field, which would be:

I think there's two action items for me here:

  1. The documentation is wrong on model pages, for example here, and needs to be updated. Is that what led you to this particular implementation, or is there another spot in the documentation that is referring to these UMD builds?
  2. Ensure available top-level UMD index exports that contain all the models are published alongside the model packages. This would make all models in a package (like esrgan-medium) available in the window scope via the index.min.js file.
AntiProSkills commented 1 year ago

Thank you for such a quick and thorough response!

Yes, the documentation you mentioned (on the model pages) is what I used to create my implementation. I appreciate you providing those URLs for me to use with the non-default models, as I was looking for a way to use the non-default models with the script tag imports. I think updating the documentation to reflect what you've said is a good idea.

thekevinscott commented 1 year ago

If you run into any other issues, feel free to re-open this ticket