Написать веб-видеоплеер с нуля

внешний интерфейс прямая трансляция

предисловие

За последние недели мы завершили пересмотр живой страницы и страницы воспроизведения видео Университета Куцзяле. В ходе этого процесса стоит записать некоторые обсуждения и мысли. В этой статье будет представлен процесс внедрения веб-видеоплеера.

Передний совет 1. В этой статье не рассматриваются детали реализации веб-видеоплеера.
Передний совет 2. Веб-видеоплеер, который будет обсуждаться в этой статье, не включает в себя базовую реализацию или другие знания о видеоформатах, битрейтах и ​​т. д., а представляет собой веб-видеокомпонент на чистом HTML5.
Front Tip 3: При написании статьи в первый раз некоторые слова могут быть неуместно выражены, пожалуйста, укажите.

Подключаемый модуль видеопроигрывателя, используемый в старой версии страницы воспроизведения видео Kujiale, называется video.js, очень расширяемым подключаемым модулем проигрывателя со многими пользователями. video.js также обеспечивает поддержку Flash player. Версия браузера переключает видео проигрыватель Flash и HTML5, что позволяет получить такой же опыт воспроизведения, как и у продвинутых браузеров в браузерах с низкой версией, и имеет множество плагинов.Можно сказать, что функции, которые вам нужны, являются общими. можно решить с помощью плагинов, но из-за его очень мощных функций я его не использую. С одной стороны, хотя video.js является мощным, он также требует определенных затрат на обучение. друг-дизайнер доволен, вам нужно изменить его стиль, И изменить стиль video.js не так уж и гибко.С другой стороны, как интерфейс с преследованием, почему бы мне не разработать видеоплеер самостоятельно?

Если бы два года назад я бы точно не сказал, что буду писать веб-видеоплеер с нуля, тому две причины, одна из них — производственная среда двухлетней давности все еще должна быть совместима со старой версией IE Browser, вы Придется использовать Flash, чтобы позаботиться об этих ностальгирующих пользователях, еще одна причина в том, что два года назад я не знал внешнего интерфейса, эта шутка может быть немного холодной, но реальная цель заключается в разработке современного браузера. Веб-видеоплеер HTML5 не так уж и сложен. И бизнес нашей компании просто должен быть совместим с современными браузерами выше IE11, поэтому нам не нужно рассматривать Flash, что избавляет от многих проблем!

Кроме того, в последнее время, если вы посещаете несколько известных домашних видео-сайтов, вы можете обнаружить, что в дополнение к версии браузера Flash также будет версия видеоплеера с чистым HTML5, такая как Tencent Video, Youku и Bilibili и т.д., особенно Да, Bilibili тоже с открытым исходным кодом.Flv.js, использованиеMedia Source Extensionsреализовано в HTML5 Библиотека JavaScript для воспроизведения видео в формате FLV в видео, чтобы многие видео в формате FLV можно было воспроизводить на встроенных видеоплеерах HTML 5. Я использовал эту библиотеку, когда создавал живую страницу Kujiale. Глядя на структуру DOM видеопроигрывателей HTML5 на вышеуказанных веб-сайтах, вы обнаружите, что в дополнение к самому элементу видео, который изначально предоставляется браузером, все функциональные модули на панели управления, необходимые для других проигрывателей, реализовано с помощью моделирования DOM, например индикатор выполнения, выбор объема и т. д. Эти функциональные модули фактически предусмотрены в родном видеоплеере, но ведут себя по-разному в разных браузерах.
Выглядят они так: (хром)

Таким образом: (край)

и это: (Файрфокс)

В целом, чтобы добиться согласованного взаимодействия с пользователем и функционального расширения, мы не будем использовать собственные видеоплееры в производственных средах, поэтому мы используем DOM для имитации этих функциональных модулей.

Подводя итог: все, что вам нужно сделать для реализации видеоплеера, — это использовать нативный видеоэлемент в качестве носителя воспроизведения, а затем написать для него набор управляющих интерфейсов для управления состоянием видеоэлемента. Мы опишем этот процесс на примере полного проигрывателя.

приступить к реализации

Прежде всего, посмотрите на конечный эффект:

Я называю его KuPlayer.Как упоминалось ранее, KuPlayer использует собственный элемент видео, как и некоторые распространенные проигрыватели HTML5, но не устанавливает элементы управления, что заставляет браузер предоставлять только видеопроигрыватель без панели управления, а затем мы смоделировали панель управления проигрывателем, используя ДОМ.
KuPlayer состоит из следующих функций в разделе панели управления:

  1. воспроизведение / пауза
  2. Отображение продолжительности видео
  3. контроль громкости
  4. Раздел индикатора выполнения - отображение загрузки воспроизведения и отображение прогресса
  5. Выбор разрешения
  6. полноэкранное управление

Сначала взгляните на общую структуру DOM:

Обратитесь к приведенной выше структуре DOM для краткого ознакомления с этими элементами DOM и их функциями.

  1. kp-media — это сам элемент видео,
  2. kp-controlsЭто родительский элемент панели управления, написанный для него, а его дочерние элементы соответствуют функции панели управления.
  • kp-play и kp-pause — это кнопки для управления воспроизведением и паузой видео соответственно.
  • kp-progress представляет индикатор выполнения
  • kp-time указывает продолжительность отображения
  • kp-volume - регулятор громкости видео
  • kp-resolution — переключатель разрешения
  • kp-full и kp-cancelFull используются для переключения видео в полноэкранный режим.
    То, как организована конкретная структура DOM, полностью зависит от функциональности, требуемой бизнесом, и приведенное выше является лишь базовым примером.

Далее я начну с основных стилей, а затем представлю, как реализованы некоторые из этих функциональных моментов, например, как управлять воспроизведением и паузой, как изменять громкость видео, как добиться полноэкранного режима и как правильно отображать индикатор выполнения (включая ход воспроизведения) и ход буфера). Аналогично реализованы и другие функции, поэтому я не буду описывать их по отдельности.

Сначала поговорим об основном стиле.

Исходный размер элемента видео соответствует размеру воспроизводимого видео. Объясните здесь, это означает, что его визуальный экран всегда масштабируется с воспроизводимым видео, аналогично установке фонового изображения для элемента какbackground-size: cover, поэтому, если элемент видео установлен наwidth:100%а такжеheight:100%, он не будет растянут, как предполагалось, но будет вести себя в соответствии со своей первоначальной пропорцией, установленной наwidth:100%,height:100%а такжеwidth:100%,height:autoПроизводительность выглядит следующим образом:

Как видите, даже если установлено значениеwidth:100%,height:100%, или как пропорциональное отображение исходного видео, браузер автоматически дает сплошной черный фон невидимым областям видео, а не растягивается, как я предполагал.
Оглядываясь назад на структуру DOM только что, мы видим, что вся структура DOM игрока состоит только из трех элементов: Div, Button и Input. Среди них Div — это элемент-оболочка некоторых модулей, а Button — некоторые кнопки, такие как воспроизведение и пауза.Так что же делает элемент Input?

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

Полоса в форме трека с ползунком на нем, который люди не могут не перетаскивать, вы можете перетаскивать его и изменять текущий прогресс воспроизведения, а я ленивый человек, поэтому я даже пишу небольшой элемент управления, который можно перетаскивать Слишком ленивый для этого есть ли какие-либо собственные элементы DOM, которые можно использовать? Ответ — да, просто установите для элемента Input значение(type='range')просто сделай это. Давайте посмотрим, как выглядит элемент Input Range в браузере на примере браузера chrome (все браузеры, используемые в следующих примерах, — это chrome ). Простой элемент Input Range выглядит в браузере так:

Помимо того, что он немного уродлив, он, кажется, делает то, что я хочу, так что есть ли способ изменить его стиль? После недолгих поисков и проб он на моих руках превратился в вот это! Ползунок, который становится синим внизу на изображении ниже, — это состояние наведения.

Метод очень прост, фактически он заключается в модификации трека и бегунка соответственно, используются элементы псевдокласса:

