Using VideoJS as texture?

Obviously I tried to check if ChatGPT knows that but it failed too.

I wanted VideoJS since it can be easily extended and load AV1 video files.

My intention is to synchronize the frame decoding with an event and that’s not something that you can do 1:1 with video textures (you can get the approximated time but no the exact frame)

The test was:

<!DOCTYPE html>
<html>
<head>
    <title>Video Texture en BabylonJS con VideoJS</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.3.0/video-js.min.css" rel="stylesheet">
    
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
    <script src="https://vjs.zencdn.net/7.21.1/video.min.js"></script>

    <style>
        #renderCanvas {
            width: 100%;
            height: 70vh;
            touch-action: none;
        }
        
        .video-container {
            width: 100%;
            max-width: 640px;
            margin: 20px auto;
        }
        
        #videoPlayer {
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="video-container">
        <video 
            id="videoPlayer"
            class="video-js vjs-default-skin"
            controls
            preload="auto"
            width="640"
            height="360"
            data-setup="{}"
        >
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
    </div>

    <canvas id="renderCanvas"></canvas>
    
    <script>
        window.addEventListener('load', function() {
            const player = videojs('videoPlayer');
            
            if (typeof BABYLON !== 'undefined') {
                // Esperar a que el video esté listo
                player.ready(() => {
                    initBabylon(player);
                });
            } else {
                console.error('BABYLON is not loaded correctly');
            }
        });

        function initBabylon(player) {
            const canvas = document.getElementById('renderCanvas');
            const engine = new BABYLON.Engine(canvas, true);
            
            const createScene = function() {
                const scene = new BABYLON.Scene(engine);
                scene.clearColor = new BABYLON.Color4(0.2, 0.2, 0.2, 1);
                
                // Debug layer
                scene.debugLayer.show();
                
                // Camera setup
                const camera = new BABYLON.ArcRotateCamera(
                    "camera",
                    Math.PI / 2,
                    Math.PI / 2,
                    10,
                    BABYLON.Vector3.Zero(),
                    scene
                );
                camera.attachControl(canvas, true);
                
                // Lights
                const hemisphericLight = new BABYLON.HemisphericLight(
                    "hemisphericLight",
                    new BABYLON.Vector3(0, 1, 0),
                    scene
                );
                hemisphericLight.intensity = 1;
                
                // Create reference sphere (red)
                const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {
                    diameter: 1
                }, scene);
                sphere.position = new BABYLON.Vector3(2, 0, 0);
                const sphereMaterial = new BABYLON.StandardMaterial("sphereMaterial", scene);
                sphereMaterial.diffuseColor = new BABYLON.Color3(1, 0, 0);
                sphere.material = sphereMaterial;
                
                // Create box
                const box = BABYLON.MeshBuilder.CreateBox("box", {
                    size: 2
                }, scene);
                box.position = new BABYLON.Vector3(-2, 0, 0);

                // Create video material
                const videoMaterial = new BABYLON.StandardMaterial("videoMaterial", scene);
                
                // Configurar el material antes de asignar la textura
                videoMaterial.roughness = 1;
                videoMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
                videoMaterial.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2);
                
                // Crear y asignar la textura del video
                const videoElement = player.tech().el();
                const videoTexture = new BABYLON.VideoTexture(
                    "videoTexture",
                    videoElement,
                    scene,
                    true,
                    false,
                    BABYLON.VideoTexture.TRILINEAR_SAMPLINGMODE,
                    {
                        autoPlay: false,
                        loop: true,
                        autoUpdateTexture: true
                    }
                );
                
                videoMaterial.diffuseTexture = videoTexture;
                box.material = videoMaterial;
                
                // Rotación
                scene.registerBeforeRender(function() {
                    box.rotation.y += 0.005;
                });
                
                return scene;
            }
            
            const scene = createScene();
            
            engine.runRenderLoop(function() {
                scene.render();
            });
            
            window.addEventListener('resize', function() {
                engine.resize();
            });
            
            // Actualizar la textura cuando el video se reproduzca
            player.on('play', function() {
                const videoMaterial = scene.getMaterialByName("videoMaterial");
                if (videoMaterial && videoMaterial.diffuseTexture) {
                    videoMaterial.diffuseTexture.update();
                }
            });
        }
    </script>
</body>
</html>

I modified it a little but as you can see the cube disappears when you apply that video texture.

Any help is welcome!

I have a very limited knowledge of HTML/video element.
Do you see that element using your browser debugging feature?

1 Like

You can use the underlying videoElement as a source of a VideoTexture, this should work

2 Likes

As you said videoElement was the key!