這個問題源於的HTML5視頻不打在Android手機上期。 (Three.js WebGLRenderered videos don't play on android phones)three.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>
我試過以上的解決方案,我沒有得到錯誤了,但視頻仍然不會在Chrome中播放,但在Android的Firefox中... ... – Mark 2015-03-07 14:17:13
馬克,你看到任何異常/錯誤被拋出?另外three.js網站提供了大部分可以用它來做的事情的例子。找到一個這樣的,看看它是否在Chrome中工作。這可能會告訴你,如果它的鉻或代碼問題。 – sandav 2015-03-07 16:44:14
我的桌面上,它工作正常。但在Android版Chrome,我看不出異常,但以下警告:WebGLRenderingContext]渲染警告:紋理綁定到紋理單元0不可渲染。它可能不是2的權力,並具有不兼容的紋理過濾或不是'紋理完成'(索引):1 WebGL:INVALID_VALUE:texImage2D:沒有視頻 – Mark 2015-03-07 16:55:41