Trying to play audio from source on my VideoPlayer

Basically i’m trying to do a videoplayer component similar to unity. It would be really helpful if i could play a video with the audio source of my choice. This is my code and i’m trying to play a video mute it’s audio and play my own source but i can’t seem to find anything about my problem.

Thanks in advance

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

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

Videotexture.attributes.add('videoAsset', {
   type: 'asset',
   assetType: 'audio',
});
//Video Controls declaration

Videotexture.attributes.add('PlayfromURL', {type: 'string'});
Videotexture.attributes.add('playfromURL_Button',{ type:'entity'});
Videotexture.attributes.add('playFromFileButton',{ type:'entity'});
Videotexture.attributes.add('ResumeButton',{type: 'entity' });
Videotexture.attributes.add('pauseButton',{type: 'entity' });
Videotexture.attributes.add('skipForwardButton',{type: 'entity'});
Videotexture.attributes.add('skipBackwardButton',{type: 'entity'});
Videotexture.attributes.add('loopEnableButton',{type: 'entity'});
Videotexture.attributes.add('loopDisableButton',{type: 'entity'});
Videotexture.attributes.add('muteOnButton', {type: 'entity'});
Videotexture.attributes.add('muteOffButton', {type: 'entity'});
//Videotexture.attributes.add('setCameraNearPlane',{type: 'entity'});
Videotexture.attributes.add('frameSkipFactor',{type:'number'});
Videotexture.attributes.add('PlayVideoFullScreen', {type: 'entity' });

//Audio
Videotexture.attributes.add('SoundAsset', {type:'asset' , typeAsset: 'audio'});
Videotexture.attributes.add('PlayAudioOnly', {type: 'entity'});
Videotexture.attributes.add('PlayfromDirect', {type: 'entity'});
// initialize code called once per entity
// 


Videotexture.prototype.initialize = function() {
    var app = this.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) {
        videoTexture.setSource(video);
    });
    
    // This is how to get the full URL path to the asset.
    video.src = this.videoAsset.getFileUrl();
    //video.src = "https://s3-eu-west-1.amazonaws.com/static.playcanvas.com/video/playcanvas-web-small.mp4";
    video.crossOrigin = 'anonymous';    
    video.loop = true;
   

    // 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;
        material.update();
    }

    this.videoTexture = videoTexture;
//play video file on click method
    //this.app.mouse.once(pc.EVENT_MOUSEDOWN, function () { video.play(); }, this);
   this.playFromFileButton.button.on('click', function(event) {
       this.app.root.findByName('Plane').enabled=true;
       //video.src =this.videoAsset.getFileUrl();
       video.play();
       //video.controls = true; apply video controls for the player
    }, this);
    this.upload = true;
    
    //pause button method
    this.pauseButton.button.on('click', function(event) {
       video.pause();
    }, this);
    this.upload = false;
    
    //resume button
    //
    this.ResumeButton.button.on('click', function(event) {
      video.play();
    }, this);
    this.upload = true;
    
//skip forward button method
    this.skipForwardButton.button.on('click', function(event) {
       video.currentTime +=this.frameSkipFactor;
        console.log('hits here');
        //seconds += this.frameSkipFactor;
        console.log(video.currentTime);
    },this);
    
    //skip back button method
    this.skipBackwardButton.button.on('click', function(event) {  
     video.currentTime -=this.frameSkipFactor;
    },this);
    
    //loop enable
    this.loopEnableButton.button.on('click', function(event){               
        video.loop=true;
    },this);
    
  //loop disable
  
    this.loopDisableButton.button.on('click', function(event){
        video.loop=false;
    },this);
    
    //mute on
    this.muteOnButton.button.on('click', function(event){
        video.volume=0;
        },this);
    
//mute off
     this.muteOffButton.button.on('click', function(event){
        video.volume=1;
        },this);
    
    //play from url method
   this.playfromURL_Button.button.on('click', function(event) { 
        this.app.root.findByName('Plane').enabled=true;
        //this.root.model.enabled=true;
       video.src = this.PlayfromURL;
       video.play();
        },this);
    this.upload=true;
    
  //sound source
  //Audio Source
  
    this.PlayAudioOnly.button.on('click', function(event) { 
        video.play();
       video.volume=0;
        this.entity.sound.slot('Slot 1').play();
        this.entity.sound.volume=1;
        console.log('sound play');
        },this);
          
};
 
// 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) {
        this.videoTexture.upload();
    }
    
    //if(app.keyboard.wasPressed(pc.KEY_END))
       //{
           // this.entity.sound.stop();
      // }
};

What is the problem? Do you have an example project that shows your issue?

Hey this is the project i’m working on

https://playcanvas.com/editor/scene/1183372

When i click on the Audio only button an audio source must play but for some reason it always throws an type undefined error.

Hope this would give you a clear picture of the problem i’m facing.

Looking at the code that the error is on:

  //sound source
  //Audio Source
  this.convolver = this.app.systems.sound.context.createConvolver();
    this.PlayAudioOnly.button.on('click', function(event) { 
       this.convolver.buffer = asset.resource.buffer;
        this.entity.sound.slot('Slot 1').setExternalNodes(this.convolver);
        },this);

It is saying that asset variable is undefined. Where is this variable defined? Is that the right variable you should be using?

There are a few other issues too. It would be worth doing a smaller separate project on just playing the audio bit without handling the video too.

Yeah i added a audio DOM element but for some reason it’s throwing an DOMException: Failed to load because no supported source was found.error. And i was wondering if i can use a different audio source when my video is playing and not playing the video’s default sound.

Thanks in advance. And for issues yes there is alot and i’m trying to finish one by one lol.

Should work. You may have to have the video muted for it to work though. Example here: https://playcanvas.com/editor/scene/1183905

@yaustar Thanks i was able to do it thanks to you. I was wondering if there is a way to sync audio and video when playing from an url. Should i set preload to auto or metadata? Thanks in advance.

Don’t set preload on the video to true as the video is being in a html video element, it doesn’t go through the PlayCanvas asset system.

If you need it to be perfectly synced, you need investigate the video html element API more and keep track of when it buffers, is it ready to play, etc.