Основная идея реализации видеоплеера в браузере

внешний интерфейс

"Это 22-й день моего участия в августовском испытании обновлений.Подробности о событии:Испытание августовского обновления"

Для настройки плеера компоненты все нативные, так что немного некрасиво, ориентируйтесь на бизнес-логику.

Интерфейс выглядит так. Вы можете посмотреть на интерфейс и подумать, как бы вы реализовали этот видеоплеер. Вы можете задать себе следующие вопросы:

  • Этот компонент примет эти реквизиты
  • Как получить основную информацию о видео, включая продолжительность, разрешение и т. д.
  • Как сделать паузу и воспроизвести
  • Как реализовать логику перетаскивания индикатора выполнения
  • Начальная загрузка видео показывает, как обрабатывается загрузка
  • В процессе воспроизведения видео показывает, как быть с загрузкой

Если вы не совсем понимаете API, связанное с аудио и видео в браузере, и не знаете, с чего начать, обратитесь к этой моей статье:Знание аудио и видео в браузере

image.png

Общая идея такова:

  1. Этот компонент получает src видео в качестве параметра
  2. мониторonLoadedMetadataСобытие, получение продолжительности видео (duration), реальной ширины и высоты (videoWidth, videoHeight)
  3. При нажатии кнопки воспроизведения/паузы вызывается метод воспроизведения/паузы видеоэлемента.
  4. Во время игры следитеonTimeUpdate, получить текущее время воспроизведения (currentTime) и вычислить прогресс индикатора выполнения
  5. Перетащите индикатор выполнения, чтобы установить текущее время воспроизведения видео, напротив шага 4.
  6. Когда видео изначально загружается, отображается загрузка. То есть при первом рендеринге компонента свойство загрузки по умолчанию имеет значение true, то есть отображается эффект загрузки.При загрузке метаданных видео загрузка отменяется.
  7. Видео зависает и показывает загрузку. Реализация этой функции заключается в контролеonWaitingСобытие, когда он не зависает, отменяет загрузку и мониторonCanPlayсобытие

Код

Код реализован с помощью React, и то же самое с Vue, просто сконцентрируйтесь на бизнес-логике. Если у вас есть какие-либо потребности, я могу обновить эту статью и добавить код Vue.

Примечание. Собственным событиям DOM необходимо предшествовать on в реакции, а затем записывать в форме верблюжьего регистра.

function formatDuration(duration) {
    var sec_num = parseInt(duration, 10); // don't forget the second param
    var hours   = Math.floor(sec_num / 3600);
    var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
    var seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}
    return hours+':'+minutes+':'+seconds;
}

import React, { createRef, useState } from 'react'
import './VideoPlayer.css'
function VideoPlayer({src}){
    const videoDom=createRef()
    // 视频当前播放时间
    const [curTime,setCurTime]=useState(0)
    // 视频时长
    const [duration,setDuration]=useState(0)
    // 视频状态,是否暂停
    const [isPause,setPause]=useState(true)
    // 视频真是尺寸
    const [size,setSize]=useState({width:1920,height:1080})
    // 视频加载中
    const [waiting,setWaiting]=useState(true)

    // 视频元数据加载成功
    const onLoad=(e)=>{
        const {duration,videoWidth,videoHeight}=e.target
        setDuration(duration)
        setSize({width:videoWidth,height:videoHeight})
        setWaiting(false)
    }
    // 控制播放暂停
    const handlePlay=(play)=>{
        const v=videoDom.current
        if(play){
            setPause(false)
            v.play()
        }else{
            setPause(true)
            v.pause()
        }

    }
    // 拖动slider时改变视频currentTime
    const onSliderChange=(e)=>{
        setCurTime(e.target.value)
        videoDom.current.currentTime=e.target.value

    }
    // 监听video timeupdate
    const onTimeUpdate=()=>{
        const v=videoDom.current
        setCurTime(v.currentTime)
        if(v.ended){
            handlePlay(false)
            v.currentTime=0
        }
    }
    // 卡顿时,显示加载中提示
    const onWaiting=()=>{
        setWaiting(true)
    }
    // 可以播放时,隐藏加载中提示
    const onCanPlay=()=>{
        setWaiting(false)
    }
    return <div className="video-wrapper">
            <video ref={videoDom}  src={src} onLoadedMetadata={onLoad} onTimeUpdate={onTimeUpdate} onWaiting={onWaiting} onCanPlay={onCanPlay}  ></video>
            {/* 视频加载时显示loading */}
            {waiting && <div className="waiting">loading...</div>}
            <div className="video-controls">
                {/* 播放按钮 */}
                {isPause? <button onClick={()=>{handlePlay(true)}}>播放</button>: <button onClick={()=>{handlePlay(false)}}>暂停</button>}
                {/* 进度条 */}
                <input type="range" min="0" max={duration}  value={curTime} onChange={onSliderChange}/>
                {/* 时间信息和分辨率信息 */}
                <span>{formatDuration(curTime)}/{formatDuration(duration)}</span>
                <span>分辨率:{size.width}x{size.height}</span>
            </div>
        </div>
}
export default VideoPlayer

Стиль написан немного,VideoPlayer.css

.video-wrapper{
    width:800px;
}
.video-wrapper>video{
    width: 100%;
}

.video-controls{
    margin-top: 20px;
}

В центре внимания этой статьи не React, React — это просто носитель, ту же логику можно легко реализовать с помощью Vue, основное внимание уделяется настройке логики видеоплеера.