Black frame at start of video

I have a video texture set up on an image element within a 2d screen. Before the video starts you do get one black frame which I guess is from the material. Is there any way of losing that first frame?


You will have to wait for the first frame of the video to be loaded. Here is a quick example based on the tutorial project:

The video element has an event fired for the first frame being loaded:

We can listen for that and send the video texture to the material via the event and then start playing the video when the video element can be played through:

    video.addEventListener('loadeddata', function (e) {, this.videoTexture);
    video.addEventListener('canplaythrough', function (e) {;

It might be best to either add/load the video before the scene is loaded or do what YouTube does and use a thumbnail image as placeholder until the video is played


Hi, I tried to add the event listener after a button click but when i add it, the video doesn’t load anymore so i want to know where i need to put it in my script to make it work.

var Videotexture = pc.createScript('videotexture');

Videotexture.attributes.add('materials', {
    type: 'asset',
    assetType: 'material',
    array: true

Videotexture.attributes.add('videoAsset', {
   type: 'asset',
   assetType: 'audio',

Videotexture.attributes.add('Button', {
   type: 'entity',

Videotexture.attributes.add('mediaPlayer', { type: 'entity' });

// initialize code called once per entity
Videotexture.prototype.initialize = function() {
    var app =;
    // Create a texture to hold the video frame data            
    var videoTexture = new pc.Texture(app.graphicsDevice, {
        format: pc.PIXELFORMAT_R5_G6_B5,
        autoMipmap: false
    videoTexture.minFilter = pc.FILTER_LINEAR;
    videoTexture.magFilter = pc.FILTER_LINEAR;
    videoTexture.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
    videoTexture.addressV = pc.ADDRESS_CLAMP_TO_EDGE;

    // Create HTML Video Element to play the video
    var video = document.createElement('video');
    video.addEventListener('canplay', function (e) {
    // This is how to get the full URL path to the asset.
    video.src = this.videoAsset.getFileUrl();
    video.crossOrigin = 'anonymous';
    video.loop = false;

    // Get the material that we want to play the video on and assign the new video
    // texture to it.
    for (var i = 0; i < this.materials.length; i++) {
        var material = this.materials[i].resource;
        material.emissiveMap = videoTexture;

    this.videoTexture = videoTexture;

    //, function () {;  }, this);
    if (pc.platform.ios) {
        // critical for iOS or the video won't initially play, and will go fullscreen when playing
        video.playsInline = true;
        this.Button.element.on('click', function () {
            this.Button.enabled = false; 
            this.mediaPlayer.enabled = true;
        }, this);
    //this.Button.script.buttonStartVideo.on('move', function () {; }, this);
    this.upload = true;

// update code called every frame
Videotexture.prototype.update = function(dt) {
    // Upload the video data to the texture every other frame
    this.upload = !this.upload;
    if (this.upload) {

Sorry, I’m a little lost with some Playcanvas stuff, but thanks for all the help !

Sorry, I don’t understand the question? Sharing a project with the issue will help

It’s an ar project so it work only on phone :

in sprite, you have the image who you need to target in .jpg

Can you share a smaller example project that has the same issue without the need for AR please? And describe what you are seeing the issue as and what you expect or what to see?

I’ve created a fork with just the video and button from your project to isolate the issue and it looks like it works as expected for me:

Can you disable the fade script because it hide the video for 1 second.
It was a bad tricks to hide the black frame :sweat_smile:

Then if it’s works well for you, i don’t understand why is not working for me :thinking:

I still don’t see it

One thing you can try is to upload the texture immediately when the button is pressed or wait a few frames before enabling the plane.

eg :

    this.Button.element.on('click', function () {; 
        this.Button.enabled = false; 
        this.mediaPlayer.enabled = true;

        // Do an upload immediately to try to avoid black frame at start
    }, this);

Try the project again and see if you can see the black frame:

That doesn’t do anything but i decide to use the video of you’re project to test and it’s work !

The problem is from my video, i will look for it, thanks for your help !

My bad it’s gone black again for both video, i’m quite confused :confused: :joy:

One day, I will find the solution !

Maybe it’s because the video still loading ?

Hi @Enivort! I think it’s indeed a loading issue. I’m on a bad network at the moment and I see the black screen for almost 10 seconds.

Okay thanks for the answer.

The black screen look like to be only on the phone, when i open it on computer the video start directly so maybe it depend of device too

It’s very possible that the video is not ready yet by the time play is called or needs to buffer. In which case try the project again

The button is inactive until the video is ready (button turns blue).

No blue button and still a black screen for me.

You should see something like this depending on the network speed:

Ah, the code I used was input on the element, not button.

Fixed now:

Right now the button is not working at all. (No blue color).

The video is not loading for you then or loading so slowly, it’s waiting for the whole video to download/is blocked on your device for some reason. A bit surprised given it’s only 3.4MB :thinking: