Jump to content

Unable to pause video immediately on load?


purebe
 Share

Recommended Posts

Is there any way to pause a video immediately after creating the element with PIXI.Texture.fromVideo or fromVideoUrl?  It looks like it might be bugged currently, because under some circumstances the paused flag is set but the video doesn't actually pause.  I noticed in the fromVideoUrl function it will call play() before returning, and at one point console.log'ing the baseTexture.source element showed instead of the HTML tag, an object with a pixi_id or something.  I'm not sure if that is relevant, but I haven't been able to repeat that, so I'm not sure if it was just a one off (but it makes me suspicious if that object is somehow messing with my .pause() calls?  Maybe during the transition .pause() calls don't work properly, so the video keeps playing?  I'm not sure how that would work, but I'm not sure what's going on there either.)

 

This is the only code that I have been able to make that works, but I imagine it's fragile due to the bug? where sometimes .paused gets set to true even though the video is still playing.  If the timeout is lower than 1000 it doesn't pause the video, but the paused flag gets set so it stops it's setTimeout loop.  Also, it means the video plays for ~1 second before pausing which in my case is problematic.

var renderer, stage, video, sprite;$(function() {	renderer = new PIXI.autoDetectRenderer(1920, 1080);	$('body').append(renderer.view);	stage = new PIXI.Container();	video = PIXI.Texture.fromVideoUrl('720p_test_web.mp4');	sprite = new PIXI.Sprite(video);	stage.addChild(sprite);	animate();	pauseVideo(video.baseTexture.source);});function animate() {	requestAnimationFrame(animate);	renderer.render(stage);}function pauseVideo(el) {	console.log(el);	if (!el.paused) {		el.pause();		setTimeout(pauseVideo, 1000, el);	}}

I tried passing the video element directly into PIXI.Texture.fromVideo() but the video still doesn't pause and just plays from load.

var renderer, stage, video, sprite;$(function() {	renderer = new PIXI.autoDetectRenderer(1920, 1080);	$('body').append(renderer.view);	stage = new PIXI.Container();	video = PIXI.Texture.fromVideo(Util.fromVideoUrl('720p_test_web.mp4'));	sprite = new PIXI.Sprite(video);	stage.addChild(sprite);	animate();        video.baseTexture.source.pause();});function animate() {        requestAnimationFrame(animate);        renderer.render(stage);}var Util = Util || {};Util.fromVideoUrl = function(src) {        var video = document.createElement("video");        video.preload = "auto";        video.loop = true;        video.src = src;        video.pause();        return video;}

Any ideas?

Link to comment
Share on other sites

This is likely why, the video base texture listens for 'canplay' and 'canplaythrough' and calls .play():

 

https://github.com/pixijs/pixi.js/blob/master/src/core/textures/VideoBaseTexture.js#L62-L63

 

https://github.com/pixijs/pixi.js/blob/master/src/core/textures/VideoBaseTexture.js#L132

 

You will also notice there is a 'loaded' event emitted there. You can listen for that event and call pause there:

video = PIXI.Texture.fromVideoUrl('720p_test_web.mp4');sprite = new PIXI.Sprite(video);video.baseTexture.on('loaded', function () {    pauseVideo(video.baseTexture.source);});
Link to comment
Share on other sites

  • 1 year later...

Hi,

Sorry to bring this topic up again, but I'd like to know how to pause the video on the current version.

I'm using the loader class to preload the video and I'm passing the resources to the callback and getting the HTML video element there, but using autoplay=false is not working and I'm getting an error when trying to use pauseVideo on the base texture.

I found this:

https://github.com/pixijs/pixi.js/blob/master/src/core/textures/VideoBaseTexture.js#L73-L74

But those work with the videoBaseTexture class and I'm using a regular texture fromVideo method. When I switch to use the videoBaseTexture I get an error when trying to use it on a Sprite instance:

function loaderComplete(){
	
	// now we have the video and we can use it. but first create a reference to it
	targetVid = videoLoader.resources.testVideo.data;

	// pause the video THIS IS NOT WORKING
	targetVid.autoplay = false;
	targetVid.pause();
	targetVid.currentTime = 0;


	var videoTexture = new PIXI.VideoBaseTexture(targetVid);
	// pause the video as soon as it's loaded
	videoTexture.on("loaded", function(){
		// videoTexture.baseTexture.autoplay = false;
		videoTexture.source.pause();
		console.log( videoTexture.source );
	});
    
    // HERE I GET AN ERROR
	// now create the sprite
	var vidSprite = new PIXI.Sprite(videoTexture);

	vidSprite.width = 500;
	vidSprite.height = 500;

	// add the video sprite to the main container
	stage.addChild(vidSprite);

}

Here's the error I'm getting, basically because the video base texture doesn't have a baseTexture property, so that returns undefined

Uncaught TypeError: Cannot read property 'hasLoaded' of undefined     Sprite.js:584

