0

我即将使用 cocoon.js 和 three.js 为 Android 和 IOS 创建一个具有设备方向控制的全景 360 视频播放器。

我已经在threejs.org 的示例上成功构建了演示,但遇到了一个问题:我的原始测试视频文件是4000x1618 分辨率,只有30 秒长。加载它会发出声音但没有图片。但是,如果我尝试将文件转换为 720x292,那么它在 android 和 ios 上都可以正常工作!不幸的是,这个较低的分辨率。视频文件质量太差,但是如果我尝试加载一个更大的文件,它将再次发出声音而没有图像。

开始电影时,我在 adb logcat 中发现了这些错误日志:

E/OMXNodeInstance(  124): setParameter(4b:Nvidia.h264.decode, ParamPortDefinition(0x2000001)
W/ACodec  (  124): [OMX.Nvidia.h264.decode] setting nBufferCountActual to 13 failed: -1010

我的代码:

<!DOCTYPE html>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src='cordova.js'></script>
<script src='js/three.js'></script>
<script src='js/OrbitControls.js'></script>
<script src='js/PointerLockControls.js'></script>
<script src='js/DeviceOrientationControls.js'></script>
<script src='js/stats.min.js'></script>
<body style='margin: 0px;; overflow: hidden; text-align:center;'>
<div id="btn" style='background: red; width: 200px; height: 200px; position: absolute; z-index: 1000;' onclick="start_video()">START VIDEÓ</div>
<script>

var video = document.createElement('video');
video.loop = true;
video.src = 'heroes-new-720p.mp4';

function start_video() {
	document.getElementById('btn').style.visibility = 'hidden';
	video.play();
}

window.addEventListener('load', function() {
	var renderer	= new THREE.WebGLRenderer({
		antialias	: true,
	});
	renderer.setClearColor(new THREE.Color('lightgrey'), 1)
	renderer.setSize( window.innerWidth, window.innerHeight );
	document.body.appendChild( renderer.domElement );
	var onRenderFcts= [];
	var scene	= new THREE.Scene();
	var camera	= new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000);
	camera.position.z = 3;

	var texture = new THREE.VideoTexture( video );
	texture.minFilter = THREE.LinearFilter;
	texture.format = THREE.RGBFormat;
	texture.generateMipmaps = false;

	var controls	= new THREE.OrbitControls(camera)
	controls.target.copy(scene.position)
	function onDeviceOrientation(event){
		if( !event.alpha )	return;
		controls.enabled	= false
		controls = new THREE.DeviceOrientationControls(camera);
		controls.connect();
		window.removeEventListener('deviceorientation', onDeviceOrientation, false);
		renderer.domElement.addEventListener('click', function(){
			var domElement	= renderer.domElement
			if(domElement.requestFullscreen)		domElement.requestFullscreen();
			else if(domElement.msRequestFullscreen) 	domElement.msRequestFullscreen();
			else if(domElement.mozRequestFullScreen)	domElement.mozRequestFullScreen();
			else if(domElement.webkitRequestFullscreen)	domElement.webkitRequestFullscreen();
		}, false);
	}
	window.addEventListener('deviceorientation', onDeviceOrientation, false);
	onRenderFcts.push(function(){
		controls.update()
	})

;(function(){
	var geometry	= new THREE.SphereGeometry(10, 32, 16);
	var material	= new THREE.MeshBasicMaterial({
                // opacity         : 0.5,
                // transparent     : true,
                // side            : THREE.DoubleSide,
				map: texture
        }); 
	var mesh	= new THREE.Mesh( geometry, material );
	mesh.scale.x	= -1
	scene.add( mesh );
})()


	onRenderFcts.push(function(){
		onWindowResize();
		renderable();
	})
	
	function renderable() {
		if ( video.readyState === video.HAVE_ENOUGH_DATA )  {
			renderer.render( scene, camera );
		}				
	}
	
	function onWindowResize(){
		renderer.setSize( window.innerWidth, window.innerHeight )
		camera.aspect	= window.innerWidth / window.innerHeight
		camera.updateProjectionMatrix()		
	}
	window.addEventListener('resize', onWindowResize, false)
	
	// run the rendering loop
	var lastTimeMsec= null
	requestAnimationFrame(function animate(nowMsec){
		// keep looping
		requestAnimationFrame( animate );
		// measure time
		lastTimeMsec	= lastTimeMsec || nowMsec-1000/60
		var deltaMsec	= Math.min(200, nowMsec - lastTimeMsec)
		lastTimeMsec	= nowMsec
		// call each update function
		onRenderFcts.forEach(function(onRenderFct){
			onRenderFct(deltaMsec/1000, nowMsec/1000)
		})
	})
})
</script>
</body>

更新:从那时起,我发现问题不在于视频分辨率本身,而在于尺寸。我创建了一个运行良好的 1920x1080 原始视频版本,所以唯一困扰我的是质量。即使是 16000 kbps 的全高清视频在我的 Nexus 7 和 ipad 4 上看起来也很像素化,我相信它应该会更好......

4

2 回答 2

2

好吧,最后我发现我的测试设备(Moto G、Nexus 7、iPad4、HTC m8)都不能在大于 1920x1080 的 three.js 球体中将视频作为纹理处理。我不确定原因,但我发现了一篇关于全景视频分辨率的非常有趣的文章,它也揭示了质量问题。

简而言之:在 360 度视频中,120 度的全高清视频的 2K 宽度变为 682 像素宽度,所以这就是我发现我的视频质量不令人满意的原因。

如果有人有兴趣,这里是文章:

http://www.360heros.com/2015/02/4k-vr-360-video-what-is-it-and-how-can-i-produce-it/

于 2016-03-22T20:28:18.577 回答
0

它与threejs 或cocoonjs 无关。高于 1080p 的分辨率在移动屏幕上没有意义(您的用例除外),因此硬件不支持它(在大多数情况下)。您可以检查的是 h264 配置文件是否适合您的视频文件的分辨率。特殊的iphone非常挑剔,以防编码错误!

于 2016-03-23T20:52:40.653 回答