2017-09-18 6 views
-1

Vu le codeComment éviter SecurityError: L'opération n'est pas sécurisée. à Firefox lors de l'utilisation de .mozCaptureStream et MediaRecorder?

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
</head> 
 

 
<body> 
 
    <video width="320" height="280"></video> 
 
    <script> 
 
     const video = document.querySelector("video"); 
 
     const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10"; 
 
     let recorder; 
 
     video.oncanplay =() => { 
 
     video.play(); 
 
     const mediaStream = video.captureStream(); 
 
     recorder = new MediaRecorder(mediaStream); 
 
     recorder.ondataavailable = event => 
 
      console.log(URL.createObjectURL(event.data)); 
 
     
 
     recorder.start(); 
 
     } 
 

 
     video.onpause =() => recorder && recorder.stop(); 
 

 
     video.src = src; 
 
    </script> 
 
</body> 
 

 
</html>

navigateur Chrome capture la lecture de l'élément <video> en utilisant .captureStream(), MediaRecorder() et les journaux Blob URL de résultant Blob à dataavailable cas de MediaRecorder exemple.

Dans le navigateur Firefox qui implémente actuellement .mozCaptureStream() une erreur est renvoyée recorder.start() appel SecurityError: The operation is insecure. et à recorder.stop() appel InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. Les erreurs sont apparemment dues à Security Considerations de Media Capture from DOM Elements.

Comment éviter les erreurs décrites ci-dessus et atteindre le même résultat que les navigateurs Chromium et Chrome implémentés dans le navigateur Firefox?

+0

Cela ressemble en fait à un bug de chrome! Le fichier 'crossOrigin' de la vidéo devrait être réglé sur' 'anonyme '' pour que votre code ne puisse pas être lancé (notez que FF en effet [a un bug à ce sujet] (https://bugzilla.mozilla.org/show_bug.cgi?id=1341016), mais au moins, ils sont ** trop ** sécurisés). Notez également que vous ne pouvez pas attendre que 'mozCaptureStream' fonctionne de la même manière que' captureStream', c'est pourquoi il est toujours préfixé/ – Kaiido

+0

@Kaiido Aucune erreur n'est levée sur Chrome ou Chrome. Solution de contournement composée tout en continuant à chercher une solution pour concaténer les enregistrements créés en utilisant 'MediaRecorder'. Si l'attribut 'crossOrigin' permet également d'enregistrer la lecture de média sans erreur, pouvez-vous poster une réponse décrivant la solution? – guest271314

+0

Comme indiqué dans le bogue FF auquel je suis lié, FF ne permet pas MediaElement servi avec les en-têtes CORS corrects, donc tant qu'il n'est pas corrigé, il ne fonctionnera pas comme une solution de contournement. Mais ce que je dis c'est que c'est un bug de sécurité dans le chrome (je les laisse maintenant tout de suite.) Ils ne devraient pas laisser capturerStream être appelé sur un mediaElement servi sans les en-têtes CORS. Cela va à l'encontre de toutes les autres mesures de sécurité de CORS (par exemple dans webAudio ou API de canevas) Vous devriez donc avoir l'attribut 'cross-origin' sur votre mediaElement. – Kaiido

Répondre

0

Vous pouvez utiliser XMLHttpRequest() ou fetch() pour obtenir une représentation Blob de ressource média, créer un Blob URL de Blob en utilisant URL.createObjectURL()

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
</head> 
 

 
<body> 
 
    <video width="320" height="280"></video> 
 
    <script> 
 
    (async() => { 
 
     const video = document.querySelector("video"); 
 
     const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10"; 
 
     const url = new URL(src); 
 
     let recorder; 
 
     video.oncanplay =() => { 
 
     // note, audio is not output here 
 
     video.play(); 
 
     const mediaStream = video.mozCaptureStream(); 
 
     recorder = new MediaRecorder(mediaStream); 
 
     recorder.ondataavailable = event => 
 
      // audio is output at resulting `Blob URL`   
 
      console.log(URL.createObjectURL(event.data)); 
 

 
     recorder.start(); 
 
     } 
 

 
     video.onpause =() => recorder && recorder.stop(); 
 

 
     const blob = await fetch(url).then(response => response.blob()); 
 
     video.src = URL.createObjectURL(blob) + url.hash; 
 

 
    })(); 
 
    </script> 
 
</body> 
 

 
</html>

alternativement, nous pouvons enregistrer la lecture multimédia de MediaSource() ensemble comme .src de HTMLMediaElement en ajoutant une représentation ArrayBuffer de la ressource média au SourceBuffer de MediaSource exemple

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
</head> 
 

 
<body> 
 
    <video width="320" height="280"></video> 
 
    <script> 
 
    (async() => { 
 
    // SecurityError: The operation is insecure. 
 
    // InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable 
 
    const video = document.querySelector("video"); 
 
    const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10"; 
 
    const url = new URL(src); 
 
    const mediaSource = new MediaSource(); 
 
    const mimeCodec = "video/webm;codecs=opus"; 
 
    video.src = URL.createObjectURL(mediaSource); 
 
    mediaSource.onsourceopen = async() => { 
 
    const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); 
 
    const mediaBuffer = await fetch(url).then(response => response.arrayBuffer()); 
 
    sourceBuffer.appendBuffer(mediaBuffer); 
 
    } 
 
    let recorder; 
 
    video.oncanplay =() => { 
 
    // note, audio is not output here 
 
    video.play(); 
 
    const mediaStream = video.mozCaptureStream(); 
 
    recorder = new MediaRecorder(mediaStream); 
 
    recorder.ondataavailable = event => 
 
     // audio is output at resulting `Blob URL` 
 
     console.log(URL.createObjectURL(event.data)); 
 
     
 
    recorder.start(); 
 
    } 
 

 
    video.ontimeupdate =() => { 
 
    if (Math.floor(video.currentTime) === Number(url.hash.split(",").pop())) { 
 
     video.ontimeupdate = null; 
 
     video.pause(); 
 
     mediaSource.endOfStream(); 
 
    } 
 
    } 
 

 
    video.onpause =() => recorder && recorder.stop(); 
 

 
})(); 
 

 
</script> 
 

 
</body> 
 
</html>

On peut en outre utiliser une fonction d'aide pour utiliser le même code à chaque Chrome, le navigateur Chrome et le navigateur Firefox, par exemple, voir Answer à captureStream() on dynamically created video element.