Although the line seems to be this one:

https://github.com/pixijs/pixi.js/blob/master/src/core/sprites/Sprite.js#L592

Thanks,

Rodrigo.

Link to comment
Share on other sites

When you create a Sprite, it should always be done with a Texture, not a BaseTexture, or a VideoBaseTexture.

Think of the base textures as the actual image, or actual video, and a texture as a rectangle describing what part of that actual image / video to use. Thinking that way, you get spritesheets... lots of images on 1 big image. The big image becomes the BaseTexture, each little image is a Texture, which points to where abouts on the BaseTexture to use a smaller image. Doing PIXI.Texture.fromVideo will, behind the scenes, create a BaseVideoTexture for you, and then create a Texture that uses it.

Now the science bit is over, there are a couple of things you'll need to change with your code.

First of all, don't wait until 'loaded' to set the autoPlay property on your VideoBaseTexture to false; set it to false as soon as you've created it

Second, you need to create a Texture from that VideoBaseTexture. A simple case of 

var texture = new PIXI.Texture(videoTexture);

And use that for your sprite

Link to comment
Share on other sites

Thanks for the advice. Is creating the texture and the sprite correctly, but the video doesn't pause, it keeps running as soon as it's done loading.

I tried the following code with no luck:

// load complete callback
function loaderComplete(){
	
	// now we have the video and we can use it. but first create a reference to it
	targetVid = videoLoader.resources.testVideo.data;
	console.log( videoLoader.resources.testVideo.data );

	// pause the video
	targetVid.autoplay = false;
	targetVid.pause();
	targetVid.currentTime = 0;


	var videoBase = new PIXI.VideoBaseTexture(targetVid);

	videoBase.on("loaded", function(){
		videoBase.source.paused = true;
		videoBase.source.pause();
		videoBase.source.autoplay = false;

		console.log( "video paused => ", videoBase.source.paused );
		console.log( "video autoplay => ", videoBase.source.autoplay );
	});

	var videoTexture = new PIXI.Texture(videoBase);

	// now create the sprite
	var vidSprite = new PIXI.Sprite(videoTexture);

	vidSprite.width = 500;
	vidSprite.height = 500;


	// add the video sprite to the main container
	stage.addChild(vidSprite);

}

videoLoader
	.add('testVideo', 'vid/head-track-small.mp4')
	.once('complete', function(loader, resources){loaderComplete();})
	.load();

I tried to set up a codepen sample but I'm getting CORS errors. So I set up a live sample.

The console logs return the expected values, ie, paused is true and autoplay is false, but the video still runs after being loaded

Link to comment
Share on other sites

A solution is to add a timeout in the loader complete callback:

function loaderComplete(){
	
	// now we have the video and we can use it. but first create a reference to it
	targetVid = videoLoader.resources.testVideo.data;
	console.log( videoLoader.resources.testVideo.data );
	
	setTimeout(function(){
		// pause the video
		targetVid.pause();
		targetVid.currentTime = 0;
	},100);


	var videoBase = new PIXI.VideoBaseTexture(targetVid);

	var videoTexture = new PIXI.Texture(videoBase);

	// now create the sprite
	var vidSprite = new PIXI.Sprite(videoTexture);

	vidSprite.width = 500;
	vidSprite.height = 500;


	// add the video sprite to the main container
	stage.addChild(vidSprite);

}

Then after the sprite is added and outside the loader callback, I can control the video (targetVid resides outside the loader callback scope).

Hopefully someone can give some insight of what's happening here.

Best,

Rodrigo.

Link to comment
Share on other sites

  • 1 year later...

@Rodrigo A solution that is simpler and I think more elegant is to simply undefine the autoplaying:

PIXI.VideoBaseTexture.prototype._onCanPlay = function () {
        this.hasLoaded = true;

        if (this.source)
        {
            this.source.removeEventListener('canplay', this._onCanPlay);
            this.source.removeEventListener('canplaythrough', this._onCanPlay);

            this.width = this.source.videoWidth;
            this.height = this.source.videoHeight;

            // prevent multiple loaded dispatches..
            if (!this.__loaded)
            {
                this.__loaded = true;
                this.emit('loaded', this);
            }

            if (this._isSourcePlaying())
            {
                this._onPlayStart();
            }
        }
}

var sprite = PIXI.Sprite.from(your url)

 I tried to set it up via creating a video texture class that extends PIXI.VideoBaseTexture and it should be possible, however you have to do a little bit more shenanigans with it, for example you'd have to redefine fromUrl and fromVideo functions as well. This is simpler and if you need the video to immediately play after loading, you can set that up via

spr.texture.baseTexture.on('loaded', function () {spr.texture.baseTexture.source.play()});

immediately (while pausing immediately is impossible), so it's also completely harmless.

 

EDIT: For some reason it deletes the formatting of the text :(

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...