socialincome-san / public

Fighting global poverty with the help of everyday people and your coding skills. Public repository of the NGO and global initiative Social Income.
https://socialincome.org
Other
91 stars 26 forks source link

[Web]: Mux video flickers when played on Safari #951

Open ssandino opened 3 days ago

ssandino commented 3 days ago

Describe the bug

In Safari, the poster image flickers briefly before the video starts playing, causing a "not so smooth" transition. Image

Steps To Reproduce

No response

Expected Behavior

No response

Screenshots?

No response

Desktop Environment (please complete the following information)

- OS:
- Browser:
- Version:

Smartphone Type (please complete the following information)

- Device:
- OS:
- Browser:
- Version:

Additional context

No response

Code of Conduct

ssandino commented 3 days ago

The flickering was really bothering me, so I played around with some fixes and found something that worked for me locally. Here’s what I ended up with—could you @mdumond try it out on your end and see if it resolves the issue for you too?


Changes:

1. Added a Dedicated Poster Layer
I added a div with an <img> for the poster. This ensures the poster remains visible until the video is fully ready to play.

const posterRef = useRef<HTMLDivElement>(null);
<div ref={posterRef} className="absolute inset-0 z-0">
    <img
        className="h-full w-full object-cover"
        src="https://image.mux.com/IPdwilTUVkKs2nK8zKZi5eKwbKhpCWxgsYNVxcANeFE/thumbnail.jpg?time=2"
        alt="Video Poster"
    />
</div>

2. Managed Poster Visibility Dynamically
The poster's visibility is controlled using the opacity property. It fades out when the video is ready (canplay event) and fades back in when the video is paused.

useEffect(() => {
    const video = videoElementRef.current;
    if (playing && video) {
        video.addEventListener('canplay', () => {
            if (posterRef.current) {
                posterRef.current.style.opacity = '0';
                posterRef.current.style.transition = 'opacity 0.5s ease';
            }
        });
        video.play();
    } else {
        video?.pause();
        if (posterRef.current) {
            posterRef.current.style.opacity = '1';
        }
    }
}, [playing]);

3. Some Layering for <MuxVideo>
Added z-10 to make sure the video plays above the poster layer.

<MuxVideo
    ref={videoElementRef}
    className="h-full w-full object-cover z-10"
    playbackId="IPdwilTUVkKs2nK8zKZi5eKwbKhpCWxgsYNVxcANeFE"
    startTime={2}
    loop
    muted={muted}
    autoPlay={playing}
    playsInline
    onCanPlay={() => setPlaying(true)}
>

This worked for me—curious to know if it resolves the issue on your end as well or if it causes new problems.

(one issue is now that when we press pause the poster image reappears, which is not optimal, but not really as bad as the white flickering)