muxinc / media-chrome

Custom elements (web components) for making audio and video player controls that look great in your website or app.
https://media-chrome.org
MIT License
1.21k stars 62 forks source link

Cannot get Media Preview Thumbnail to render #763

Closed shenders13 closed 10 months ago

shenders13 commented 10 months ago

Hi Media Chrome folks 👋

The problem

I'm running into some issues getting the "Media Preview Thumbnail" images to appear when the user hovers over the media time range.

When I hover over the time range, the small badge showing the current time appears, but not the "Preview Thumbnail"

Screenshot 2023-11-11 at 7 59 59 pm

I am on version 1.5.2 of media-chrome

Attempt 1 - Render the MediaPrevewThumbnail component with mediaPreviewImage and mediaPreviewCoords props

I saw in the Media Chrome docs (here) that I can render <MediaPreviewThumbnail /> like so:

import { MediaPreviewThumbnail } from 'media-chrome/dist/react';

<MediaPreviewThumbnail
  mediaPreviewImage="https://image.mux.com/A3VXy02VoUinw01pwyomEO3bHnG4P32xzV7u1j1FSzjNg/storyboard.vtt"
  mediaPreviewCoords="284 640 284 160"
/>

I have tried it with and without the mediaPreviewCoords but no luck. I can see the file being downloaded successfully in the network tab.

No preview image appeared 😢

Attempt 2 - Render the MediaPrevewThumbnail but put the mediaPreviewImage props on the MediaController

<MediaController
  autohide={autohide} // https://www.media-chrome.org/en/media-controller#autohide
  className={sizeClasses}
  defaultStreamType={defaultStreamType} // https://www.media-chrome.org/en/media-controller#default-stream-type
  ref={mediaControllerRef}
  style={{
    '--media-control-background': 'transparent',
    '--media-control-hover-background': 'transparent',
    '--media-control-padding': '0',
  }}
  nohotkeys
  // ADD  mediaPreviewImage PROP TO MEDIA CONTROLLER BELOW
  mediaPreviewImage="https://image.mux.com/A3VXy02VoUinw01pwyomEO3bHnG4P32xzV7u1j1FSzjNg/storyboard.vtt"
  mediaPreviewCoords="284 640 284 160"
>
<MediaPreviewThumbnail />

No preview image appeared 😢

Attempt 3 - Render a element inside the video element

I saw in these docs that you could render a <track /> element inside the <video> element.

Here was my code:

<video
  className="w-full h-full"
  crossOrigin="anonymous"
  muted={initiallyMuted}
  playsInline
  poster={loadingImageSrc}
  ref={videoRef}
  slot="media"
>
    <track
      default
      label="thumbnails"
      kind="metadata"
      src="https://image.mux.com/A3VXy02VoUinw01pwyomEO3bHnG4P32xzV7u1j1FSzjNg/storyboard.vtt"
    />
</video>

No preview image appeared in this case either 😢

Attempt 4 - Adding a mediaPreviewImage prop to the <MediaTimeRange /> component

At this point I was trying random things - but I discovered that if you add a mediaPreviewImage prop to the <MediaTimeRange/> component, we end up with the faded outline of where the preview image should be (but alas, no actual image).

Screenshot 2023-11-11 at 8 13 49 pm

My code:

  return (
    <div>
      <MediaController
        autohide={autohide}
        className={sizeClasses}
        defaultStreamType={defaultStreamType}
        ref={mediaControllerRef}
        style={{
          '--media-control-background': 'transparent',
          '--media-control-hover-background': 'transparent',
          '--media-control-padding': '0',
        }}
        nohotkeys
      >
        <video
          className="w-full h-full"
          crossOrigin="anonymous"
          muted={initiallyMuted}
          playsInline
          poster={loadingImageSrc}
          ref={videoRef}
          slot="media"
        >
          {/** I tried adding a  a <track> here for the preview thumbnail*/}
          <track
            default
            label="thumbnails"
            kind="metadata"
            src="https://image.mux.com/A3VXy02VoUinw01pwyomEO3bHnG4P32xzV7u1j1FSzjNg/storyboard.vtt"
          />
        </video>

        {/** Desktop Center: Loading Indicator */}
        {isLoading && <div slot="centered-chrome" className="hidden md:flex opacity-100">
          <MediaLoadingIndicator />
        </div>}

        <MediaControlBar className="pb-2 px-4 md:pb-4 z-raised">
          <div className={clsx(hideControlBar ? 'hidden' : 'flex', 'flex-col w-full')}>
            <div className="flex flex-row w-full">
              {/** Mobile Control Bar: Left Section */}
              {streamType === 'on-demand' ? (
                <ControlBarGroup showOn="mobile-only">
                  <MediaTimeDisplay showDuration />
                </ControlBarGroup>
              ) : null}

              {/** Desktop Control Bar: Left Section */}
              <ControlBarGroup showOn="desktop-only">
                <PlayButton
                  isPlaying={isPlaying}
                  playButtonRef={mediaPlayButtonRef}
                  screen="desktop"
                />
                <MuteButton />
                <MediaTimeDisplay showDuration />
              </ControlBarGroup>

              {/** Desktop Control Bar: Center Section */}
              <div
                className="flex-1"
                style={{ backgroundColor: 'var(--media-control-background)' }}
              >
                {isDesktop && streamType === 'on-demand' ? (
                  <div className="hidden md:flex h-full px-4">
                    <TimeRange />
                    <MediaPreviewThumbnail
                      mediaPreviewImage="https://image.mux.com/A3VXy02VoUinw01pwyomEO3bHnG4P32xzV7u1j1FSzjNg/storyboard.vtt"
                      mediapreviewcoords="284 640 284 160"
                    />
                  </div>
                ) : null}
              </div>

              {/** Desktop & Mobile Control Bar: Right Section */}
              <ControlBarGroup showOn="mobile-and-desktop">
                <QualityButton
                  id="settings-button"
                  qualityOptions={{
                    activeLevel: activeVideoLevel,
                    levels: videoLevels,
                    selectLevel: setActiveVideoLevel,
                  }}
                  show={Boolean(hlsjs)}
                />
                <TheaterModeButton {...theaterModeControls} />
                <MediaPipButton className="hover:bg-initial" />
                <MediaFullscreenButton className="hover:bg-initial" />
              </ControlBarGroup>
            </div>

            {/** Mobile Time Range: Under Controls Section */}
            {isMobile && streamType === 'on-demand' ? (
              <div
                className="flex-1 mt-3 flex md:hidden h-full"
                style={{ backgroundColor: 'var(--media-control-background)' }}
              >
                <TimeRange />
              </div>
            ) : null}
          </div>
        </MediaControlBar>
        {children}
      </MediaController>
    </div>
  );

Please help me understand why the preview image isn't appearing 🙏 Thanks team!

luwes commented 10 months ago

Any chance you could put a reproduction online? What's in <TimeRange />? Only MediaTimeRange

It should be option 3, that's correct. https://www.media-chrome.org/docs/en/components/media-time-range#preview-thumbnails

shenders13 commented 10 months ago

Hi @luwes 👋

Of course, here is a small codesandbox that reproduces the issue.

Does anything jump out at you as wrong in terms of how I'm rendering the <track /> element?

Screenshot 2023-11-12 at 4 02 18 pm

EDIT:

I added some console.logs and found that the track element did not have any cues. So this line in controller.js was aborting early.

When I add crossOrigin="anonymous" to the parent video component, it works A-okay!

luwes commented 10 months ago

Ah yes, crossOrigin is required. Great you found the issue!