:-webkit-slider-runnable-trackа также:-webkit-slider-thumb, что похоже на изменение собственного стиля полосы прокрутки браузера, но, что удивительно, основные браузеры очень совместимы с этими свойствами, но вам, возможно, придется написать аналогичный псевдокласс для каждого браузера.Если вы используете scss или меньше, он будет очень удобно использовать миксин. Например, как показано ниже:

Стоит отметить, что-webkit-appearance: none, это утверждение очень важно, оно заставит браузер отказаться от собственного стиля,эта статьяПодробно представил, для разных браузеров всегда есть какие-то странные отличия, например, в браузере chrome значение margin-top для slider-thumb должно быть установлено равным -4px, иначе ползунок всегда будет смещаться вниз на 4px.Это может быть шуткой для нас со стороны браузера, но часто раздражает фронтенд-инженеров.В интернете много подобных статей про изменение стиля Input Range элемент, который не будет здесь указан. После такого метания стиль красивый, но кажется, что это не так просто, как напрямую с помощью div имитировать скользящее управление.На самом деле это не так.Очень громоздко использовать элементы псевдокласса для модификации и адаптироваться к основным браузерам, но это браузер.То, что изначально предоставляется разработчикам, использование родного родного гораздо более естественно, чем ручное моделирование, но текущие браузеры все еще очень разные, но это можно рассматривать как видение, если однажды , нам не нужно нацеливаться на каждый. Если большие браузеры пишут так много псевдоклассов, мы можем потратить нашу энергию на более стоящие вещи...

Как написать css других элементов, полностью зависит от визуального проекта.Конечно, если он используется как независимый компонент плеера, некоторые хорошие поведения в процессе разработки могут сделать последующее обслуживание более удобным, например, разумные имена классов, лаконичный DOM уровень, разумные элементы DOM плюс необходимая семантика и т. д. Конечно, KuPlayer еще нужно оптимизировать некоторые моменты в этом отношении, и ваши предложения приветствуются.

Поговорим о реализации функции

Сначала откройте MDN и выполните поискvideoelement , вы увидите, что существует так много атрибутов и событий, которые относятся только к элементу видео, только их целых 23 события! Например: прервать, можно играть, завершено, ошибка, загружены метаданные и т. д. Эти события являются внутренними событиями элемента видео, и все его объекты эффектов относятся к воспроизводимому видео. А фронтенд-инженеры хотят управлять его воспроизведением и паузой или какими-то другими состояниями, они не могут напрямую вызывать эти события внутри него, но они могут прослушивать эти события и добиваться каких-то спецэффектов, например, когда Когда происходят ошибки и зависшие события, их следует прослушивать, а пользователю следует говорить: «Извините, ваша сеть не в порядке, пожалуйста, обновите и попробуйте еще раз!».

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

Сначала создайте класс KuPlayer

class KuPlayer {}

Как воспроизвести и приостановить видео

Элемент video1o предоставляет множество методов, позволяющих разработчикам контролировать его состояние. Например, методы воспроизведения и паузы могут управлять воспроизведением и паузой видео. Если эти два метода вызываются, события воспроизведения и паузы внутри элемента видео также будут При немедленном срабатывании состояние воспроизведения видео также изменится немедленно, например, при вызове метода pause() атрибут paused видеоэлемента, полученный в это время, станет истинным.
Итак, мы можем написать так (код только для справки)

class KuPlayer {
 constructor(){
 // 首先获取到媒体对象,指代 video 元素本身,下文所有video元素都以此代替。
 this.media = document.querySelector('.J_kpMedia');
 }
 // 然后是 play 和 pause 方法。 
 play(){
 // 执行原生play()方法
 this.media.play();
 // 这里显示播放器播放状态UI
 }
 pause(){
 // 执行原生pause()方法
 this.media.pause();
 // 这里显示播放器暂停状态UI
 }
}

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

Это то, что я обнаружил, когда быстро протестировал воспроизведение и паузу в плеере.Я перешел по указанному URL-адресу и обнаружил, что хром уже сообщил нам, почему появилось это приглашение.

