Question

I have a program(Here) that converts a video blob into a gif using getusermedia. To take advantage of library (GIFEncoder) that let's me convert canvas frames into frames of a gif, I am first drawing the vide blob to the canvas using ctx.drawImage then I am drawing the frames to the gif.

Is there any more efficient way to do this?

Code:

<!Doctype html>
<html>
<head>
<style type="text/css">
    body {

    }
</style>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="LZWEncoder.js"></script>
<script type="text/javascript" src="NeuQuant.js"></script>
<script type="text/javascript" src="GIFEncoder.js"></script> 
<script type="text/javascript" src="b64.js"></script>
</head>
<body>
        <title>RecorderGif</title>
        <header>
            <h1>RecordGif</h1>
        </header>
        <article>
            <video id="video" width="320" height="200" style="display:none" autoplay=""></video>
            <section>
                <button id="btnStart">Start video</button>
                <button id="btnStop">Stop video</button>
                <button id="btnSave">Download</button>             
                            </section>
            <canvas id="canvas" width="320" height="240"></canvas>
        </article>
<script type="text/javascript">//<![CDATA[ 
var encoder = new GIFEncoder();
encoder.setRepeat(0);
encoder.setDelay(100);
encoder.start();
window.onload = function() {

//Compatibility


 navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
    var data = []
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        video = document.getElementById("video"),
        btnStart = document.getElementById("btnStart"),
        btnStop = document.getElementById("btnStop"),
        btnSave = document.getElementById("btnSave")
        videoObj = {
            video: true,
            };

    btnStart.addEventListener("click", function() {
        var localMediaStream;

        if (navigator.getUserMedia) {
            navigator.getUserMedia(videoObj, function(stream) {              
                video.src = (navigator.webkitGetUserMedia) ? window.webkitURL.createObjectURL(stream) : stream;
                localMediaStream = stream;
                var addFrame = setInterval(function() {
                data.push(canvas.toDataURL('image/png'))
            },100);

            }, function(error) {
                console.error("Video capture error: ", error.code);
            });

            btnStop.addEventListener("click", function() {
                clearInterval(addFrame)
                localMediaStream.stop();

            });
            btnSave.addEventListener("click", function() {
                for (var i = 0; i < data.length; i++) {
                    var frame = new Image();
                    frame.src=data[i]
                    context.drawImage(frame,0,0)
                    encoder.addFrame(context);

                };
                encoder.finish();
                var binary_gif = encoder.stream().getData() //notice this is different from the as3gif package!
                var data_url = 'data:image/gif;base64,'+encode64(binary_gif);
                var gif = window.open('about:blank','','width=320,height=240')
                gif.document.location.href=data_url
            });

            setInterval(function() {context.drawImage(video, 0, 0, 320, 240)},100);
        }

    });
};
//]]>  
</script>
</body>
</html>
Was it helpful?

Solution

As there is no native support for GIF encoding in the browsers you very much depend on JavaScript solutions such as the one you're using.

The only way to improve the encoding is to go through the source code and see if you can optimize parts of it such as utilizing typed arrays (if not), conform to engine specifics knowing what works well with the engine compilers (ie. things like using simulated types, full constructor, non-morphing objects etc.).

Another tip is to encode the GIF when the video is not playing (stepping it forward "manually" for each frame using currentPosition and the event for it) and with an off-screen video element. This may leave some more resources for the browser and the engine to run the script faster (depending partly on the system and its support for hardware decoding video - there will still be an overhead updating the video on-screen which may or may not affect the encoding process).

My 2.5 cents..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top