ffmpegwasm / ffmpeg.wasm

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

Failed to execute 'postMessage' on 'Worker': [object Array] could not be cloned. #579

Closed weboob closed 10 months ago

weboob commented 10 months ago

Describe the bug

Failed to execute 'postMessage' on 'Worker': [object Array] could not be cloned. can not exec ffmpeg command. worker is not work;

Key message

const baseURL: string = "https://unpkg.com/@ffmpeg/core-mt@0.12.3/dist/esm";

await ffmpeg.load({
  coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
  wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, "applicaiton/wasm"),
  workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, "text/javascript")
});
"@ffmpeg/ffmpeg": "^0.12.6",
"@ffmpeg/util": "^0.12.1",
  1. lib loaded success
  2. file write success
  3. exec -i /resource/1698632605093629954.mp4 test.mp4 failed

Screenshots image image

Desktop

LostBeard commented 10 months ago

Hard to say without some more code from your implementation.

1 Possible issue with call to ffmpeg.exec()

Can you show your call to ffmpeg.exec? It should look similar to the below line. This is the line that throws your error so this line is the most important to share.

await ffmpeg.exec(['-i', '/resource/1698632605093629954.mp4', 'test.mp4']);

2 Possible issue with input file (less possible as the writeFile call would likely throw the error)

Can you show your file write code where you write to '/resource/1698632605093629954.mp4'?

Probably looks similar to this...

    await ffmpeg.createDir('/resource');
    await ffmpeg.writeFile('/resource/input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));

The closest I could get to reproducing that error was if the input file is written to the FS incorrectly like below:

await ffmpeg.writeFile('/resource/input.webm', fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));

Notice the missing await on the above fetchFile call. Doing this gives me the error below which is similar to yours.

Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': #<Promise> could not be cloned.

I am thinking that your file may not be correctly saved to the input at '/resource/1698632605093629954.mp4' which could cause a postMessage clone error like the one you are seeing. You may not have omitted the await on fetchFile like I did but the error message is near identical which leads me to believe the file contents are not what ffmpeg is expecting.

Try checking the file contents after you write it. Like below:

    await ffmpeg.createDir('/resource');
    ## INSERT YOUR await ffmpeg.writeFile LINE HERE ##
    // read the contents back out and verify they are Uint8Array
    var contents = await ffmpeg.readFile('/resource/input.webm');
    console.log(contents.byteLength);
    // above line should output the size of your input file if written correctly

I am just a user, like you, trying to be helpful. If this doesn't help some more of your code may increase the chances of locating the issue. Best of luck.

weboob commented 10 months ago

First of all, thank you very much for your help @LostBeard I tried calling ffmpeg.exec() directly,it worked!! So the problem is not due to file read and write My train of thought: 1、there is task queue(command array); 2、Using watch() to automatically run commands in the queue

utils code:

const taskQueue = reactive([]); // queue
const running = ref(false);  // has task running

/**
 * add command
 * */
function addTask(command) {
  const task = {command};
  const instance = new Promise((resolve, reject) => {
    Object.assign(task, {resolve, reject});
  });
  this.taskQueue.push({instance, ...task});
  return instance;
}

/**
 * start exec queue
 * */
async function startRun() {
  if (running.value) {
    return;
  }
  running.value = true;
  await loopRunTask();
}

async function loopRunTask() {
  const currTask = this.taskQueue.shift();
  const { command, resolve, reject } = currTask;
  // 执行原始命令
  try {
    const result = await ffmpeg.exec(command);
    resolve(result);
  } catch (e) {
    console.log(`err exec:ffmpeg ${command.join(' ')}`);
    reject(e);
  } finally {
    if (taskQueue.value.length>0) {
      await this.loopRunTask();
    } else {
      running.value = false;
    }
  }
}

async function testExec(command) {
  console.log(`[exec]: ffmpeg ${command.join(' ')}`);
  return await ffmpeg.exec(command);
}

watch(this.taskQueue, () => {
  startRun();
});

test code:

// succss
... write some file to mem_fs 
command = ['-i', 'in.mp4', 'out.mp4']
await testExec(command)

// failed
... write some file to mem_fs 
command = ['-i', 'in.mp4', 'out.mp4']
await addTask(command)

I don't know where the problem is

Hard to say without some more code from your implementation.

如果没有从您的实现中获得更多的代码,就很难说。

1 Possible issue with call to ffmpeg.exec()

1调用 ffmpeg.exec ()可能出现的问题

Can you show your call to ffmpeg.exec? It should look similar to the below line. This is the line that throws your error so this line is the most important to share.

您可以显示对 ffmpeg.exec 的调用吗?它应该看起来类似于下面的行。这是抛出错误的行,所以这一行是最重要的共享。

await ffmpeg.exec(['-i', '/resource/1698632605093629954.mp4', 'test.mp4']);

2 Possible issue with input file (less possible as the writeFile call would likely throw the error)

2输入文件可能出现问题(不太可能,因为 writeFile 调用可能抛出错误)

Can you show your file write code where you write to '/resource/1698632605093629954.mp4'?

能否显示写入“/resource/1698632605093629954.mp4”的文件编写代码?

Probably looks similar to this...

可能看起来和这个很像。

    await ffmpeg.createDir('/resource');
    await ffmpeg.writeFile('/resource/input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));

The closest I could get to reproducing that error was if the input file is written to the FS incorrectly like below:

如果输入文件被错误地写入 FS,我最接近于重现这个错误,如下所示:

await ffmpeg.writeFile('/resource/input.webm', fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));

Notice the missing await on the above fetchFile call. Doing this gives me the error below which is similar to yours.

注意上面的 fetchFile 调用中缺少的等待。这样做会给我下面的错误,类似于你的错误。

Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': #<Promise> could not be cloned.

I am thinking that your file may not be correctly saved to the input at '/resource/1698632605093629954.mp4' which could cause a postMessage clone error like the one you are seeing. You may not have omitted the await on fetchFile like I did but the error message is near identical which leads me to believe the file contents are not what ffmpeg is expecting.

我认为您的文件可能没有正确地保存到“/resource/1698632605093629954.mp4”的输入中,这可能会导致您正在看到的 postMessage 克隆错误。您可能没有像我一样忽略 fetchFile 上的等待,但是错误消息几乎是相同的,这使我相信文件内容不是 ffmpeg 所期望的。

Try checking the file contents after you write it. Like below:

试着在你写下文件后检查它的内容,如下所示:

    await ffmpeg.createDir('/resource');
    ## INSERT YOUR await ffmpeg.writeFile LINE HERE ##
    // read the contents back out and verify they are Uint8Array
    var contents = await ffmpeg.readFile('/resource/input.webm');
    console.log(contents.byteLength);
    // above line should output the size of your input file if written correctly

I am just a user, like you, trying to be helpful. If this doesn't help some more of your code may increase the chances of locating the issue. Best of luck.

我只是个利用者,和你一样,想帮忙。如果这没有帮助您的一些更多的代码可能会增加找到问题的机会。祝你好运。

weboob commented 10 months ago

image

I found the reason Need to convert proxy array to a regular array

ffmpeg.exec([...command])

console.log(command, [...command]); image