简体   繁体   中英

Azure Media Player events now working for React Component

I tried to create a React component to play Azure Media Services content and it works to play, but not to capture events. This is the code of my component:

import React, { useEffect, useRef } from 'react';
import { Helmet } from 'react-helmet';

export interface AzureMediaPlayerProps {
  videoUrl: string;
}

const AzureMediaPlayer = (props: AzureMediaPlayerProps): JSX.Element => {
  const { videoUrl } = props;

  const videoRef = useRef<HTMLVideoElement>(null);

  const clearListener = (): void => {
    videoRef.current?.removeEventListener('load', (): void => { });
    videoRef.current?.removeEventListener('progress', (): void => { });
  };

  const addListener = (): void => {
    videoRef.current?.addEventListener('load', (ev): void => { console.log(ev); });
    videoRef.current?.addEventListener('progress', (ev): void => { console.log(ev); });
  };

  useEffect((): void => {
    addListener();
    return clearListener();
  }, [videoRef]);

  return (
    <>
      <Helmet>
        <link href="//amp.azure.net/libs/amp/2.3.7/skins/amp-default/azuremediaplayer.min.css" rel="stylesheet" />
        <script src="//amp.azure.net/libs/amp/2.3.7/azuremediaplayer.min.js" />
      </Helmet>
      <video
        id="vid1"
        className="azuremediaplayer amp-default-skin"
        autoPlay
        controls
        width="100%"
        data-setup='{"nativeControlsForTouch": false}'
        ref={videoRef}
      >
        <source src={videoUrl} type="application/vnd.ms-sstr+xml" />
        <p className="amp-no-js">
          To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
        </p>
      </video>
    </>
  );
};

AzureMediaPlayer.displayName = 'AzureMediaPlayer';

export default AzureMediaPlayer;

I also tried:

<video
    id="vid1"
    className="azuremediaplayer amp-default-skin"
    autoPlay
    controls
    width="100%"
    data-setup='{"nativeControlsForTouch": false}'
    ref={videoRef}
    onProgress={(ev): void => { console.log(ev); }}
    >
    <source src={videoUrl} type="application/vnd.ms-sstr+xml" />
    <p className="amp-no-js">
      To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
    </p>
    </video>

But I was not able to get the events of the player. Can anybody please help me? How can I get the player events in React?

Thanks a lot.

Recommend that you don't try to use the AMP player in React component directly. It was not written to be componentized.

Try looking at a more modern player like Shaka or HLS.js that may already have a React wrapper for it.

For example - https://www.npmjs.com/package/shaka-player-react https://github.com/matvp91/shaka-player-react

Or a more commercial player that supports React like Theo Player or Bitmovin https://docs.theoplayer.com/getting-started/02-frameworks/02-react/00-getting-started.md https://github.com/bitmovin/bitmovin-player-web-samples

This is the final version of VideoJsPlayer.tsx:

import { Box } from 'grommet';
import React, { useEffect, useRef, useState } from 'react';
import videojs, { VideoJsPlayerOptions } from 'video.js';
import 'video.js/dist/video-js.css';

export interface VideoJsPlayerProps {
  videoUrl?: string;
  transcriptionUrl?: string;
  type?: string;
  saveProgress: (minute: number) => Promise<void>;
  completeProgress: (progress: string) => Promise<void>;
  startingTime?: number;
}

const VideoJsPlayer = (props: VideoJsPlayerProps): JSX.Element => {
  const {
    videoUrl, transcriptionUrl, type, saveProgress, completeProgress, startingTime = 0,
  } = props;
  let player;

  const videoRef = useRef<HTMLVideoElement>(null);
  const [minutes, setMinutes] = useState<number>(0);

  const getMin = (sec: number): number => Math.floor(sec / 60);

  const updateMinutes = (time: string): void => {
    const secs = parseInt(time, 10);
    const min = getMin(secs);

    if (min > minutes) {
      setMinutes(min);
    }
  };

  const videoJsOptions = {
    autoplay: true,
    controls: true,
    responsive: true,
    fill: true,
    nativeControlsForTouch: false,
    playbackRates: [0.5, 1, 1.5, 2],
    sources: [
      {
        src: videoUrl as string,
        type: type as string,
      },
    ],
  } as VideoJsPlayerOptions;

  useEffect((): any => {
    const videoElement = videoRef.current;

    // mount
    if (videoElement) {
      // @ts-ignore
      player = videojs(
        videoElement,
        videoJsOptions,
        () => {
          player.addRemoteTextTrack({
            kind: 'captions',
            src: transcriptionUrl || '',
            label: 'English',
            language: 'en',
            srcLang: 'en',
            default: true,
          }, false);

          player.on('progress', (): void => {
            updateMinutes(player.currentTime());
          });

          player.on('ended', (): void => {
            completeProgress(player.currentTime());
          });
        },
      );

      // set starting time
      player.currentTime(startingTime);
    }

    // unmount
    return (): void => {
      if (player) {
        player.dispose();
      }
    };
  }, []);

  useEffect((): void => {
    if (minutes > 0) {
      saveProgress(minutes);
    }
  }, [minutes]);

  return (
    <Box
      fill="horizontal"
      align="center"
      background="yellow"
      style={{
        height: 700,
      }}
    >
      <video
        className="video-js vjs-big-play-centered"
        ref={videoRef}
      />
    </Box>
  );
};

VideoJsPlayer.displayName = 'VideoJsPlayer';

export default VideoJsPlayer;

The only details is the url to play: it must be /manifest(format=mpd-time-csf)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM