libass / JavascriptSubtitlesOctopus

Displays subtitles in .ass format from JavaScript. Supports most SSA/ASS features, easily integrates with HTML5 videos.
MIT License
413 stars 104 forks source link

How to use it for webpack? #51

Closed jiseopX closed 2 years ago

jiseopX commented 4 years ago

in subtitles-octopus-worker.js, it seems to load .wasm file from the same directory of itself. However, this way doesn't work with webpack. How can i fix it?

Dudecake commented 4 years ago

I also struggled with this. In a Vue application I "fixed" it with the javascript below. This worked mostly, except for the .wasm file. I "fixed" that by creating a symlink in the public directory which gets copied as-is, which is less than ideal but it works.

import SubtitlesOctopus from "libass-wasm/dist/subtitles-octopus.js";
// TODO: find a less garbage way to load libass-wasm
// import(
//   "!!file-loader?name=[name].[ext]!libass-wasm/dist/subtitles-octopus-worker.wasm"
// );
import "!!file-loader?name=[name].[ext]!libass-wasm/dist/subtitles-octopus-worker.data";

My webpack configuration might also contribute to this "fix", so below is the content of the configureWebpack object of my vue.config.js. The commented out parts are things I've attempted to copy the subtitles-octopus-worker.wasm file as-is. DISCLAIMER: I only vaguely know what I'm doing with Webpack, so it might not be pretty...

{
  "module": {
    // defaultRules: [
    //   {
    //     test: /subtitles-octopus-worker\.wasm$/,
    //     use: [{
    //       loader: "file-loader",
    //       options: {
    //         name: "[name].[ext]"
    //       }
    //     }],
    //     type: "webassembly/experimental"
    //   },
    //   {
    //     test: /\.wasm$/,
    //     use: [{
    //       loader: "file-loader",
    //       options: {
    //         name: "[name].[ext]"
    //       }
    //     }],
    //     type: "webassembly/experimental"
    //   }
    // ],
    "rules": [
      {
        "test": /\/svg$/,
        "use": [{ "loader": "file-loader" }]
        // },
        // {
        //   test: /subtitles-octopus-worker\.wasm$/,
        //   use: [{
        //     loader: "file-loader",
        //     options: {
        //       name: "[name].[ext]"
        //     }
        //   }],
        //   type: "webassembly/experimental"
        // },
        // {
        //   test: /\.wasm$/,
        //   use: [{
        //     loader: "file-loader",
        //     options: {
        //       name: "[name].[ext]"
        //     }
        //   }],
        //   type: "webassembly/experimental"
      }
    ]
  },
  "optimization": {
    "mangleWasmImports": false,
    "noEmitOnErrors": true,
    "splitChunks": {
      "chunks": "all",
      "maxInitialRequests": Infinity,
      "minSize": 0,
      "cacheGroups": {
        "vendors": {
          "test": /[\\/]node_modules[\\/]/,
          "name": module =>
            module.context.match(/[\\/]node_modules[\\](.*?)([\\/]|$)/)[1]
        }
      }
    }
  }
}
jiseopX commented 4 years ago

@Dudecake and iam wondering how to connect subtitles-octopus.js and subtitles-otopus-worker.js in webpack. I mean i cannot pass the worker path using workerUrl because of webpack bundler. Could you please explain me?

Dudecake commented 4 years ago

I forgot about that part because that wasn't the part I had the most trouble with. Sorry about that...

You can actually specify the path of the subtitles-octopus-worker.js file with the below javascript

      const subtitlesOctopusOptions = {
        video: videoElement,
        workerUrl: require("!!file-loader?name=[name].[ext]!libass-wasm/dist/subtitles-octopus-worker.js")
      };
      this.subtitlesOctopus = new SubtitlesOctopus(subtitlesOctopusOptions);

You don't have to specify the name with name=[name].[ext], but I did it for the sake of consistency.

cobarx commented 4 years ago

For our setup, we don't use webpack for the worker. We have a yarn script that creates the bundle with webpack then copies the worker files to an assets folder. That makes it pretty easy to have a hardcoded path to the worker.

Dudecake commented 4 years ago

I don't know if you are still watching this issue, but after experimenting for FAR too long I gave up and just used copy-webpack-plugin to copy the dist directory to / in the target directory with:

const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
  configureWebpack: {
    plugins: [
      new CopyWebpackPlugin([{ from: "node_modules/libass-wasm/dist" }])
    ]
  }
}
ttshivers commented 4 years ago

I found looking at Jellyfin's implementation useful to look at.

nopol10 commented 3 years ago

For NekoCap which is a browser extension, copying it via copy-webpack-plugin works well enough

TheOneric commented 2 years ago

I'm not familiar with webpacks, but it seems like the question got answered? If someone knowledgeable in this wants to make a solution more visible, I'd suggeset adding a new Webpack page with the info to the wiki (every GitHub-account has write access).