brianchirls / Seriously.js

A real-time, node-based video effects compositor for the web built with HTML5, Javascript and WebGL
MIT License
3.87k stars 354 forks source link

Callback/event when the Chromakey effect has been applied to an image #161

Open polomoshnov opened 6 years ago

polomoshnov commented 6 years ago

Right after seriously.go() I do target.toDataURL('image/png') and get an empty image. But if I setTimeout(function () { target.toDataURL('image/png') }, 1000) the image is not empty and has the Chromakey effect applied successfully. (For the source I use an image not a video.) I think the effect is being applied asynchronously and that's why that happens.

positlabs commented 6 years ago

Are you preloading the image?

It should be drawn on the next frame. For that, you can do requestAnimationFrame(yourCallback)

spoji commented 5 years ago

While a lot of threads on different websites say otherwise, toDataURL() is now asynchronous (at least on Chrome) : https://bugs.chromium.org/p/chromium/issues/detail?id=514206

You can fix this using a promise/callback instead of a timeout. For example :

    return new Promise(resolve => {
        const img = new Image();
        ...<snip>...

        img.onload = function() {
            resolve(img);
        };

        img.src = canvas.toDataURL("image/png");
    });
juliandormon commented 4 years ago

I am having the exact same issue. The target canvas worked perfectly. I wrapped the method in an onload event as specified above but I still get a transparent image. Hoping you can help.Thanks in advance.

 var seriously = new Seriously();
            var source = seriously.source(media);
            var target = seriously.target(canvas);
            chromaEffect = seriously.effect("chroma");
            chromaEffect.screen = [0 / 255, 117 / 255, 49 / 255, 0];
            chromaEffect.weight = 1;
            chromaEffect.balance = 1;
            chromaEffect.clipBlack = 0;
            chromaEffect.clipWhite = 1;
            chromaEffect.source = source;
            target.source = chromaEffect;
            seriously.go();

var finalImg = new Image();

                finalImg.onload = function () {
                    $media.attr("src", finalImg.src);
                }

                finalImg.src = canvas.toDataURL("image/png");
juliandormon commented 4 years ago

I figured it out. I had to put my final functions within the go(callback);

var seriously = new Seriously();
            var source = seriously.source(media);
            var target = seriously.target(canvas);
            chromaEffect = seriously.effect("chroma");
            chromaEffect.screen = [0 / 255, 117 / 255, 49 / 255, 0];
            chromaEffect.weight = 1;
            chromaEffect.balance = 1;
            chromaEffect.clipBlack = 0;
            chromaEffect.clipWhite = 1;
            chromaEffect.source = source;
            target.source = chromaEffect;
            seriously.go(function () { 

var finalImg = new Image();

                finalImg.onload = function () {
                    $media.attr("src", finalImg.src);
                }

                finalImg.src = canvas.toDataURL("image/png");

});