-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Добавил раздел с дополнительной информацией (работа с видео)
- Loading branch information
Showing
19 changed files
with
389 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
# Video.js | ||
|
||
[Video.js](https://github.com/videojs/video.js) - это библиотека с открытым исходным кодом, предназначенная для | ||
создания видео плеера. | ||
|
||
Сама по себе библиотека очень проста. Дополнительная функциональность поставляется в плагинах(плейлисты, аналитика, | ||
реклама, и расширенные форматы видео - `HLS` или `DASH`). | ||
|
||
## Установка | ||
|
||
### NPM | ||
|
||
```bash | ||
npm install --save-dev video.js | ||
``` | ||
|
||
### CDN | ||
|
||
```html | ||
<script src="http://vjs.zencdn.net/6.7.1/video.js"></script> | ||
``` | ||
|
||
```html | ||
<link href="http://vjs.zencdn.net/6.7.1/video-js.css" rel="stylesheet"> | ||
``` | ||
|
||
## Инициализация | ||
|
||
На странице должен присутствовать тег: | ||
|
||
```html | ||
<video class="video-js"></video> | ||
``` | ||
|
||
Передаем строку содержащую `id` элемента: | ||
|
||
```js | ||
let video = videojs('id'); | ||
``` | ||
|
||
Или `DOM` элемент | ||
|
||
```js | ||
let video = videojs(document.querySelector('.video-js')); | ||
``` | ||
|
||
## Опции | ||
|
||
Опции передаются вторым параметром: | ||
|
||
```js | ||
let video = videojs('my-video', { | ||
autoplay: false, | ||
}); | ||
``` | ||
|
||
**Основные опции**: | ||
|
||
* `autoplay: boolean` - автоматическое воспроизведение; | ||
* `controls: boolean` - отображать ли интерфейс плеера; | ||
* `loop: boolean` - зацикливание воспроизведения видео; | ||
* `muted: boolean` - приглушение звука; | ||
* `poster: string` - ссылка на превью видео; | ||
* `width: string|number` - ширина видео; | ||
* `height: string|number` - высота видео; | ||
|
||
**Дополнительные опции**: | ||
|
||
* `fluid: boolean` - подгонять ли видео под размер контейнера; | ||
* `aspectRatio: string` - соотношение сторон видео (16:9, 4:3); | ||
|
||
## Методы | ||
|
||
* `src(string|array)` - позволяет задать источник видео; | ||
|
||
```js | ||
video.src('/path/to/video.mp4'); | ||
|
||
video.src([ | ||
{ | ||
type: 'video/mp4', | ||
src: '/path/to/video.mp4', | ||
}, | ||
{ | ||
type: 'video/webm', | ||
src: '/path/to/video.webm', | ||
}, | ||
{ | ||
type: 'video/ogg', | ||
src: '/path/to/video.ogg', | ||
}, | ||
]); | ||
``` | ||
|
||
* `poster(string)` - позволяет задать превью видео; | ||
|
||
* `play()` - воспроизводит видео; | ||
|
||
* `pause()` - ставит видео на паузу; | ||
|
||
* `paused()` - возвращает `true`, если видео стоит на паузе, иначе `false`; | ||
|
||
* `dispose()` - полностью удаляет плеер (вызывает событие `dispose`, удаляет все обработчики событий, удаляет `DOM` элементы); | ||
|
||
* `volume(number)` - задает горомкость звука (число от `0` до `1`); если вызвать без параметра - возвращает текущее значение; | ||
|
||
* `muted(bolean)` - возвращае `true`, если звук выключен, иначе `false`; если передано `true` - выключает звук. | ||
|
||
* `requestFullscreen()` - вход в полноэкранный режим; | ||
|
||
* `exitFullscreen()` - выход из полноэкранного режима; | ||
|
||
* `isFullscreen()` - возвращает `true` если видео находится в полноэкранном режиме, иначе `false`; | ||
|
||
* `currentTime(number)` - возвращает текущее место воспроизведения (в секундах); если передать число - устанавливает текущее место; | ||
|
||
* `duration()` - возвращает длину видео; | ||
|
||
* `remainingTime()` - возвращает оставшееся время; | ||
|
||
**Пример**: | ||
|
||
```js | ||
let video = videojs('video', { | ||
controls: true, | ||
autoplay: false, | ||
loop: false, | ||
poster: '/video/cover.jpg', | ||
}); | ||
video.src({ | ||
src: '/video/video.mp4', | ||
withCredentials: true, | ||
}); | ||
video.on('ready', () => { | ||
// ... | ||
}); | ||
``` | ||
|
||
## События | ||
|
||
События те же, что у нативного элемента `video`. | ||
Полный список [тут](https://developer.mozilla.org/ru/docs/Web/Guide/Events/Media_events). | ||
|
||
**Пример**: | ||
|
||
```js | ||
video.on('dispose', () => { | ||
// ... | ||
}); | ||
video.on('play', () => { | ||
// ... | ||
}); | ||
video.on('ended', () => { | ||
// ... | ||
}); | ||
``` | ||
|
||
## Стриминг (HLS) | ||
|
||
Для стриминга `video.js` использует плагин [videojs-contrib-hls](https://github.com/videojs/videojs-contrib-hls). | ||
|
||
Как подготовить видео - описано [тут](20_hls.md) | ||
|
||
### Установка | ||
|
||
```bash | ||
npm install --save videojs-contrib-hls | ||
``` | ||
|
||
### Инициализация | ||
|
||
```js | ||
let video = videojs('my-video', { | ||
html5: { | ||
hls: { | ||
withCredentials: true, | ||
} | ||
} | ||
}); | ||
video.src({ | ||
src: 'video-name.m3u8', | ||
type: 'application/x-mpegURL', | ||
withCredentials: true, | ||
}); | ||
``` | ||
|
||
## Стилизация | ||
|
||
По умолчанию используется стандартный скин. | ||
|
||
```html | ||
<link href="http://vjs.zencdn.net/6.7.1/video-js.css" rel="stylesheet"> | ||
``` | ||
|
||
**Стандартный скин**: | ||
|
||
![Стандартная стилизация](images/19/image-1.jpg) | ||
|
||
**Отображение без стилей**: | ||
|
||
![Отображение без стилей](images/19/image-2.jpg) | ||
|
||
Для кастомной стилизаци, нужно использовать свои стили. | ||
|
||
**Пример своей стилизации**: | ||
|
||
![Своя стилизация](images/19/image-3.jpg) | ||
|
||
- Контейнер | ||
|
||
Вписываем контейнер в блок, у которого заданы размеры требуемые | ||
по макету. | ||
|
||
```html | ||
<div id="video" class="video-js"></div> | ||
``` | ||
|
||
```scss | ||
.video-js { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
``` | ||
|
||
- Элемент `<video>` | ||
|
||
Подгоняем формат, для предотвращения деформирования видео. | ||
|
||
```scss | ||
.vjs-tech { | ||
width: auto; | ||
height: 100vh; | ||
min-width: 100vw; | ||
object-fit: cover; | ||
@media (min-aspect-ratio: 1920 / 1080) { | ||
width: 100vw; | ||
height: auto; | ||
min-height: 100vh; | ||
} | ||
} | ||
``` | ||
|
||
- Обложка `.vjs-poster` | ||
|
||
- Спинер `.vjs-loading-spinner` | ||
|
||
- Кнопка воспроизведение\пауза `.vjs-play-control` | ||
|
||
- Кнопка вкл\выкл звук `.vjs-mute-control` | ||
|
||
- Полоса громкости `.vjs-volume-bar` | ||
|
||
- Текущее время видео `.vjs-current-time` | ||
|
||
- Длительность видео `.vjs-duration` | ||
|
||
- Оставшееся время `.vjs-remaining-time` | ||
|
||
- Прогресс бар `.vjs-progress-control` | ||
|
||
- Кнопка полноэкранного режима `.vjs-fullscreen-control` | ||
|
||
**Пример**: | ||
|
||
```scss | ||
.vjs-progress-control { | ||
display: block; | ||
} | ||
.vjs-progress-holder { | ||
position: relative; | ||
height: 4px; | ||
cursor: pointer; | ||
&::before { | ||
content: ""; | ||
position: absolute; | ||
left: 0; | ||
width: 100%; | ||
height: 4px; | ||
background-color: #fff; | ||
} | ||
} | ||
.vjs-play-progress { | ||
position: relative; | ||
display: block; | ||
width: 0; | ||
height: 4px; | ||
background-color: #000; | ||
.vjs-control-text { | ||
display: none; | ||
} | ||
.vjs-time-tooltip { | ||
display: none; | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# HTTP Live Streaming (HLS) | ||
|
||
`HLS` - протокол для потоковой передачи медиа (аудио/видео), на основе `HTTP`. | ||
|
||
В основе работы лежит принцип разбиения цельного потока на небольшие фрагменты, последовательно скачиваемые по `HTTP`. | ||
|
||
В начале сессии скачивается плей-лист в формате `.m3u8` (обычные текстовый файл), содержащий метаданные об имеющихся вложенных потоках. | ||
|
||
Сами потоки находятся в файлах с расширением `.ts`. | ||
|
||
Видео обычно кодируется с помощью `H264/h265`, аудио `AAC`. | ||
|
||
[Ссылка на статью](https://developer.apple.com/library/content/referencelibrary/GettingStarted/AboutHTTPLiveStreaming/about/about.html) | ||
|
||
|
||
## Конвертация (Подготовка файлов для стриминга) `.mp4` в `.m3u8` и `.ts` | ||
|
||
### FFMPEG | ||
|
||
1. Скачиваем и устанавливаем [FFMPEG](http://www.ffmpeg.org/download.html); | ||
2. Прописываем `FFMPEG` в `path`. | ||
3. Переходим в папку с видео: | ||
|
||
```bash | ||
cd video_folder_name/ | ||
``` | ||
|
||
4. Создаем папки под видео: | ||
|
||
``` | ||
mkdir 1080 720 406 270 180 | ||
``` | ||
|
||
5. Нарезаем видео: | ||
|
||
``` | ||
ffmpeg -i video_name.mp4 | ||
-s 1920x1080 -c:a aac -c:v libx264 -map 0 -f segment -segment_time 10 -segment_format mpegts -segment_list 1080/playlist-1080.m3u8 "1080/video_name-1080-%d.ts" | ||
-s 1280x720 -c:a aac -c:v libx264 -map 0 -f segment -segment_time 10 -segment_format mpegts -segment_list 720/playlist-720.m3u8 "720/video_name-720-%d.ts" | ||
-s 720x406 -c:a aac -c:v libx264 -map 0 -f segment -segment_time 10 -segment_format mpegts -segment_list 406/playlist-406.m3u8 "406/video_name-406-%d.ts" | ||
-s 480x270 -c:a aac -c:v libx264 -map 0 -f segment -segment_time 10 -segment_format mpegts -segment_list 270/playlist-270.m3u8 "270/video_name-270-%d.ts" | ||
-s 320x180 -c:a aac -c:v libx264 -map 0 -f segment -segment_time 10 -segment_format mpegts -segment_list 180/playlist-180.m3u8 "180/video_name-180-%d.ts" | ||
``` | ||
|
||
6. Делаем обложку: | ||
|
||
``` | ||
ffmpeg -i video_name.mp4 -ss 00:00:00 -vframes 1 cover.jpg | ||
``` | ||
|
||
На выходе получаем видео, раскиданное по папкам с нужным размером и разбитое на файлы `.ts`, манифесты `.m3u8` (содержащие метаинформацию о файлах для каждого размера) и обложку `cover.jpg`. | ||
|
||
5. Создаем мастер файл для объединения всех манифестов `video-name.m3u8`: | ||
|
||
``` | ||
#EXTM3U | ||
#EXT-X-VERSION:3 | ||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3880000,RESOLUTION=1920x1080,CODECS="mp4a.40.2,avc1.77.30",CLOSED-CAPTIONS=NONE | ||
1080/playlist-1080.m3u8 | ||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1810000,RESOLUTION=1280x720,CODECS="mp4a.40.2,avc1.77.30",CLOSED-CAPTIONS=NONE | ||
720/playlist-720.m3u8 | ||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=720x406,CODECS="mp4a.40.2,avc1.77.30",CLOSED-CAPTIONS=NONE | ||
406/playlist-406.m3u8 | ||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=600000,RESOLUTION=480x270,CODECS="mp4a.40.2,avc1.77.30",CLOSED-CAPTIONS=NONE | ||
270/playlist-270.m3u8 | ||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=410000,RESOLUTION=320x180,CODECS="mp4a.40.2,avc1.77.30",CLOSED-CAPTIONS=NONE | ||
180/playlist-180.m3u8 | ||
``` | ||
|
||
## Стандартные размеры видео для HLS | ||
|
||
* **180p** - 320x180px | ||
* **270p** - 480x270px | ||
* **406p** - 720x406px | ||
* **720p** - 1280x720px | ||
* **1080p** - 1920x1080px | ||
|
||
Точки `p` - определяющие название файла, берутся от высоты видео. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.