Open Benny739 opened 1 month ago
I experienced the same and fixed it the following way:
const handleProviderChange = (e: MediaProviderChangeEvent) => {
const provider = e.detail;
if (isYouTubeProvider(provider)) {
provider.referrerPolicy = 'no-referrer-when-downgrade';
provider.iframe.referrerPolicy = 'no-referrer-when-downgrade';
}
};
Doesn't solve it for me, it still shows the poster with an endless loading indicator.
Agreed, I still have the endless loading indicator on mine too. Is there any event that vidstack fires to show that a video cannot be played from YouTube. If so, then I'd like to just show a thumbnail
I'm going to share my workaround and although it's not a solution, I think the reason why this is happening is because of the YouTube API. The full solution would have to be you render an iframe from a different URL (similar to how reddit plays youtube videos).
Essentially here is my MediaPlayer component:
<MediaPlayer ...
ref={playerRef}
>
<MediaProvider>
....
</MediaProvider>
<YoutubePlayerControl src={props.src} thumbnail={props.thumbnail} isExternal={props.isExternal} />
<DefaultVideoLayout
/>
</MediaPlayer>
Notice how I have a YoutubePlayerControl component there. I have a context hook that contains a reference to my video player in that component and use the bufferedEnd to see if the video has loaded. bufferedEnd is true when the video loads 1 second, however is false initially (0). If this video has not buffered 1 second that likely means it's blocked, which I then open the video up in the browser. This is my full code for my component:
const YoutubePlayerControl: React.FC<YoutubePlayerControlProps> = ({ src, isExternal, thumbnail }) => {
const { playerRef } = useVideoContext();
const bufferedEnd = useMediaState('bufferedEnd', playerRef);
const openInBrowser = async () => {
await Browser.open({ url: src, presentationStyle: 'popover' });
};
return (
!bufferedEnd && isExternal && (
<div
className="absolute inset-0 w-full h-full cursor-pointer flex items-center justify-center"
onClick={openInBrowser}
aria-label="Youtube video"
>
{/* Icon container with higher z-index, using flex centering */}
<div className="absolute z-30 flex items-center justify-center">
<IonImg
src="/assets/icon/logos--youtube-icon.svg"
alt="Play"
className="w-[100px] h-[100px]"
/>
</div>
{/* Poster with lower z-index */}
<Poster
className="absolute inset-0 block h-full w-full bg-black rounded-md opacity-0 transition-opacity data-[visible]:opacity-100 [&>img]:h-full [&>img]:w-full [&>img]:object-cover z-10"
src={thumbnail}
/>
</div>
)
);
};
Hope this helps as I've been spending about 2 weeks thinking on how I can fix this and it works well enough for a good user experience!
Hi @brendanahart,
Have you been able to get the player to be reliable for when using with YouTube? I'm still hitting lots of issues (reported but issues still exist), even with the default setup just following the docs exactly.
Especially when trying to view on iPhone. Finding it too unreliable for production. Lots of situations where the player still gets stuck. Some I've reported for where it reliably fails..
Setting playsinline=false prevents video from being playable on iPhone - https://github.com/vidstack/player/issues/1431
The 'play' loading strategy will crash the player on iPhone (never ending loading, can't click to play ) - https://github.com/vidstack/player/issues/1395
After using chapters to navigate, using the time slider no longer works and causes the player to get stuck - https://komododecks.com/recordings/92YAhFQn7wBvNDFaMKC0
Are these things you're using workarounds for? Are you seeing the same issues?
When I'm testing, these issues happen every time.
Hey @wplit
I've never seen the player crash the app, however, I've seen the loading "Video is unavailable" whenever I try to load the video natively on an iPhone. I believe this is from the YouTube API blocking anything that is hosted on localhost (which by default is what an app is hosted on). It seems you must need an https connection to the video (according to this issue: https://stackoverflow.com/questions/51969269/embedded-youtube-video-doesnt-work-on-local-server). For some reason, randomly, videos are able to load sometimes and then not load natively on iOS. That's why I went with the custom thumbnail solution and then redirects them to a browser popup in app to load the youtube video. FYI I am using vidstack in a native iOS/Android app
I haven't gotten to chapters yet and the loading strategy I use is custom.
Here is my code. When the video loads, I am able to navigate with the timesliders.
I would make sure that on iPhone, you're audio is always muted unless you are native. That could be an issue. The user must make sure the audio is pressed for it to play according to recent authoritarian restrictions from Chrome and Safari
<MediaPlayer
ref={playerRef}
src={props.src}
poster={props.thumbnail}
aspectRatio={aspectRatioFraction}
crossOrigin
playsInline
loop
paused={!shouldBePlaying}
onCanPlay={handleCanPlay}
onError={handleError}
load="custom"
posterLoad="eager"
style={{ width: playerWidth }}
onProviderChange={onProviderChange}
className={loadingClass}
onClick={handleMediaClick}
muted={!isNative ? true : muted}
controlsDelay={hasInteracted ? 1250 : 0}
>
useEffect(() => {
// console.log("Scrolling:", props.isScrolling, "Speed:", props.scrollSpeed, "Should Load:", shouldLoad, "In View:", inView, "ID:", props.src);
if (shouldLoad) {
playerRef.current?.startLoading();
}
}, [inView, props.isScrolling, props.scrollSpeed]);
const shouldLoad = inView && (!props.isScrolling || props.scrollSpeed < playingScrollSpeedMax);
I've never seen the player crash the app
Try setting the playsInline to false, and then view on iPhone. The player will crash the moment play is clicked (stuck in loading with no way to play the video).
Reg. mute being needed. Yes, this is a shame. It makes it less useful than a regular Youtube embed, which can play on one click. Obviously can't be helped from vidstack side of things, but is a huge UX issue imo.
Current Behavior:
When embedding is forbidden video shows an endless loading indicator with the poster
Expected Behavior:
The video can not be embedded image should be shown
Steps To Reproduce:
Reproduction Link: Demo Link