vidstack / player

UI components and hooks for building video/audio players on the web. Robust, customizable, and accessible. Modern alternative to JW Player and Video.js.
https://vidstack.io
MIT License
1.89k stars 114 forks source link

SSR not working (silently..) #1260

Open iSuslov opened 2 months ago

iSuslov commented 2 months ago

Hi, first things first. I want to admit that I really appreciate the way you architected this project and the way how you iterate over the issues.

Current Behavior:

Simple SSR example renders empty video tag. (NextJs)

Expected Behavior:

I believe SSR ready means HTML5 video player is present on the initial page with src attribute pointing to the actual video. <source> elements pointing to, say, vtt files should be also rendered.

Steps To Reproduce (Paste&Reproduce solution):

npx create-next-app@latest vidstack-nextjs-test --ts --no-eslint --no-tailwind --src-dir --app --no-import-alias
cd vidstack-nextjs-test
npm i @vidstack/react@next
cat <<EOF > src/app/page.tsx
import '@vidstack/react/player/styles/default/theme.css';
import '@vidstack/react/player/styles/default/layouts/video.css';
import { MediaPlayer, MediaProvider } from '@vidstack/react';
import { defaultLayoutIcons, DefaultVideoLayout } from '@vidstack/react/player/layouts/default';

export default function Home() {
  return (
    <main>
      <MediaPlayer title="Sprite Fight" src="https://files.vidstack.io/sprite-fight/720p.mp4">
        <MediaProvider />
        <DefaultVideoLayout
          thumbnails="https://files.vidstack.io/sprite-fight/thumbnails.vtt"
          icons={defaultLayoutIcons}
        />
      </MediaPlayer>
    </main>
  )}
EOF
npm run dev

Observe the bug

<main>
    <div data-media-player="" role="region" aria-label="Media Player - Sprite Fight" data-orientation="portrait" aria-busy="true" data-load="visible" data-can-seek="" data-media-type="unknown" data-paused="" data-remote-state="disconnected" data-remote-type="none" data-stream-type="unknown" data-view-type="unknown" tabindex="0">
        <div data-media-provider="">
            <video preload="none" aria-hidden="true"></video>
        </div>
        <div class="vds-video-layout dark" data-match="" data-sm="" data-size="sm"></div>
    </div>
</main>

Interestingly, video url is included in the same html page but in a form of hydration(?) script.

<script>
self.__next_f.push([1, "0:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/c6868c6887bfb940.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"oqv0LmVBmcOiNax8js2b1\",\"assetPrefix\":\"\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[[\"$L5\",[\"$\",\"main\",null,{\"children\":[\"$\",\"$L6\",null,{\"title\":\"Sprite Fight\",\"src\":\"https://files.vidstack.io/sprite-fight/720p.mp4\",\"children\":[[\"$\",\"$L7\",null,{}],[\"$\",\"$L8\",null,{\"thumbnails\":\"https://files.vidstack.io/sprite-fight/thumbnails.vtt\",\"icons\":\"$9\"}]]}]}]],null],null]},[[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_aaf875\",\"children\":[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"styles\":[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/524ac47de73630b9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]]}]}]}],null],null],\"couldBeIntercepted\":false,\"initialHead\":[false,\"$Lc\"],\"globalErrorComponent\":\"$d\",\"missingSlots\":\"$We\"}]]\n"])
</script>

Environment:

Anything Else?

If this is how it should work, then it's not clear how can we benefit from such SSR, since search engines face an empty <video> tag. Google won't index video on page because, quote:

Video is not the main content of the page

Google Search Console:

Screenshot 2024-04-17 at 1 18 00 PM

If I missed some configuration then documentation should be fixed. I followed the installation wizard and kept in mind that the only thing the doc says: SSR ready

Jumaron commented 2 months ago

As far as i know regarding Googles "Video is not the main content of the page" message, putting video in your url like this domain.com/hello/video worked in most cases, while also adding Video in the meta name. Without that even when it covers the whole screen somehow google while give out this error, but i saw a lot of people faceing that issue.

shaghayegh70 commented 1 month ago

I have the same issue on the Nextjs platform