javascript - Safari 中的 HTML5 视频纹理

标签 javascript safari html5-canvas html5-video webgl

是否可以在 Safari 中使用视频作为 webGL 的纹理(我什至不是在谈论 iOS Safari)?我无法让它工作。这是我能想出的最简单的重现代码:https://jsfiddle.net/bmkb6r9h/3/而且它不起作用here要么。

一旦视频源来自另一个域或子域并出现 SecurityError: DOM Exception 18: A attempt was made to breakthrough the security policy of the user agent 附加视频时,它就会失败使用 texImage2D 的纹理。

这是我的代码(抱歉,它有点长,但这就是 webGL 的运行方式)也很高兴收到有关如何改进 webGL 的评论。我从 https://github.com/hawksley/eleVR-Web-Player 中获取了代码这是对 360 度全景视频播放器的精彩介绍。

// get DOM elements
videoContainer = document.getElementById('video-container');
video = document.getElementById('video');
canvas = document.getElementById('glcanvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// load the video, and play on ready
video.load();
video.oncanplaythrough = function() {
  video.play();
  drawScene();
};

gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

// create and attach the shader program to the webGL context
var attributes, uniforms, program;
var attachShader = function(params) {
  // compile the shaders from the shaders scripts
  var getShaderByName = function(id) {
    var shaderScript = document.getElementById(id);

    var theSource = "";
    var currentChild = shaderScript.firstChild;

    while(currentChild) {
      if (currentChild.nodeType === 3) {
        theSource += currentChild.textContent;
      }
      currentChild = currentChild.nextSibling;
    }

    var result;
    if (shaderScript.type === "x-shader/x-fragment") {
      result = gl.createShader(gl.FRAGMENT_SHADER);
    } else {
      result = gl.createShader(gl.VERTEX_SHADER);
    }
    gl.shaderSource(result, theSource);
    gl.compileShader(result);

    if (!gl.getShaderParameter(result, gl.COMPILE_STATUS)) {
      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(result));
      return null;
    }
    return result;
  };

  fragmentShader = getShaderByName(params.fragmentShaderName);
  vertexShader = getShaderByName(params.vertexShaderName);

  program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    alert("Unable to initialize the shader program: " + gl.getProgramInfoLog(program));
  }
  gl.useProgram(program);

  // get the location of attributes and uniforms
  attributes = {};
  for (var i = 0; i < params.attributes.length; i++) {
    var attributeName = params.attributes[i];
    attributes[attributeName] = gl.getAttribLocation(program, attributeName);
    gl.enableVertexAttribArray(attributes[attributeName]);
  }
  uniforms = {};
  for (i = 0; i < params.uniforms.length; i++) {
    var uniformName = params.uniforms[i];
    uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
    gl.enableVertexAttribArray(attributes[uniformName]);
  }
};
attachShader({
  fragmentShaderName: 'shader-fs',
  vertexShaderName: 'shader-vs',
  attributes: ['aVertexPosition'],
  uniforms: ['uSampler'],
});

// some webGL initialization
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clearDepth(1.0);
gl.disable(gl.DEPTH_TEST);

positionsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionsBuffer);
var positions = [
  -1.0, -1.0,
  1.0, -1.0,
  1.0,  1.0,
  -1.0,  1.0,
];
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

  verticesIndexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, verticesIndexBuffer);
  var vertexIndices = [
  0,  1,  2,      0,  2,  3,
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
              new Uint16Array(vertexIndices), gl.STATIC_DRAW);

texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);

// update the texture from the video
updateTexture = function() {
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  // the next line fails in Safari if the video is coming from another domain or subdomain
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB,
                gl.UNSIGNED_BYTE, video);
  gl.bindTexture(gl.TEXTURE_2D, null);
};

// draw stuff in the canvas
drawScene = function() {
  updateTexture();
  gl.useProgram(program);
  gl.bindBuffer(gl.ARRAY_BUFFER, positionsBuffer);
  gl.vertexAttribPointer(attributes['aVertexPosition'], 2, gl.FLOAT, false, 0, 0);

  // Specify the texture to map onto the faces.
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.uniform1i(uniforms['uSampler'], 0);

  // Draw
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, verticesIndexBuffer);
  gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
  // keep looping
  requestAnimationFrame(drawScene);
};
<!-- Fragmend shader program -->
<script id="shader-fs" type="x-shader/x-fragment">
varying mediump vec2 vDirection;
uniform sampler2D uSampler;
void main(void) {
  gl_FragColor = texture2D(uSampler, vec2(vDirection.x * 0.5 + 0.5, vDirection.y * 0.5 + 0.5));
}
</script>

<!-- Vertex shader program -->
<script id="shader-vs" type="x-shader/x-vertex">
attribute mediump vec2 aVertexPosition;
varying mediump vec2 vDirection;
void main(void) {
  gl_Position = vec4(aVertexPosition, 1.0, 1.0) * 2.0;
  vDirection = aVertexPosition;
}
</script>

<div id="video-container" style="width: 100vw; height: 100vh;">
  <canvas id="glcanvas"></canvas>
  <video preload="auto" id="video" loop="true" webkit-playsinline crossOrigin="anonymous" style="    width: 300px; height: 200px;" controls>
    <source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
  </video>
</div>

在 Chrome/Firefox 中运行完美。

最佳答案

这是 Safari 中的一个错误。 Safari 尚不支持视频的 CORS(跨源支持)。参见 this webkit bug .

Video does work in WebGL in Safari if the video is from the same origin .

关于javascript - Safari 中的 HTML5 视频纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35590059/

相关文章:

javascript - D3 工具提示未在 Firefox 中显示

css - chrome 和 safari 上的 z-index 问题(firefox 没问题)

javascript - 使用 node.destroy() 时如何删除 konva 形状/图像

javascript - document.documentElement.appendChild() 不起作用

javascript - 仅在数据加载后显示子组件

javascript - 正则表达式(javascript),调试器,Regex101

javascript - Chrome 不支持此处插入图片

macos - 如何在 OS X 上的旧版 Safari 中测试我的网站?

javascript - 使用 recordrtc 将 Canvas 图像录制到视频文件

javascript - Canvas 填充图表中的区域和圆圈