Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(bug/question) How to properly use one ffmpeg.exec() execution output as another's ffmpeg.exec() input? #749

Open
knuurr opened this issue May 10, 2024 · 3 comments

Comments

@knuurr
Copy link

knuurr commented May 10, 2024

Describe the bug
Whenever I'm using previous ffmpeg.exec() output filename (i.e output-temp.mp4) in next ffmpeg.exec operation is input (by passing string with filename to -i), transformations do not stack - instead only first operation called gets presented.

To Reproduce

Here's a code simillar to which I run in my project. For this scenario let's assume all conditionals are met (As I do in my environment, with console output). In the final stage, video is presented in <video> element and blob data is used in src attribute, to return effect of ffmpeg processing to the user visually.

To verify that it's not problem with logic or ffmpeg commands, all that I need is to specify in some step different output name i.e output.mp4 and then use that as data for blob. This way I can verify that my transformation are working properly (just as in debugging bash script I maintain).

NAME_TEMP_OUTPUT = "output_temp.mp4";
...
async function convertVideo(file) {
    await ffmpeg.exec([
      "-i",
      DATA.NAME_GREENSCREEN_PNG,
      "-i",
      file.name,
      "-filter_complex",
      "... (transformation)",
      "-c:v",
      "libx264",
      "-c:a",
      "copy",
      "-preset",
      "ultrafast",
      DATA.NAME_TEMP_OUTPUT,
    ]);
}

    if (conditional1) {
      console.log("conditional 1 runs");
      await ffmpeg.writeFile(
        DATA.NAME_TEMPLATE_VIDEO,
        await fetchFile(DATA.PATH_TEMPLATE_VIDEO),
      );
      await ffmpeg.exec([
        "-i",
        DATA.NAME_TEMP_OUTPUT,
        "-i",
        DATA.NAME_TEMPLATE_VIDEO,
        "-filter_complex",
        "...",
        "-map",
        "[v]",
        "-map",
        "[a]",
        "-preset",
        "ultrafast",
        DATA.NAME_TEMP_OUTPUT,
      ]);
    }
....
    if (conditional2) {
      console.log("Conditional 2 runs");
      await ffmpeg.writeFile(
        DATA.NAME_INTRO_AUDIO,
        await fetchFile(DATA.NAME_INTRO_AUDIO),
      );
      await ffmpeg.exec([
        "-i",
        DATA.NAME_TEMP_OUTPUT, // Input video file
        "-i",
        DATA.NAME_INTRO_AUDIO, // Input audio file
        "-filter_complex",
        "..."
        "-c:v",
        "copy", // Copy video stream without re-encoding
        DATA.NAME_TEMP_OUTPUT, // Output file name
        // "output.mp4", // Output file name
      ]);
      // await ffmpeg.writeFile(DATA.NAME_TEMP_OUTPUT, DATA.NAME_TEMP_OUTPUT);
    }
    
        const data = await ffmpeg.readFile("output.mp4");
    // const data = await ffmpeg.readFile(DATA.NAME_TEMP_OUTPUT);

Expected behavior
Whenever I use name for output, such as 'temp_output.mp4', and use this name in string format as another ffmpeg.exec() input file (i.e -i temp_output.mp4 ), ffmpeg wil use the latest version of the file with latest applied transformations in memory.

Screenshots

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: MS Edge
  • Version

Additional context
Add any other context about the problem here.

@tiuvi
Copy link

tiuvi commented May 14, 2024

Doing this does not interest you because you will be duplicating memory. Better write the original file, process it with ffmpeg, delete the original file, read the new processed file and send it to the new output.
image
This is my wrapper function for the exe command

@knuurr
Copy link
Author

knuurr commented Jun 2, 2024

Thanks @tiuvi I've taken a look at your logic, learned form how do you do it, and looks like it solves my issue, at least from my experiments. I've been debugging with ffmpeg.listDir() method and from what I see, any intrmediate steps get removed in process.

Do you have any solution if I just wanted to prune any custom element within filesystem and start from scratch? because I'm not sure, if I destroy and reinitialize FFMpeg object, it won't get re-downloaded again - scenario I'd like to avoid at all costs.

@tiuvi
Copy link

tiuvi commented Jun 9, 2024

I always end the ffmpeg process
` const terminateFfmpeg = globalThis[nameGlobal]['terminateFfmpeg'] = function () {

    try {

        $ffmpeg.ffmpeg.terminate();
        return ({ err: null })
    } catch (error) {
        return ({ err: err.message })
    }

    return ({ err: null })

}`

This is the file where I am working with ffmpeg to make a video editor in conjunction with webcodecs
https://cell1.tiuvi.com:1030/ffmpegToolkit.js

This is a thread where I hope to reduce the memory by half by passing the buffer by reference
https://github.com/ffmpegwasm/ffmpeg.wasm/issues/745#issuecomment-2146063353

You need to combine url.createurl with the ffmpeg outputs, nothing much can be done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants