0

我尝试创建一个 React 组件来播放 Azure 媒体服务内容,它可以播放,但不能捕获事件。这是我的组件的代码:

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;

我也试过:

<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>

但我无法获得玩家的事件。有人可以帮我吗?如何在 React 中获取玩家事件?

非常感谢。

4

2 回答 2

1

建议不要尝试直接在 React 组件中使用 AMP 播放器。它不是为了组件化而编写的。

尝试查看更现代的播放器,例如 Shaka 或 HLS.js,它们可能已经有一个 React 包装器。

例如 - https://www.npmjs.com/package/shaka-player-react https://github.com/matvp91/shaka-player-react

或者支持 React 的更商业化的播放器,例如 Theo Player 或 Bitmovin https://docs.theoplayer.com/getting-started/02-frameworks/02-react/00-getting-started.md https://github.com/ bitmovin/bitmovin-player-web-samples

于 2021-05-11T17:01:16.820 回答
0

这是 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;

唯一的细节是要播放的网址:它必须是/manifest(format=mpd-time-csf)

于 2021-09-23T10:50:57.017 回答