libgdx / gdx-video

A libGDX cross platform video rendering extension
Apache License 2.0
147 stars 50 forks source link

Videos cannot be loaded without playing #74

Open Frosty-J opened 2 years ago

Frosty-J commented 2 years ago

In HTML5 (speaking in general here, not specifically in regards to gdx-video), videos cannot play without prior user interaction (e.g. clicking on the page) unless they are muted, even if they don't have an audio track.

As playing and loading the video is a single method in gdx-video, I cannot preload the video before interaction in order to make playback commence immediately.
(speaking from the future: this might have actually been possible if it wasn't for the resume() bug mentioned later on this page)
(again from the future: doesn't seem immediately is possible - I get blackness for a bit, so I delayed my rendering by 2/30s to make it appear at the same time as my UI)

I don't care about actually playing before interaction, but I did a quick test and concluded that setting the volume to 0 is good enough to achieve that. Whether there's a browser out there that explicitly requires the muted attribute, I'm not sure.

For my project, I added the following method to VideoPlayerGwt. I'd prefer to specify the file on creation (like new Texture("texture.png"), Gdx.audio.newMusic(Gdx.files.internal("music.mp3")) but not sure how that works with reflection and stuff.

@Override
public boolean load (FileHandle file) {
    currentFile = file;
    if (v != null) {
        v.setSrc(((GwtFileHandle)file).getAssetUrl());
        return true;
    }
    return false;
}

I also had to change v.getCurrentTime() > 0 in resume() to v.getCurrentTime() >= 0. At this point I'm not sure there's any point in the check at all, but I left it in there all the same.

Edit: I've now removed that. And also v.getCurrentTime() < v.getDuration() - this was causing playback to fail if I played the video before its duration was known.

While the time it takes to fetch a video will be shorter on other backends due to not going via the internet, I think this still has potential to benefit them, being able to give your video time to buffer before actually playing it. Though I haven't taken the time to understand the Android implementation, and the desktop implementation has bigger things to worry about than this.

SimonIT commented 2 years ago

There is also the load()-method. I agree with you that preloading might be a good idea. The reflection shouldn't be a problem. Will have to look if I get android and desktop seperated. We could integrate that also with the AssetManager, I think

dasisdormax commented 1 year ago

For the resume method, the check (v.getCurrentTime() == 0 || v.getCurrentTime() < v.getDuration()) seems to get the job done while still making sure that calling pause + resume doesn't restart an already finished video.

(Edited) For the blackness, it seems to me like we don't have an accurate way (yet?) to determine when the first video frame is available for rendering.