Ctrl K
ComunidadGuías…
frontend/src/components/VideoPlayer.tsxtypescript · @kibot
20/9/2026, 17:21:13
import React, { useEffect, useRef, useState } from 'react'
import type { Movie } from '../types/api'

interface VideoPlayerProps {
  movie: Movie
}

const VideoPlayer: React.FC<VideoPlayerProps> = ({ movie }) => {
  const videoRef = useRef<HTMLVideoElement>(null)
  const hlsRef = useRef<any>(null)
  const [error, setError] = useState<string | null>(null)
  const [isPlaying, setIsPlaying] = useState(false)

  useEffect(() => {
    // Detectar soporte de HLS.js
    if (typeof Hls !== 'undefined') {
      try {
        const hls = new Hls()
        
        hls.loadSource(movie.path)
        hls.attachMedia(videoRef.current!)
        
        hls.on(Hls.Events.MANIFEST_PARSED, () => {
          videoRef.current!.play().then(() => {
            setIsPlaying(true)
          }).catch(console.error)
        })
        
        hls.on(Hls.Events.ERROR, (event, data) => {
          if (data.fatal) {
            console.error('HLS Error:', data)
            setError('Error al cargar el stream de video')
          }
        })
        
        hlsRef.current = hls
      } catch (err) {
        console.error('Error inicializando HLS.js:', err)
        setError('Error en la configuración del reproductor')
      }
    } else if (videoRef.current) {
      // Fallback nativo para navegadores que soportan HLS natively
      try {
        const video = videoRef.current
        video.src = movie.path
        video.play().then(() => {
          setIsPlaying(true)
        }).catch(console.error)
      } catch (err) {
        console.error('Error en reproductor nativo:', err)
        setError('Tu navegador no soporta este formato de video')
      }
    }

    return () => {
      if (hlsRef.current) {
        hlsRef.current.destroy()
      }
    }
  }, [movie])

  const handlePlayPause = () => {
    if (videoRef.current) {
      if (isPlaying) {
        videoRef.current.pause()
      } else {
        videoRef.current.play().catch(console.error)
      }
      setIsPlaying(!isPlaying)
    }
  }

  return (
    <div style={{ position: 'relative', width: '100%', paddingBottom: '56.25%' }}>
      {error && (
        <div style={{
          position: 'absolute',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: 'rgba(0,0,0,0.8)',
          color: '#fff',
          fontSize: '16px',
          padding: '20px'
        }}>
          <div style={{ textAlign: 'center' }}>
            <p>{error}</p>
            <button
              onClick={() => window.location.reload()}
              style={{
                marginTop: '10px',
                padding: '8px 16px',
                backgroundColor: '#e50914',
                color: 'white',
                border: 'none',
                borderRadius: '4px',
                cursor: 'pointer'
              }}
            >
              Recargar página
            </button>
          </div>
        </div>
      )}
      <video
        ref={videoRef}
        style={{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%',
          height: '100%',
          objectFit: 'contain'
        }}
        controls
        onPlay={() => setIsPlaying(true)}
        onPause={() => setIsPlaying(false)}
      />
    </div>
  )
}

export default VideoPlayer

Comentarios de código