2014-09-30 69 views
3

這個問題源於的HTML5視頻不打在Android手機上期。 (Three.js WebGLRenderered videos don't play on android phonesthree.js所未捕獲的SecurityError:無法執行對「WebGLRenderingContext」 texImage2D「:

而作爲mrdoob提到,video.play()應該是通過用戶發起的事件,比如點擊移動設備明確。完成這些後,我可以播放該文件。不過,我只能聽到視頻的音頻部分。屏幕仍然是空白的。此外,我在dev控制檯上看到以下異常。

未捕獲SecurityError:未能在'WebGLRenderingContext'上執行'texImage2D':視頻元素包含跨源數據,可能無法加載。 three.min.js:507

我沒有加載任何圖像通過我的代碼,你可以在下面的代碼中看到,錯誤似乎在three.min.js文件中引發。 (下面的代碼是http://threejs.org/examples/#webgl_materials_video略加修改,使其在移動設備上運行)

請注意,這僅發生在移動設備上。這個例子完美地在網絡上運行。

非常感謝您的幫助!

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>three.js webgl - materials - video</title> 
     <meta charset="utf-8"> 
     <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> 
     <style> 
      body { 
       background-color: #000; 
       color: #fff; 
       margin: 0px; 
       overflow: hidden; 
       font-family:Monospace; 
       font-size:13px; 
       text-align:center; 
       font-weight: bold; 
       text-align:center; 
      } 

      a { 
       color:#0078ff; 
      } 

      #info { 
       color:#fff; 
       position: absolute; 
       top: 0px; width: 100%; 
       padding: 5px; 
       z-index:100; 
      } 

     </style> 
    </head> 
    <body> 

     <div id="info"> 
      <a href="http://threejs.org" target="_blank">three.js</a> - webgl video demo. playing <a href="http://durian.blender.org/" target="_blank">sintel</a> trailer 
     </div> 

     <script src="js/three.min.js"></script> 

     <script src="js/shaders/ConvolutionShader.js"></script> 
     <script src="js/shaders/CopyShader.js"></script> 

     <script src="js/postprocessing/EffectComposer.js"></script> 
     <script src="js/postprocessing/RenderPass.js"></script> 
     <script src="js/postprocessing/MaskPass.js"></script> 
     <script src="js/postprocessing/BloomPass.js"></script> 
     <script src="js/postprocessing/ShaderPass.js"></script> 

     <script src="js/Detector.js"></script> 

     <video id="video" autoplay loop style="display:none"> 
      <source src="textures/sintel.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'> 
      <source src="textures/sintel.ogv" type='video/ogg; codecs="theora, vorbis"'> 
     </video> 

     <script> 

      if (! Detector.webgl) Detector.addGetWebGLMessage(); 

      var container; 

      var camera, scene, renderer, element; 

      var video, texture, material, mesh; 

      var composer; 

      var mouseX = 0; 
      var mouseY = 0; 

      var windowHalfX = window.innerWidth/2; 
      var windowHalfY = window.innerHeight/2; 

      var cube_count, 

       meshes = [], 
       materials = [], 

       xgrid = 20, 
       ygrid = 10; 

      init(); 
      animate(); 

      function init() { 

       container = document.createElement('div'); 
       document.body.appendChild(container); 

       camera = new THREE.PerspectiveCamera(40, window.innerWidth/window.innerHeight, 1, 10000); 
       camera.position.z = 500; 

       scene = new THREE.Scene(); 

       var light = new THREE.DirectionalLight(0xffffff); 
       light.position.set(0.5, 1, 1).normalize(); 
       scene.add(light); 

       renderer = new THREE.WebGLRenderer({ antialias: false }); 
       renderer.setSize(window.innerWidth, window.innerHeight); 

       element=renderer.domElement; 
       element.addEventListener('click', fullscreen, false); 

       container.appendChild(renderer.domElement); 

       video = document.getElementById('video'); 

       texture = new THREE.Texture(video); 
       texture.minFilter = THREE.LinearFilter; 
       texture.magFilter = THREE.LinearFilter; 
       texture.format = THREE.RGBFormat; 
       texture.generateMipmaps = false; 

       // 

       var i, j, ux, uy, ox, oy, 
        geometry, 
        xsize, ysize; 

       ux = 1/xgrid; 
       uy = 1/ygrid; 

       xsize = 480/xgrid; 
       ysize = 204/ygrid; 

       var parameters = { color: 0xffffff, map: texture }, 
        material_base = new THREE.MeshLambertMaterial(parameters); 

       renderer.initMaterial(material_base, scene.__lights, scene.fog); 

       cube_count = 0; 

       for (i = 0; i < xgrid; i ++) 
       for (j = 0; j < ygrid; j ++) { 

        ox = i; 
        oy = j; 

        geometry = new THREE.BoxGeometry(xsize, ysize, xsize); 

        change_uvs(geometry, ux, uy, ox, oy); 

        materials[ cube_count ] = new THREE.MeshLambertMaterial(parameters); 

        material = materials[ cube_count ]; 

        material.hue = i/xgrid; 
        material.saturation = 1 - j/ygrid; 

        material.color.setHSL(material.hue, material.saturation, 0.5); 

        mesh = new THREE.Mesh(geometry, material); 

        mesh.position.x = (i - xgrid/2) * xsize; 
        mesh.position.y = (j - ygrid/2) * ysize; 
        mesh.position.z = 0; 

        mesh.scale.x = mesh.scale.y = mesh.scale.z = 1; 

        scene.add(mesh); 

        mesh.dx = 0.001 * (0.5 - Math.random()); 
        mesh.dy = 0.001 * (0.5 - Math.random()); 

        meshes[ cube_count ] = mesh; 

        cube_count += 1; 

       } 

       renderer.autoClear = false; 

       document.addEventListener('mousemove', onDocumentMouseMove, false); 

       // postprocessing 

       var renderModel = new THREE.RenderPass(scene, camera); 
       var effectBloom = new THREE.BloomPass(1.3); 
       var effectCopy = new THREE.ShaderPass(THREE.CopyShader); 

       effectCopy.renderToScreen = true; 

       composer = new THREE.EffectComposer(renderer); 

       composer.addPass(renderModel); 
       composer.addPass(effectBloom); 
       composer.addPass(effectCopy); 

       // 

       window.addEventListener('resize', onWindowResize, false); 

      } 
      function fullscreen() { 

       video.play(); 
       console.log(video); 
        if (container.requestFullscreen) { 
        container.requestFullscreen(); 
        } else if (container.msRequestFullscreen) { 
        container.msRequestFullscreen(); 
        } else if (container.mozRequestFullScreen) { 
        container.mozRequestFullScreen(); 
        } else if (container.webkitRequestFullscreen) { 
        container.webkitRequestFullscreen(); 
        } 
       } 

      function onWindowResize() { 

       windowHalfX = window.innerWidth/2; 
       windowHalfY = window.innerHeight/2; 

       camera.aspect = window.innerWidth/window.innerHeight; 
       camera.updateProjectionMatrix(); 

       renderer.setSize(window.innerWidth, window.innerHeight); 
       composer.reset(); 

      } 

      function change_uvs(geometry, unitx, unity, offsetx, offsety) { 

       var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; 

       for (var i = 0; i < faceVertexUvs.length; i ++) { 

        var uvs = faceVertexUvs[ i ]; 

        for (var j = 0; j < uvs.length; j ++) { 

         var uv = uvs[ j ]; 

         uv.x = (uv.x + offsetx) * unitx; 
         uv.y = (uv.y + offsety) * unity; 

        } 

       } 

      } 


      function onDocumentMouseMove(event) { 

       mouseX = (event.clientX - windowHalfX); 
       mouseY = (event.clientY - windowHalfY) * 0.3; 

      } 

      // 

      function animate() { 

       requestAnimationFrame(animate); 

       render(); 

      } 

      var h, counter = 1; 

      function render() { 

       var time = Date.now() * 0.00005; 

       camera.position.x += (mouseX - camera.position.x) * 0.05; 
       camera.position.y += (- mouseY - camera.position.y) * 0.05; 

       camera.lookAt(scene.position); 

       if (video.readyState === video.HAVE_ENOUGH_DATA) { 

        if (texture) texture.needsUpdate = true; 

       } 

       for (i = 0; i < cube_count; i ++) { 

        material = materials[ i ]; 

        h = (360 * (material.hue + time) % 360)/360; 
        material.color.setHSL(h, material.saturation, 0.5); 

       } 

       if (counter % 1000 > 200) { 

        for (i = 0; i < cube_count; i ++) { 

         mesh = meshes[ i ]; 

         mesh.rotation.x += 10 * mesh.dx; 
         mesh.rotation.y += 10 * mesh.dy; 

         mesh.position.x += 200 * mesh.dx; 
         mesh.position.y += 200 * mesh.dy; 
         mesh.position.z += 400 * mesh.dx; 

        } 

       } 

       if (counter % 1000 === 0) { 

        for (i = 0; i < cube_count; i ++) { 

         mesh = meshes[ i ]; 

         mesh.dx *= -1; 
         mesh.dy *= -1; 

        } 

       } 

       counter ++; 

       renderer.clear(); 
       composer.render(); 

      } 


     </script> 

    </body> 
</html> 

回答

2

因爲這裏所討論:https://code.google.com/p/chromium/issues/detail?id=173727「視頻」屬性應該有這一套:

video.setAttribute('crossorigin', 'anonymous'); 

但這不會單獨做的伎倆。這有.load()和.play之前設置()。 .load()之後我有這個,它不起作用。所以,像這樣做:

video.src = "video/test.m4v"; 
video.src = "video/test.mp4"; 
video.setAttribute('crossorigin', 'anonymous'); 
video.load(); // must call after setting/changing source 
video.play(); 

這是解決方案對於不移動設備上,由於如上所見的安全錯誤播放專門的視頻。


只是要清楚crossorigin設置告訴瀏覽器向服務器請求使用視頻的權限。服務器仍然必須提供該權限。如果服務器不給權限設置crossorigin屬性不會讓你使用的視頻。

+0

我試過以上的解決方案,我沒有得到錯誤了,但視頻仍然不會在Chrome中播放,但在Android的Firefox中... ... – Mark 2015-03-07 14:17:13

+0

馬克,你看到任何異常/錯誤被拋出?另外three.js網站提供了大部分可以用它來做的事情的例子。找到一個這樣的,看看它是否在Chrome中工作。這可能會告訴你,如果它的鉻或代碼問題。 – sandav 2015-03-07 16:44:14

+1

我的桌面上,它工作正常。但在Android版Chrome,我看不出異常,但以下警告:WebGLRenderingContext]渲染警告:紋理綁定到紋理單元0不可渲染。它可能不是2的權力,並具有不兼容的紋理過濾或不是'紋理完成'(索引):1 WebGL:INVALID_VALUE:texImage2D:沒有視頻 – Mark 2015-03-07 16:55:41

2

這是此問題上導致谷歌,所以如果你是一個移動問題的環境之外遇到這個錯誤(這是我發現這一點),嘗試在本地服務器上運行的頁面,以解決交叉來源問題。因此,舉例來說,如果你有蟒蛇,你可以嘗試:

$ python -m SimpleHTTPServer 

從您的網頁所在的目錄,然後頁面將可從http://localhost:8000。或者使用您選擇的本地服務器。

+0

哇!非常感謝你試圖通過本地服務器運行它的「小提示」。 :-) – 2018-02-07 09:43:45

+0

* eyeroll *請原諒。這種玩世不恭是我討厭SO的原因。 – 2018-02-07 13:58:13

+0

我想你錯了。沒有玩世不恭的意圖。我是認真的。我失去了一整天的調試,並試圖找出爲什麼我的360視頻不會播放。你的帖子實際上解決了它。因此,謝謝你指出這一點。 – 2018-02-07 14:09:00

相關問題