Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

canvas.toDataURL() Security Error The operation is insecure

When I am trying to get a screenshot and save it as PNG before uploading video to server, I am having the following problem

enter image description here

I hope you can solve my problem ...

/*Output image show view*/
$('#file_browse').change(function(e){
    getVideo(this);
});

var capbtn = document.querySelector('#video_capture');
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var w, h, ratio;

video.addEventListener('loadedmetadata', function() {
    ratio = video.videoWidth / video.videoHeight;
    w = video.videoWidth - 100;
    h = parseInt(w / ratio, 10);
    canvas.width = w;
    canvas.height = h;           
}, false);

capbtn.addEventListener("click", function(){
    context.fillRect(0, 0, w, h);
    context.drawImage(video, 0, 0, w, h);
    var objImageData = canvas.toDataURL("data:image/png;");  
});

function getVideo(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
            var video = document.getElementsByTagName('video')[0];
            var sources = video.getElementsByTagName('source');
            sources[0].src = e.target.result;
            video.load();
            video.style.display="block";
        }
        reader.readAsDataURL(input.files[0]);
    }
}
<input id="video_capture" type="submit" value="Capture" />
<video id="video_view" controls>
    <source src="movie.mp4" type="video/mp4">
</video>
<canvas width="300" height="300"></canvas>
like image 899
Kemal Avatar asked Sep 09 '14 21:09

Kemal


3 Answers

Sounds like a CORS issue.

The Video is on a different origin than the web server.

If you can get the video to include an "Access-Control-Allow-Origin: *" header in the response, and you can set video.crossorigin = "Anonymous", then you can probably pull this off.

I used Charles Web Proxy to add the header to any image or video I wanted to work with.

See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

See Also https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes

Here's a Fiddle working with an Image: http://jsfiddle.net/mcepc44p/2/

var canvas = document.getElementById("canvas").getContext("2d");

var button = document.getElementById("button");

var image = new Image();
image.crossOrigin = "anonymous";  // This enables CORS
image.onload = function (event) {
    try {
        canvas.drawImage(image, 0, 0, 200, 200);
        button.download = "cat.png";
        button.href = canvas.canvas.toDataURL();        
    } catch (e) {
        alert(e);
    }
};
image.src = "https://i.chzbgr.com/maxW500/1691290368/h07F7F378/"

Is this what you're looking for?

like image 180
StephenKC Avatar answered Nov 19 '22 19:11

StephenKC


It's because of the Same Origin Policy. Basically, you're not allowed to access the video data of something loaded from another origin/site using a canvas.

Drawing video data on the canvas sets the origin-clean flag to false, which stops you from getting the image data in any way.

See toDataURL for more information.

like image 25
tcooc Avatar answered Nov 19 '22 20:11

tcooc


As well, took some experimentation to reach that conclusion, on iOS, looks the position .crossOrigin parameter position should be put before the .src

// Webkit will throw security error when image used on canvas and canvas.toDataUrl()

return new Promise((resolve, reject) => {
  let image = new Image();
  img.onload = () => {resolve(image)}
  img.src = `${url}?${Date.now()}`;
  img.crossOrigin = ""
})

// Webkit will not throw security error when image used on canvas and canvas.toDataUrl()

return new Promise((resolve, reject) => {
  let img = new Image()
  img.onload = () => {resolve(img)}
  img.crossOrigin = ''
  img.src = `${url}?${Date.now()}`
})
like image 10
Dotgreg Avatar answered Nov 19 '22 19:11

Dotgreg