vimeo / player.js

Interact with and control an embedded Vimeo Player.
https://player.vimeo.com/api/demo
MIT License
1.45k stars 262 forks source link

Newer videos are not working on Vimeo Player on Flutter using InAppWebView on iOS #952

Closed giordanna closed 1 year ago

giordanna commented 1 year ago

Our application consists of a website displayed inside Flutter using the InAppWebView Plugin. Inside we use Vimeo Player to allow users to watch our training courses. It works fine on almost everywhere except on iOS devices. It even works on Safari but not on Flutter.

We tried searching anywhere for similar issues with no luck, and there are no log errors when this happens. We also tried setting the same configurations from our working videos to the not working ones, but again, no luck.

I created a minimal reproduction on Github, here's the repo of the website: https://github.com/giordanna/vimeo-player-ios-issue-svelte and here's on GH pages: https://giordanna.github.io/vimeo-player-ios-issue-svelte/. And the main.dart gist from Flutter: https://gist.github.com/giordanna/938ee0c301a19a0068d03ca29ace2300. I tried my best to simplify the Flutter file so it's reproducible. For instance, this vimeo ID words fine on our iOS app: 666201451, while this one gives an error: 855303737. We don't know if the issue is on Vimeo itself or on InAppWebView Plugin.

Expected Behavior

That both videos 666201451 and 855303737 would play normally on iOS WebView.

Actual Behavior

Newer videos like 855303737 are showing me the “Player error: The player is having trouble” message. The error is not logged on the player.on('error', event => { ... }) event listener.

Steps to Reproduce

Here's a video reproducing the error on iOS: https://drive.google.com/file/d/1ah_hvrFFfg4EZ1AxiEpv2shFK86ileIm/view?usp=sharing

rkrishnan8594 commented 1 year ago

Hi @giordanna - is it possible to share the actual embed code that's loaded inside of the web view?

giordanna commented 1 year ago

Hi @giordanna - is it possible to share the actual embed code that's loaded inside of the web view?

Hi, here is the code where I use the Vimeo Player (using the SvelteKit framework):

<script lang="ts">
    import Player from '@vimeo/player';

    let vimeoDiv: HTMLDivElement;
    let vimeoPlayer: Player;
    let videoHasLoaded: boolean = false;

    let vimeoId: string = '';

    const reloadPlayer = async () => {
        if (vimeoDiv == null || vimeoId === '') {
            return;
        }

        // if player is already loaded, destroy and load it again
        if (vimeoPlayer != null) {
            await vimeoPlayer.destroy();
            videoHasLoaded = false;
        }

        try {
            const vimeoOptions: any = {
                responsive: true,
                color: '9358fa',
                title: false
            };

            // if it starts with https then we set on url, not on id
            if (vimeoId.startsWith('https://')) {
                vimeoOptions.url = vimeoId;
            } else {
                vimeoOptions.id = vimeoId;
            }

            vimeoPlayer = new Player(vimeoDiv, vimeoOptions);

            vimeoPlayer.on('loaded', (event: any) => {
                console.log('============= loaded', JSON.stringify(event));
                videoHasLoaded = true;
            });

            vimeoPlayer.on('error', (event: any) => {
                console.log('============= error', JSON.stringify(event));
                videoHasLoaded = true;
            });

            vimeoPlayer.on('timeupdate', (event: any) => {
                console.log('============= timeupdate', JSON.stringify(event));
            });

            vimeoPlayer.on('seeked', (event: any) => {
                console.log('============= seeked', JSON.stringify(event));
            });

            vimeoPlayer.on('play', (event: any) => {
                console.log('============= play', JSON.stringify(event));
            });

            vimeoPlayer.on('pause', (event: any) => {
                console.log('============= pause', JSON.stringify(event));
            });
        } catch (error) {
            console.error('========= error 2', JSON.stringify(error));
        }
    };
</script>

<main class="w-full max-w-screen-lg px-3 md:px-0 mx-auto mt-3 md:mt-5">
    <h1 class="font-bold text-xl">Vimeo Player iOS Issue</h1>

    <p class="text-slate-500 my-3">Add the vimeo ID or URL below:</p>

    <fielset
        class="inline-flex flex-col w-full md:flex-row space-x-0 md:space-y-0 space-y-3 items-center md:space-x-3 mb-3"
    >
        <input type="text" bind:value={vimeoId} class="rounded-lg w-full md:w-auto" />
        <button
            on:click={reloadPlayer}
            disabled={vimeoId === ''}
            class="bg-emerald-600 w-full md:w-auto active:bg-emerald-700 transition-all disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-emerald-600/50 text-white rounded-lg font-bold p-2"
        >
            Reload player
        </button>
    </fielset>

    <div
        bind:this={vimeoDiv}
        class="{!videoHasLoaded
            ? 'h-44 animate-pulse rounded-lg bg-slate-200 md:h-96'
            : ''} w-full max-w-full"
    />
</main>

The deployed version is at https://giordanna.github.io/vimeo-player-ios-issue-svelte/

giordanna commented 1 year ago

Any updates on this? Or at least a workaround while the issue is still up... something like, getting the direct URL of the vimeo video and embedding with the HTML5 video tag or something.

rkrishnan8594 commented 1 year ago

Hey @giordanna - I'm guessing this error is because our player is deciding not to play back HLS files, for some reason. Do you mind sharing with me the user agent string for a session that encounters this error?

Yes, that would be a sensible workaround. Here's how you can grab a direct video file URL: https://help.vimeo.com/hc/en-us/articles/12426150952593-Direct-links-to-video-files

giordanna commented 1 year ago

Hi @rkrishnan8594, thank you for the reply. Apparently, that was it! The user agent string was causing the error! Here's the string that was being used on Flutter plugin InAppWebView:

Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36

It was the userAgent option set on InAppWebViewSettings. The gist I mentioned on the description has this exact option set: https://gist.github.com/giordanna/938ee0c301a19a0068d03ca29ace2300.

I will investigate why we were using this user agent, but testing here on the emulator just by commenting the option it worked perfectly.

Again, thanks!