Получается, что this.media.play() вернет Promise! Если функция Promise успешно выполнена, видео будет воспроизведено, а элемент video также выполнит событие воспроизведения. Причина этого сообщения об ошибке в том, что оно находится в this.media. Когда асинхронная операция ( Promise ), возвращаемая play(), не была разрешена или отклонена, принудительно вызывается метод this.media.pause(), чтобы прервать процесс, так что само видео не воспроизводится успешно, поэтому консоль выдает эту ошибку, когда на самом деле вызывает Метод pause() — не единственный способ остановить этот процесс, он будет срабатывать при изменении текущего хода воспроизведения или замене src видео, поэтому в случае плохой сети или некоторых операций, таких как частые пользовательские переключение При воспроизведении и паузе подсказка будет срабатывать непрерывно.

Хотя эта ошибка больше похожа на предупреждение, даже если будет сообщено об ошибке, она не будет воспринята пользователем и не повлияет на весь процесс воспроизведения, но невыносимо, как интерфейс, сообщать об ошибках в консоли, поэтому мы должны указать this.media.Добавить обработку ошибок в обещание, возвращаемое методом play(). Это нормально для простой обработки, по крайней мере, консоль больше не будет сообщать об ошибке.

play() {
 // 返回一个promise
 const playPromise = this.media.play();
 if (playPromise !== undefined) {
 playPromise.catch(() => {
				//
 });
 }
 }

Однако в playPromise.catch() наиболее подходящей операцией является прямой вызов метода this.pause(), который заставляет его продолжать отображать состояние паузы при сбое события play().
As our business requirements, when users turn on the player page when needed autoplay video, but when I was in safari browser testing, I found another surprise: the video does not play automatically on safari in the player, it would not be Apple is prohibited вне?一番搜索后,果不其然,如这里所说 :Auto-Play Policy Changes for macOS, автоматическое воспроизведение видео отключено в Safari 11, и пользователям необходимо вручную щелкнуть, чтобы выбрать, разрешить ли автоматическое воспроизведение. А по недостоверной информации, чтобы не подходить всем под одну гребенку, Apple добавила в белый список 11 видеосайтов, таких как Tencent Video и Youku, что позволяет их веб-страницам воспроизводить видео напрямую, но для других сайтов это не так. повезло. , но Apple также интимно рассказала разработчикам, как быть в этой ситуации:

Разработчики могут активно вызывать событие this.media.play(), но поскольку оно будет заблокировано сафари, обещание, возвращаемое this.media.play(), будет отклонено Мое решение состоит в том, чтобы вызвать this.pause непосредственно в теле метод функции catch (), напрямую приостанавливает воспроизведение и отображает пользовательский интерфейс в состоянии паузы, проблема решена, но это не может дать пользователям Safari возможность играть при открытии страницы.

как изменить громкость видео

Атрибут тома нативного видеоэлемента является атрибутом доступа: как геттером, так и сеттером. Вы можете установить или вернуть текущую громкость видео, и его диапазон значений составляет 0,0–1,0 (по умолчанию 1,0), поэтому вызывайте его напрямую.

this.media.volume = 0.5;

Вы можете установить текущую громкость видео на 0,5, чтобы контролировать громкость самого видео, но на самом деле избыточный диапазон и интервал громкости может быть определен разработчиком, например, видеоплеер Tencent устанавливает громкость диапазон до 0. - 100 , на самом деле это просто замена отношения, и изменение является размером объема самого элемента видео.

