0

Is there a way to play 360 video with Three js coming from m3u8 file?

I found a similar question here but no answer: https://github.com/mrdoob/three.js/issues/8216

https://threejs.org/examples/webgl_video_panorama_equirectangular.html

I have used the code from thee website for playing 360 video and this work fine when normal mp4 video url is used but when I try to include m3u8 then it fails with error.MEDIA_ERR_SRC_NOT_SUPPORTED:

  The video could not be loaded, either because the server or network failed or because the format is not supported.

Here is the code:

<video id="video" width=960 height=540 style="display:none">
  <source src="https://bitmovin.com/player-content/playhouse-vr/m3u8s/105560.m3u8" type="application/x-mpegURL">
</video>



        var camera, scene, renderer;

        var isUserInteracting = false,
            lon = 0, lat = 0,
            phi = 0, theta = 0,
            distance = 50,
            onPointerDownPointerX = 0,
            onPointerDownPointerY = 0,
            onPointerDownLon = 0,
            onPointerDownLat = 0;

        init();
        animate();

        function init() {

            var container, mesh;

            container = document.getElementById( 'container' );

            camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
            camera.target = new THREE.Vector3( 0, 0, 0 );

            scene = new THREE.Scene();

            var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
            // invert the geometry on the x-axis so that all of the faces point inward
            geometry.scale( - 1, 1, 1 );

            var video = document.getElementById( 'video' );
            video.play();

            var texture = new THREE.VideoTexture( video );
            var material = new THREE.MeshBasicMaterial( { map: texture } );

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

            scene.add( mesh );

            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            document.addEventListener( 'mousedown', onDocumentMouseDown, false );
            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'mouseup', onDocumentMouseUp, false );
            document.addEventListener( 'wheel', onDocumentMouseWheel, false );

            //

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

        }

        function onWindowResize() {

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

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

        }

        function onDocumentMouseDown( event ) {

            event.preventDefault();

            isUserInteracting = true;

            onPointerDownPointerX = event.clientX;
            onPointerDownPointerY = event.clientY;

            onPointerDownLon = lon;
            onPointerDownLat = lat;

        }

        function onDocumentMouseMove( event ) {

            if ( isUserInteracting === true ) {

                lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
                lat = ( onPointerDownPointerY - event.clientY ) * 0.1 + onPointerDownLat;

            }

        }

        function onDocumentMouseUp() {

            isUserInteracting = false;

        }

        function onDocumentMouseWheel( event ) {

            distance += event.deltaY * 0.05;

            distance = THREE.MathUtils.clamp( distance, 1, 50 );

        }

        function animate() {

            requestAnimationFrame( animate );
            update();

        }

        function update() {

            lat = Math.max( - 85, Math.min( 85, lat ) );
            phi = THREE.MathUtils.degToRad( 90 - lat );
            theta = THREE.MathUtils.degToRad( lon );

            camera.position.x = distance * Math.sin( phi ) * Math.cos( theta );
            camera.position.y = distance * Math.cos( phi );
            camera.position.z = distance * Math.sin( phi ) * Math.sin( theta );

            camera.lookAt( camera.target );

            renderer.render( scene, camera );

        }

    

m3u8 plays on chrome (and some other browsers). I have been using it for years. The problem is in combining m3u8 format with three js

m3u8 works as can be seen here: https://hls-js.netlify.app/demo/ enter this url : https://bitmovin.com/player-content/playhouse-vr/m3u8s/105560.m3u8

Toniq
  • 4,492
  • 12
  • 50
  • 109
  • Does this answer your question? [How to play m3u8 playlist in all PC browsers?](https://stackoverflow.com/questions/5516247/how-to-play-m3u8-playlist-in-all-pc-browsers) – M - Jul 15 '20 at 23:39
  • This isn't a three.js issue. I think you have your answer right there: The format is not supported on that browser [because browser support is very poor](https://caniuse.com/#search=m3u8). If I'm not mistaken, the m3u8 file is a text file, so maybe you could open it and see what URLs are inside, you might find video files that *are* supported. – M - Jul 15 '20 at 23:41
  • No, this is not an answer. m3u8 plays on chrome (and some other browsers). I have been using it for years. The problem is in combining m3u8 format with three js, I have edited the question. – Toniq Jul 16 '20 at 09:28
  • Right, the ` – M - Jul 16 '20 at 19:15

1 Answers1

0

HLS (.m3u8 file type) and MPEG DASH (.mpd file type) are adaptive bit rate streaming protocols (ABR).

ABR creates multiple bit rate versions of your content and chunks them, so the client can choose the next chunk from the best bit rate for the device and current network conditions (https://stackoverflow.com/a/42365034/334402).

To play a HSL or DASH file you typically use a Javascript based video player, which in turn will leverage the HTML5 Media Soure Extension API - HTML5 MSE:

The Javascript video player downloads the chunks of video, choosing the most appropriate bit rate for each chunk, and assembles them and passes them to the HTML5 video player.

Many Javascript Video Players will support 360 video and you may find it is easier to simply integrate one of these into your project. As an example, extensions to the commonly used videoJS player will support 360 video:

Mick
  • 24,231
  • 1
  • 54
  • 120