itube-modern-player 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -2
- package/dist/core.cjs +4 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +631 -548
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +22 -23
- package/dist/index.js.map +1 -1
- package/dist/itube-modern-player.iife.js +3 -3
- package/dist/itube-modern-player.iife.js.map +1 -1
- package/dist/lazy.cjs +1 -1
- package/dist/lazy.cjs.map +1 -1
- package/dist/lazy.d.ts +10 -2
- package/dist/lazy.js +56 -63
- package/dist/lazy.js.map +1 -1
- package/dist/placeholder.cjs +2 -0
- package/dist/placeholder.cjs.map +1 -0
- package/dist/placeholder.d.ts +32 -0
- package/dist/placeholder.js +42 -0
- package/dist/placeholder.js.map +1 -0
- package/dist/types.d.ts +19 -2
- package/dist/vue.cjs +1 -1
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.ts +68 -5
- package/dist/vue.js +131 -38
- package/dist/vue.js.map +1 -1
- package/package.json +7 -2
- package/dist/dom-Bq7EQenh.cjs +0 -5
- package/dist/dom-Bq7EQenh.cjs.map +0 -1
- package/dist/dom-DrpWbY0y.js +0 -87
- package/dist/dom-DrpWbY0y.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Содержание
|
|
8
8
|
|
|
9
|
+
- [Подключить за 2 минуты (копипаст)](#подключить-за-2-минуты-копипаст)
|
|
9
10
|
- [Возможности](#возможности)
|
|
10
11
|
- [Установка](#установка)
|
|
11
12
|
- [Быстрый старт (vanilla JS / TS)](#быстрый-старт-vanilla-js--ts)
|
|
@@ -40,6 +41,87 @@
|
|
|
40
41
|
- [Сборка и публикация](#сборка-и-публикация)
|
|
41
42
|
- [История изменений](#история-изменений)
|
|
42
43
|
|
|
44
|
+
## Подключить за 2 минуты (копипаст)
|
|
45
|
+
|
|
46
|
+
Три готовых рецепта. Скопируй подходящий целиком, подставь свои URL — работает.
|
|
47
|
+
|
|
48
|
+
### Рецепт 1: просто HTML-страница (без npm и сборщика)
|
|
49
|
+
|
|
50
|
+
Сохрани как `index.html`, открой в браузере. Всё.
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<!doctype html>
|
|
54
|
+
<html>
|
|
55
|
+
<head>
|
|
56
|
+
<link rel="stylesheet" href="https://unpkg.com/itube-modern-player/dist/style.css">
|
|
57
|
+
</head>
|
|
58
|
+
<body>
|
|
59
|
+
<div id="player"></div>
|
|
60
|
+
|
|
61
|
+
<!-- hls.js нужен ТОЛЬКО если видео — .m3u8 (стрим). Для .mp4 эту строку можно удалить. -->
|
|
62
|
+
<script src="https://unpkg.com/hls.js"></script>
|
|
63
|
+
<script src="https://unpkg.com/itube-modern-player/dist/itube-modern-player.iife.js"></script>
|
|
64
|
+
<script>
|
|
65
|
+
new ITubePlayer('#player', {
|
|
66
|
+
source: {
|
|
67
|
+
src: 'https://example.com/video.m3u8', // ← твоё видео (.m3u8 или .mp4)
|
|
68
|
+
poster: 'https://example.com/poster.jpg', // ← твоя обложка
|
|
69
|
+
title: 'Название ролика',
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
</script>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Что получится: обложка с кнопкой play; по клику — воспроизведение со всеми контролами.
|
|
78
|
+
|
|
79
|
+
### Рецепт 2: проект со сборщиком (Vite / webpack / любой)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm i itube-modern-player
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { Player } from 'itube-modern-player'
|
|
87
|
+
import 'itube-modern-player/style.css'
|
|
88
|
+
|
|
89
|
+
new Player('#player', {
|
|
90
|
+
source: { src: '/video.m3u8', poster: '/poster.jpg', title: 'Название' },
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
hls.js для `.m3u8` подтянется сам, отдельным чанком — ставить и импортировать его не нужно.
|
|
95
|
+
|
|
96
|
+
### Рецепт 3: Nuxt 3 / Vue 3 (рекомендуемый — быстрый LCP из коробки)
|
|
97
|
+
|
|
98
|
+
```vue
|
|
99
|
+
<script setup lang="ts">
|
|
100
|
+
import { ITubePlayer } from 'itube-modern-player/vue'
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<template>
|
|
104
|
+
<!-- lazy = постер приходит в первом HTML (SSR), тяжёлый плеер качается
|
|
105
|
+
только когда пользователь потянулся к видео. Никаких ClientOnly. -->
|
|
106
|
+
<ITubePlayer
|
|
107
|
+
lazy
|
|
108
|
+
:source="{ src: '/video.m3u8', poster: '/poster.jpg', title: 'Название' }"
|
|
109
|
+
:options="{ muted: true }"
|
|
110
|
+
@ended="onEnded"
|
|
111
|
+
/>
|
|
112
|
+
</template>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Если что-то не так
|
|
116
|
+
|
|
117
|
+
| Симптом | Причина и лечение |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| Видео не стартует само | Браузеры блокируют автоплей со звуком. Нужен автостарт — `playOnInit: true` **плюс** `muted: true`. Иначе — старт только по клику, это норма |
|
|
120
|
+
| Чёрный прямоугольник вместо плеера | Не подключён `style.css` (рецепт 1 — `<link>`, рецепт 2 — `import`) |
|
|
121
|
+
| `.m3u8` не играет (в рецепте 1) | Удалил строку с hls.js — верни её |
|
|
122
|
+
| Контролы на английском | Добавь в опции `language: 'ru'` |
|
|
123
|
+
| Реклама не нужна | Просто не передавай `adConfig` — её и не будет |
|
|
124
|
+
|
|
43
125
|
## Возможности
|
|
44
126
|
|
|
45
127
|
- **Источники** — MP4/WebM, HLS-стримы (`.m3u8`, hls.js или нативно в Safari), live-потоки с бейджем LIVE, прогрессивные качества с переключением без потери позиции, HLS-уровни с пунктом Auto.
|
|
@@ -267,7 +349,7 @@ const source: VideoSource = {
|
|
|
267
349
|
|
|
268
350
|
Стандартный формат — WebVTT, каждый cue указывает картинку и регион спрайта:
|
|
269
351
|
|
|
270
|
-
```
|
|
352
|
+
```text
|
|
271
353
|
WEBVTT
|
|
272
354
|
|
|
273
355
|
00:00:00.000 --> 00:00:05.000
|
|
@@ -620,13 +702,38 @@ player.off('timeupdate', fn)
|
|
|
620
702
|
|
|
621
703
|
## Vue 3: `<ITubePlayer>`
|
|
622
704
|
|
|
705
|
+
Ядро подтягивается **динамическим импортом** — сам компонент весит ~2 KB gzip и не тащит плеер в главный бандл приложения.
|
|
706
|
+
|
|
623
707
|
| Что | API |
|
|
624
708
|
| --- | --- |
|
|
625
709
|
| Пропсы | `source: VideoSource \| VideoSource[]` (реактивный — смена вызывает `load()`), `options: Omit<PlayerOptions, 'source'>` |
|
|
710
|
+
| `lazy` | **poster-first, player-on-intent**: компонент рендерит декларативную SSR-заглушку (постер уходит в первый HTML и становится LCP-кандидатом — `<ClientOnly>` не нужен), по триггеру качает чанк ядра + CSS и свапает через реактивное состояние. Клик по заглушке = загрузить и играть; фоновые триггеры не автоплеят |
|
|
711
|
+
| `loadOn` | триггер при `lazy`: `'placeholder'` (по умолчанию — любой интерактив в зоне заглушки), `'interaction'`, `'visible'`, `'immediate'` |
|
|
712
|
+
| `adConfig` | `AdsOptions` или **async-фабрика** `() => Promise<AdsOptions \| undefined>` (например, запрос VAST-тега) — выполняется параллельно загрузке чанка, плеер конструируется с готовым конфигом. Приоритетнее `options.adConfig` |
|
|
626
713
|
| События | Все события `PlayerEventMap` ретранслируются 1:1 (`@timeupdate`, `@aderror`, `@customaction`, …) |
|
|
627
714
|
| Слоты | `#pauseScreen="{ player, close }"` — контент экрана паузы (scoped: доступ к плееру и `close()`) |
|
|
628
715
|
| Expose | `player: ShallowRef<Player \| null>` — доступ к ядру: `playerRef.value.player.seek(0)` |
|
|
629
716
|
|
|
717
|
+
```vue
|
|
718
|
+
<!-- Nuxt 3: без ClientOnly, без ручного постера, без createLazyPlayer -->
|
|
719
|
+
<ITubePlayer lazy :source="video" :options="{ muted: true }" :ad-config="fetchVast" @ended="onEnded" />
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
CSS компонент подгружает сам (self-reference `itube-modern-player/style.css` через exports пакета); ручной импорт `style.css` в приложении продолжает работать и дедуплицируется бандлером — это фолбэк для экзотических сборок.
|
|
723
|
+
|
|
724
|
+
## Изоморфный шаблон заглушки: `itube-modern-player/placeholder`
|
|
725
|
+
|
|
726
|
+
`renderPlaceholder(options, flags?) → string` — чистая строка без DOM-зависимостей, единый источник правды по разметке «постер + кнопка play». Используется внутри `createLazyPlayer` и Vue-`lazy`; экспортируется для SSR любого фреймворка:
|
|
727
|
+
|
|
728
|
+
```ts
|
|
729
|
+
import { renderPlaceholder } from 'itube-modern-player/placeholder'
|
|
730
|
+
// options: { poster?, icon?, styling?, className?, playLabel? }
|
|
731
|
+
// flags: { inlineStyles?: true } — самодостаточные инлайн-стили (SSR без style.css)
|
|
732
|
+
const html = renderPlaceholder({ poster: { src: '/p.jpg', width: 1280, height: 720 } }, { inlineStyles: true })
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
Там же `posterSrc(poster)` — нормализация `PosterSource` в URL.
|
|
736
|
+
|
|
630
737
|
## Экспортируемые типы
|
|
631
738
|
|
|
632
739
|
`PlayerOptions, VideoSource, ChannelInfo, SubtitleTrack, Chapter, QualityLevel, PlaylistOptions, ControlsOptions, ActionsOptions, CustomAction, BuiltinActionId, RelatedOptions, RelatedItem, AdsOptions, AdRoll, ResolvedAd, ThumbnailCue, PlayerLabels, IconName, PlayerEvent, PlayerEventMap, Level, SourceController, NormalizedChapter`
|
|
@@ -769,7 +876,8 @@ npm publish # prepublishOnly прогонит typecheck + build
|
|
|
769
876
|
| Импорт | Что это |
|
|
770
877
|
| --- | --- |
|
|
771
878
|
| `itube-modern-player` | ядро (`Player`, все типы, утилиты) |
|
|
772
|
-
| `itube-modern-player/vue` | Vue 3-компонент `ITubePlayer` |
|
|
879
|
+
| `itube-modern-player/vue` | Vue 3-компонент `ITubePlayer` (ядро — динамическим импортом; проп `lazy`) |
|
|
880
|
+
| `itube-modern-player/placeholder` | изоморфный `renderPlaceholder()` + `posterSrc()` (без DOM — можно на сервере) |
|
|
773
881
|
| `itube-modern-player/style.css` | стили (подключить один раз) |
|
|
774
882
|
|
|
775
883
|
---
|
|
@@ -778,6 +886,13 @@ npm publish # prepublishOnly прогонит typecheck + build
|
|
|
778
886
|
|
|
779
887
|
Версионирование по [SemVer](https://semver.org/lang/ru/): `major.minor.patch`.
|
|
780
888
|
|
|
889
|
+
### 0.8.0
|
|
890
|
+
|
|
891
|
+
- **Vue-обёртка: ядро — динамическим импортом.** `itube-modern-player/vue` больше не тащит весь плеер в бандл приложения (~2 KB gzip вместо ~30): чанк ядра качается на mount, а с новым пропом **`lazy`** — по интенту. `lazy` = poster-first: декларативная SSR-заглушка (постер в первом HTML, LCP-кандидат, `<ClientOnly>` не нужен), триггер `loadOn` (`'placeholder'` по умолчанию / `'interaction'` / `'visible'` / `'immediate'`), своп через реактивное состояние — никакого чужого DOM. CSS подгружается самим компонентом (self-reference через exports; ручной импорт `style.css` остаётся рабочим фолбэком). NB: `import { Player } from '…/vue'` теперь только тип (рантайм-класс — из главного entry).
|
|
892
|
+
- **`adConfig` как async-фабрика** в lazy-слоях (`createLazyPlayer` и Vue-компонент): `adConfig: () => Promise<AdsOptions | undefined>` выполняется параллельно загрузке чанка — интегратору не нужно самому синхронизировать VAST-запрос с инициализацией.
|
|
893
|
+
- **Изоморфный шаблон заглушки** — новый entry `itube-modern-player/placeholder`: `renderPlaceholder(options, { inlineStyles? }) → string` без DOM-зависимостей (SSR любого фреймворка) + `posterSrc()`. Единый источник правды по разметке: `createLazyPlayer` и Vue-`lazy` рендерят её же — кастомная иконка `bigPlay`, `styling`, постер с полными `<img>`-атрибутами.
|
|
894
|
+
- **`poster` как объект.** `VideoSource.poster: string | { src, srcset?, sizes?, width?, height?, alt? }` — LCP-качество главного постера (responsive srcset, intrinsic-размеры против layout shift); тумбы используют `src`. Строка работает как раньше.
|
|
895
|
+
|
|
781
896
|
### 0.7.2
|
|
782
897
|
|
|
783
898
|
- **Скип битых роликов в «следующем видео».** Если при подготовке превью следующего ролика (ховер-карточка / end-оверлей) его постер не загрузился (4xx/5xx/сеть) — видео тоже не загрузится: источник помечается мёртвым и все вычисления «следующего» (превью, `next()`, автопереход, `hasNext`) пропускают его, подставляя следующий живой из списка. Карточка перерисовывается на лету; если живых впереди нет — прячется, next-кнопка дизейблится. Публичный метод `player.markSourceDead(source)` — пометить источник вручную. Панель плейлиста по-прежнему показывает все элементы.
|