Вы можете установить уровень громкости, или вы можете установить отключение звука напрямую, установить текущее значение громкости на 0,0 или установить для атрибута muted элемента видео значение true (атрибут muted — это логический атрибут, который может устанавливать и возвращать, будет ли видео воспроизводиться). выключен) Отключить звук видео.
Срабатывает после того, как уровень громкости видео изменен[volumechange](https://developer.mozilla.org/en-US/docs/Web/Events/volumechange) метод.

Метод Volumechange запускается при изменении громкости звука (либо при изменении свойства громкости, либо при изменении свойства отключения звука).

Как изменить текущий прогресс видео.

Как и свойство Volume, упомянутое выше, currentTime также является свойством-аксессором.[getter](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/get)Слишком[setter ](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/set), currentTime может устанавливать или возвращать текущую позицию воспроизведения аудио/видео, поэтому прямое присвоение определенного значения this.media.currentTime может изменить ход воспроизведения видео, но его необходимо согласовать с некоторыми пользовательскими интерфейсами и интерактивными модификациями. Далее будет упомянуто как изменить индикатор выполнения. После активной установки curentTime запускаются методы поиска и поиска самого видеоэлемента.

Способ поиска и способ поиска соответственно указывают, что операция перехода выполняется (изменение момента времени воспроизведения) и операция перехода завершена.

Как добиться полноэкранного видео

Полный экран воспроизведения видео можно разделить на два типа: псевдополный экран и собственный полный экран.Псевдополный экран реализуется путем прямого увеличения текущего элемента до размера окна.iQIYI обеспечивает полноэкранные веб-страницы во время видео воспроизведение., но он будет заполнять только текущий размер окна браузера, а не размер окна всего экрана. По моему личному опыту, иммерсивный просмотр, обеспечиваемый заполнением всего экрана, лучше, чем заполнение окна браузера. , поэтому KuPlayer обеспечивает только собственный полноэкранный режим, окончательный эффект показан на рисунке ниже: видео будет занимать весь экран, и будет встроенная подсказка «Нажмите ESC, чтобы выйти из полноэкранного режима», фактический эффект эквивалентен тому, что в
окно Нажмите клавишу F11 вниз.

Стандартный способ вызвать полноэкранный режим:Element.requestFullscreen, этот метод используется для отправки асинхронного запроса, чтобы элемент перешел в полноэкранный режим, но, учитывая совместимость браузера, он должен быть совместим с браузерами с такими префиксами, как webkit, moz, ms и т. д.
Таким образом, код для запроса полноэкранного режима можно записать так (пока только для справки):

requestFullscreen(elem) {
 if (elem.requestFullscreen) {
 elem.requestFullscreen();
 } else if (elem.msRequestFullscreen) {
 elem.msRequestFullscreen();
 } else if (elem.mozRequestFullScreen) {
 elem.mozRequestFullScreen();
 } else if (elem.webkitRequestFullscreen) {
 elem.webkitRequestFullscreen();
 }
}

Способ отменить полноэкранный режимdocument.exitFullscreen, но интересно то, что хотя exitFullscreen и является методом выхода из полноэкранного режима в стандарте w3c, в chrome и Firefox он стал соответственно webkitCancelFullScreen и mozCancelFullScreen.Возможно, chrome считает более подходящим использовать [Cancel] чем [Выход].
Таким образом, код выхода из полноэкранного режима можно записать так:

cancelFullscreen(){
 if (document.exitFullscreen) {
 document.exitFullscreen();
 } else if (document.msExitFullscreen) {
 document.msExitFullscreen();
 } else if (document.mozCancelFullScreen) {
 document.mozCancelFullScreen();
 } else if(document.oRequestFullscreen){
 document.oCancelFullScreen();
 }else if (document.webkitExitFullscreen){
 document.webkitExitFullscreen();
 }
}

Как видно из приведенных выше двух фрагментов кода, для реализации полного экрана элемента необходимо вызвать его метод requestFullscreen, напримерdocument.queryselector('.kp-video).requestFullscreen(), но выход из полноэкранного режима запускается непосредственно в документе, поскольку при вызове метода requestFullscreen элемента элемент будет развернут на весь экран, включая его дочерние элементы. При этом полноэкранный элемент всего один, так что при отмене можно напрямую вызвать document.CancelFullScreen Вот и все.

Затем нам также нужно настроить некоторые эффекты в зависимости от того, является ли он полноэкранным или нет.В это время мы будем прослушивать его событие fullscreenchange на объекте документа.Независимо от того, запрашивает ли он полноэкранный режим или отменяет полноэкранный режим, после этих двух операций успешно, событие fullscreenchange будет запущено, и тогда мы находимся в этом методе, использует ли document.fullscreenElement равенствоnullчтобы определить, является ли текущее состояние уже полноэкранным, а затем вы можете настроить стиль полноэкранного состояния. На самом деле мы можем судить о текущем полноэкранном состоянии только после вызова события fullscreenchange, потому что requestFullscreen() сам по себе является асинхронным запросом. После отправки запроса полноэкранное состояние не будет запущено немедленно, и, поскольку это запрос, он либо завершится успешно, либо завершится неудачей. Неудачный метод requestFullscreen вызовет событие fullscreenerror.

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

Как показать индикатор выполнения

Видеопроигрыватель должен информировать пользователя о текущем ходе воспроизведения видео и ходе буферизации.
Для хода воспроизведения это не что иное, как получение текущего времени воспроизведения (currentTime) и общей продолжительности видео (duration), а затем отображение соотношения этих двух значений с использованием элементов и стилей.

использовать

const {currentTime, duration } = this.media

Вы можете получить текущее время и продолжительность видео, а затем выполнить простой процентный расчет:

const percent = `${currentTime/ duration * 100}%`

Затем используйте элементы и стили для имитации индикатора выполнения. Вы можете просто использовать div, а затем установить его ширину, или вы можете использовать собственный элемент прогресса, который включает изменение стиля элемента прогресса.Так же, как и модификация элемента Input Range выше, его необходимо написать для различных браузеров. разные стили,эта статьяЕсть подробные введения, поэтому я не буду повторять их здесь.

Теперь, когда вы знаете, как изменить ход воспроизведения, как сделать так, чтобы индикатор выполнения вел себя плавно и естественно? В это время необходимо хорошо использовать оригинал
Некоторые события, предоставляемые элементом видео:timeupdateЗапускается при обновлении currentTime. Это именно то, что нам нужно для отображения индикатора выполнения, поэтому мы можем напрямую отслеживать событие timeupdate, а затем выполнять вышеописанные операции получения длительности и вычисления коэффициента. Однако производительность прогресса есть не только при нормальном воспроизведении видео, если пользователь Во время операции поиска текущий ход воспроизведения должен быть соответствующим образом изменен, поэтому следите за видеоseekingсобытие, а затем продолжить вызов функции, которая изменяет ход воспроизведения, или вы можете вызвать ее вручную при изменении видео currentTime.

Реализация прогресса буферизации немного более громоздка, потому что атрибут, описывающий текущее состояние загрузки видео,Buffered, это свойство сообщит нам, какая часть видео была загружена. он возвращаетTimeRangesчтобы указать, какие фрагменты видео были загружены, объект TimeRanges содержит следующее:

Свойство length может получить количество буферизованных экстентов в видео.
Вызовите метод start(index), чтобы получить начало буферизованного диапазона.
Вызовите метод end(index), чтобы получить конец буферизованного диапазона.

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

const { buffered } = this.media;
const start = buffered.start(0);
const end = buffered.end(0);

Полученная разница между началом и концом представляет собой буферное пространство, но поскольку это случай без дополнительных операций в допущении, начало приблизительно равно 0, поэтому длина интервала, который мы хотим использовать, является фактическим значением конца. Затем, точно так же, как при воспроизведении индикатора выполнения, используйте элемент для имитации изменения хода выполнения. Точно так же вы можете отслеживать ход выполнения и события воспроизведения собственного элемента видео, чтобы изменить состояние буферизации для нас,

воспроизведение запускается, когда видео начинает воспроизводиться (независимо от того, воспроизводится ли оно в первый раз, возобновляется после паузы или перезапускается после его окончания).
progress Запускается периодически для информирования о ходе загрузки соответствующей части носителя. Информация об общем количестве загруженных на данный момент медиафайлов доступна в атрибуте buffered элемента.

Однако операция поиска неизбежна при воспроизведении видео.В настоящее время длина TimeRanges больше не равна 1. Каждый раз, когда вы переходите к небуферизованной области видео, будет создаваться новое буферное пространство, и этот буфер упорядочивается от наименьшего к самый большой.
Давайте воспользуемся схемой из MDN для описания процесса:

------------------------------------------------------------------------------
|=============|                   |===========|  |
------------------------------------------------------------------------------
0             5                   15         19 21

Это представляет два диапазона буферного времени: первый охватывает от 0 до 5 секунд, а второй — от 15 до 19 секунд. Если в это время для currentTime установлено значение 10, будет сгенерирован интервал буферизации, начинающийся с 10 секунд, и неизвестно, будет ли буфер буферизован до 13 секунд или до 14 секунд (в реальном тесте при буферизации до 15 секунд, 10 - 15-секундный буферный период комбинируется с 15-19-секундным буферным периодом). В настоящее время start(0) - end(0) больше не может быть использовано в качестве буферного пространства. Он должен взять буферное пространство с 10 в качестве начальной точки, а затем вычислить значение индекса между буферами: index, use buffered.start(index) для запуска буфера. buffered.end(index) используется как точка отсечки буфера, а затем разница между ними принимается за текущий буфер.

несколько советов

Благодаря реализации вышеуказанных конкретных функций можно обнаружить, что многие свойства, предоставляемые собственным видео, являются свойствами доступа.Чтобы получить прямой доступ к этим свойствам и предоставить их в созданном объекте, мы можем написать следующий код в классе.

class KuPlayer {
 constructor(){}
 
 ...
 
 get volume() {
 return this.media.volume;
 }

 set volume(value) {
 this.media.volume = value;
 }

 get muted() {
 return this.media.muted;
 }

 set muted(muted) {
 this.media.muted = muted;
 }

 get currentTime() {
 return this.media.currentTime;
 }
 ...
}

Кроме того, независимо от того, воспроизводится ли он и приостанавливается, или изменяется громкость и прогресс, или некоторые из самих видео, такие как загруженные метаданные (метаданные мультимедиа были загружены, и теперь все свойства содержат свою действительную информацию), ошибка ( в случае возникновения события After the event, необходимо прослушивать эти события в методе инстанцирования объекта, по этой причине мы вводим модуль events и вызываем методы on и emit для прослушивания видеоэлемента. Мероприятия.

import EventEmitter from 'events';
...
class KuPlayer {
 constructor(){
 // 首先获取到媒体对象,指代 video 元素本身。
 this.media = document.querySelector('.J_kpMedia');
 // 生成一个EventEmitter 的实例。
 this.emiter = new EventEmitter();
 }
 
 // 方法: 监听一个事件
 on(event, listener) {
 this.emiter.on(event, listener);
 }

 // 方法: 移除一个事件
 off(event, listener) {
 this.emiter.removeListener(event, listener);
 }

 // 方法: 触发一个事件
 emit(event, data) {
 this.emiter.emit(event, data);
 }
 
 // 方法: 播放视频
 play(){
 ...
 // 触发emiter 的 play 事件
 this.emit('play');
 }

 // 类方法:暂停视频
 pause(){
 ...
 // 触发emiter 的 pause 事件
 this.emit('pause');
 }
 
 ... 
}

После создания экземпляра вы можете напрямую использовать метод on для прослушивания внутренних событий проигрывателя:

const kuPlayer = new KuPlayer();

// 监听 KuPlayer play 事件
kuPlayer.on('play', ()=>{
 // 埋点或者其他的一些操作
})

// 直接获取当前 currentTime
console.log(kuPlayer.currentTime)
...

резюме

В этой статье представлена ​​только верхушка айсберга видеоэлемента, а также существует множество нативных событий и атрибутов видеоэлемента. Поскольку он не участвует в развитии бизнеса, исследования не проводились. Если вы обнаружите какие-либо ошибки в статья, обращайтесьtitian@qunhemail.com.

Я надеюсь, что эта статья вдохновит студентов, которые хотят разрабатывать веб-видеоплееры и делать более удивительные и практичные видеоплееры.
Кроме того, процесс разработки плеера и написание этой статьи ссылаются на множество отличных проектов и статей с открытым исходным кодом, в том числе:video.js,plyr.jsи МДН и т.д.

Наконец, поместите объявление.Есть ли друзья, желающие работать в Куджиале? В качестве внешнего интерфейса он должен быть совместим только с IE 11 или выше! Мы приветствуем лучших из вас!

知识共享许可协议
В этой работе используетсяCreative Commons Attribution-NonCommercial-ShareAlike 4.0 Международная лицензияЛицензия.