import type { OdFileObject } from '../../types' import { FC, useEffect, useState } from 'react' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import axios from 'axios' import toast from 'react-hot-toast' import Plyr from 'plyr-react' import { useAsync } from 'react-async-hook' import { useClipboard } from 'use-clipboard-copy' import { getBaseUrl } from '../../utils/getBaseUrl' import { getExtension } from '../../utils/getFileIcon' import { getStoredToken } from '../../utils/protectedRouteHandler' import { DownloadButton } from '../DownloadBtnGtoup' import { DownloadBtnContainer, PreviewContainer } from './Containers' import FourOhFour from '../FourOhFour' import Loading from '../Loading' import CustomEmbedLinkMenu from '../CustomEmbedLinkMenu' import 'plyr-react/plyr.css' const VideoPlayer: FC<{ videoName: string videoUrl: string width?: number height?: number thumbnail: string subtitle: string isFlv: boolean mpegts: any }> = ({ videoName, videoUrl, width, height, thumbnail, subtitle, isFlv, mpegts }) => { useEffect(() => { // Really really hacky way to inject subtitles as file blobs into the video element axios .get(subtitle, { responseType: 'blob' }) .then(resp => { const track = document.querySelector('track') track?.setAttribute('src', URL.createObjectURL(resp.data)) }) .catch(() => { console.log('Could not load subtitle.') }) if (isFlv) { const loadFlv = () => { // Really hacky way to get the exposed video element from Plyr const video = document.getElementById('plyr') const flv = mpegts.createPlayer({ url: videoUrl, type: 'flv' }) flv.attachMediaElement(video) flv.load() } loadFlv() } }, [videoUrl, isFlv, mpegts, subtitle]) // Common plyr configs, including the video source and plyr options const plyrSource = { type: 'video', title: videoName, poster: thumbnail, tracks: [{ kind: 'captions', label: videoName, src: '', default: true }], } const plyrOptions: Plyr.Options = { ratio: `${width ?? 16}:${height ?? 9}`, fullscreen: { iosNative: true }, } if (!isFlv) { // If the video is not in flv format, we can use the native plyr and add sources directly with the video URL plyrSource['sources'] = [{ src: videoUrl }] } return } const VideoPreview: FC<{ file: OdFileObject }> = ({ file }) => { const { asPath } = useRouter() const hashedToken = getStoredToken(asPath) const clipboard = useClipboard() const [menuOpen, setMenuOpen] = useState(false) const { t } = useTranslation() // OneDrive generates thumbnails for its video files, we pick the thumbnail with the highest resolution const thumbnail = `/api/thumbnail/?path=${asPath}&size=large${hashedToken ? `&odpt=${hashedToken}` : ''}` // We assume subtitle files are beside the video with the same name, only webvtt '.vtt' files are supported const vtt = `${asPath.substring(0, asPath.lastIndexOf('.'))}.vtt` const subtitle = `/api/raw/?path=${vtt}${hashedToken ? `&odpt=${hashedToken}` : ''}` // We also format the raw video file for the in-browser player as well as all other players const videoUrl = `/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}` const isFlv = getExtension(file.name) === 'flv' const { loading, error, result: mpegts, } = useAsync(async () => { if (isFlv) { return (await import('mpegts.js')).default } }, [isFlv]) return ( <> {error ? ( ) : loading && isFlv ? ( ) : ( )}
window.open(videoUrl)} btnColor="blue" btnText={t('Download')} btnIcon="file-download" /> { clipboard.copy(`${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`) toast.success(t('Copied direct link to clipboard.')) }} btnColor="pink" btnText={t('Copy direct link')} btnIcon="copy" /> setMenuOpen(true)} btnColor="teal" btnText={t('Customise link')} btnIcon="pen" /> window.open(`iina://weblink?url=${getBaseUrl()}${videoUrl}`)} btnText="IINA" btnImage="/players/iina.png" /> window.open(`vlc://${getBaseUrl()}${videoUrl}`)} btnText="VLC" btnImage="/players/vlc.png" /> window.open(`potplayer://${getBaseUrl()}${videoUrl}`)} btnText="PotPlayer" btnImage="/players/potplayer.png" /> window.open(`nplayer-http://${window?.location.hostname ?? ''}${videoUrl}`)} btnText="nPlayer" btnImage="/players/nplayer.png" />
) } export default VideoPreview