edoloughlin
edoloughlin

Reputation: 5891

HTML5 FileWriter InvalidStateError

I'm using a canvas element to tile a number of video elements together in real time, which works fine. I'm also trying to grab the canvas data and write it to a file periodically, so I can encode a video from the file of raw frames when the video elements have finished playing.

I've got a function called on a timer interval every 40ms (giving 25fps) that roughly looks as follows (there's too much code to paste in its entirety):

function saveFrame() {

  // code to copy from video elements to my canvas...
  // ...

  // Get the canvas image data and write it to a file
  var imgData = canvasContext.getImageData(0, 0,
                                           canvasElement.width,
                                           canvasElement.height);
  var b = new Blob([imgData], {type: 'application/octet-binary'});

  // Write the blob to a file I previously opened
  // fileWriter is a FileWriter that I obtained and saved previously
  fileWriter.write(b);
}

setInterval(function() {
              saveFrame();
            }, 40);

Every time I hit the fileWriter.write(blob) statement I get the following error:

Uncaught InvalidStateError: An operation that depends on state cached in an interface object was made but the state had changed since it was read from disk.

Is this a timing issue? Can't the file writer API support writing every 40ms?

Upvotes: 1

Views: 4431

Answers (1)

Alex
Alex

Reputation: 11245

From docs of method write:

If readyState is WRITING, throw an InvalidStateError and terminate this series of steps.

So you get InvalidStateError error because your fileWriter still write previous data.

Try to use writeend event and setTimeout:

function saveFrame() {
    var imgData = canvasContext.getImageData(0, 0,
        canvasElement.width,
        canvasElement.height);
    var b = new Blob([imgData], {
        type: 'application/octet-binary'
    });
    fileWriter.write(b);
}

fileWriter.writeend = function () {
    setTimeout(saveFrame, 40)
}

saveFrame();

Upvotes: 1

Related Questions