ffmpegwasm / ffmpeg.wasm

FFmpeg for browser, powered by WebAssembly
https://ffmpegwasm.netlify.app
MIT License
13.63k stars 787 forks source link

[Angular] Error: Failed to construct 'Worker': Script at 'file:///some-location/node_modules/@ffmpeg/ffmpeg/dist/esm/worker.js' #548

Closed gaurav10610 closed 3 months ago

gaurav10610 commented 11 months ago

Describe the bug [Angular] Encountering the following error in an angular application while the app is locally served(npm serve) - Error: Failed to construct 'Worker': Script at 'file:///some-location/node_modules/@ffmpeg/ffmpeg/dist/esm/worker.js'

To Reproduce

Expected behavior FFmpeg should be loaded correctly

Screenshots

Screenshot 2023-08-15 at 12 52 28 PM

Desktop (please complete the following information):

Additional Information: Also, if we can have a small example added for Angular in the examples section then it will be really great. Thanks!

Willy-JL commented 11 months ago

Similar issue here. It appears that @ffmpeg/ffmpeg must be imported from the same domain as the user's script. I am trying to import it from unpkg in a plain simple html+js page, not a single thing will make it work.

So it looks to me like this is not an Angular issue. Although for me the error is about dist/umd/814.ffmpeg.js rather than dist/esm/worker.js:

DOMException: Failed to construct 'Worker': Script at 'https://unpkg.com/@ffmpeg/ffmpeg/dist/umd/814.ffmpeg.js' cannot be accessed from origin 'http://localhost:8000'.

If i merely download the contents of @ffmpeg/ffmpeg and serve them myself, then it works properly, even importing util, core and core-mt from unpkg. The only issue is @ffmpeg/ffmpeg.

How simpler were the days without cors and domexception

Willy-JL commented 11 months ago

https://stackoverflow.com/a/25495206

Willy-JL commented 11 months ago

so because of this line: https://github.com/ffmpegwasm/ffmpeg.wasm/blob/1b2f5f14f5b4eeecb0c95588c0c337274eca7405/packages/ffmpeg/src/classes.ts#L166 and the above explanation on stackoverflow, you need headers or whatever other kind of bullshit on the domain hosting @ffmpeg/ffmpeg. So unpkg will NOT work AT ALL...

LostBeard commented 10 months ago

@Willy-JL

Same issue using ffmpeg.wasm with Blazor WASM, but using ffmpeg files from unpkg does work after a simple patch (very similar to pull #562)

I am able to use unpkg as the host for all of the ffmpeg files (umd version) using Blob and URL.createObjectURL. But I do have to modify the ffmpeg.js code slightly to do it. In fact, that line you mentioned is the part I have to modify so that I can specify the URL that the worker is created with in the config passed to ffmpeg.load. The code patch can easily be done on the fly before creating the Blob using a single text replacement. If pull #562 gets merged, or at least a similar fix enabled, I won't need to modify ffmpeg.js at all and neither will others with similar issues like yours.

No extra headers are needed from the unpkg site to use the ffmpeg files directly from them. Your server hosting your html file does need additional headers if you wish to use multithreading due to the requirements of SharedArrayBuffer. SharedArrayBuffer on MDN. I have tested the multithreaded version also using unpkg as the ffmpeg cdn and it works also.

If you think patch #562, which allows the path for the primary worker to be set via the config sent to ffmpeg.load may help resolve your issue also please go give it a thumbs up.

LostBeard commented 10 months ago

Working code example that does on the fly patching of ffmpeg.js and uses unpkg for all ffmpeg.wasm files.

The below code must be served via http:// or https:// but will not work if served via file://

index.html

<html>
    <head>
        <script src="index.js"></script>
    </head>
    <body>
        <video autoplay muted id="video-result" controls></video><br/>
        <button disabled id="load-button">Load ffmpeg-core (~31 MB)</button><br/>
        <button disabled id="transcode-button">Transcode webm to mp4</button><br/>
        <p id="log-div"></p>
        <p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
    </body>
</html>

index.js

"use strict";

var loaded = false;
var ffmpeg = null;
var loadBtn = null;
var transcodeBtn = null;
var logDiv = null;
var videoEl = null;

const toBlobURLPatched = async (url, mimeType, patcher) => {
    var resp = await fetch(url);
    var body = await resp.text();
    if (patcher) body = patcher(body);
    var blob = new Blob([body], { type: mimeType });
    return URL.createObjectURL(blob);
};

const toBlobURL = async (url, mimeType,) => {
    var resp = await fetch(url);
    var body = await resp.blob();
    var blob = new Blob([body], { type: mimeType });
    return URL.createObjectURL(blob);
};

const fetchFile = async (url) => {
    var resp = await fetch(url);
    var buffer = await resp.arrayBuffer();
    return new Uint8Array(buffer);
};

const load = async () => {
    loadBtn.setAttribute('disabled', true);
    const baseURLFFMPEG = 'https://unpkg.com/@ffmpeg/ffmpeg@0.12.6/dist/umd'
    const ffmpegBlobURL = await toBlobURLPatched(`${baseURLFFMPEG}/ffmpeg.js`, 'text/javascript', (js) => {
        return js.replace('new URL(e.p+e.u(814),e.b)', 'r.worker814URL');
    });
    const baseURLCore = 'https://unpkg.com/@ffmpeg/core@0.12.3/dist/umd'
    const config = {
        worker814URL: await toBlobURL(`${baseURLFFMPEG}/814.ffmpeg.js`, 'text/javascript'),
        coreURL: await toBlobURL(`${baseURLCore}/ffmpeg-core.js`, 'text/javascript'),
        wasmURL: await toBlobURL(`${baseURLCore}/ffmpeg-core.wasm`, 'application/wasm'),
    };
    await import(ffmpegBlobURL);
    ffmpeg = new FFmpegWASM.FFmpeg();
    ffmpeg.on('log', ({ message }) => {
        logDiv.innerHTML = message;
        console.log(message);
    });
    await ffmpeg.load(config);
    loaded = true;
    console.log('ffmpeg.load success');
    transcodeBtn.removeAttribute('disabled');
}

const transcode = async () => {
    transcodeBtn.setAttribute('disabled', true);
    await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
    await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']);
    const data = await ffmpeg.readFile('output.mp4');
    videoEl.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}

addEventListener("load", async (event) => {
    loadBtn = document.querySelector('#load-button');
    loadBtn.addEventListener('click', async () => await load());
    loadBtn.removeAttribute('disabled');
    transcodeBtn = document.querySelector('#transcode-button');
    transcodeBtn.addEventListener('click', async () => await transcode());
    logDiv = document.querySelector('#log-div');
    videoEl = document.querySelector('#video-result');
    console.log('window loaded');
});
superbartman commented 5 months ago

In webpack, this issue is still exists. @jeromewu imageimage

Not sure if this has reference value: https://webpack.docschina.org/guides/asset-modules/#url-assets

vovan1710 commented 3 months ago

Hi. I've described the solution here)

https://www.linkedin.com/pulse/web-based-video-conversion-from-webm-mp4-ffmpegwasm-hladchenko-wfejf/?trackingId=d9wnxEdbS%2FOhd%2Fye5xtGmQ%3D%3D