@vplayer/core 0.2.1 → 0.2.2
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/dist/index.d.ts +3 -3
- package/dist/index.js +630 -309
- package/dist/state/slices.d.ts +27 -3
- package/dist/storage.d.ts +9 -8
- package/dist/subtitle-parser.d.ts +89 -7
- package/dist/types.d.ts +44 -5
- package/package.json +6 -6
package/dist/state/slices.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { PlaybackProgress } from '../playback-progress';
|
|
|
16
16
|
import type { ControlRegistration, ContextMenuItem, FlipState, AspectRatioState } from '../plugin-api';
|
|
17
17
|
import type { LayerRegistration, SettingRegistration } from '../plugin-api';
|
|
18
18
|
import type { PlayerSource } from '../source-resolver';
|
|
19
|
-
import type { SubtitleTrack, ThumbnailCue } from '../subtitle-parser';
|
|
19
|
+
import type { CaptionSettings, SubtitleCue, SubtitleProviderInfo, SubtitleProviderResult, SubtitleTrack, ThumbnailCue } from '../subtitle-parser';
|
|
20
20
|
export type PlaybackStatus = 'idle' | 'loading' | 'ready' | 'playing' | 'paused' | 'buffering' | 'seeking' | 'ended' | 'error';
|
|
21
21
|
export interface MediaSlice {
|
|
22
22
|
status: PlaybackStatus;
|
|
@@ -41,6 +41,14 @@ export interface PreferencesSlice {
|
|
|
41
41
|
aspectRatio: AspectRatioState;
|
|
42
42
|
activeSubtitle: SubtitleTrack | null;
|
|
43
43
|
subtitleTracks: SubtitleTrack[];
|
|
44
|
+
subtitleCues: SubtitleCue[];
|
|
45
|
+
subtitleStatus: 'idle' | 'loading' | 'ready' | 'error';
|
|
46
|
+
subtitleError: string | null;
|
|
47
|
+
subtitleProviders: SubtitleProviderInfo[];
|
|
48
|
+
subtitleSearchResults: SubtitleProviderResult[];
|
|
49
|
+
subtitleSearchStatus: 'idle' | 'loading' | 'ready' | 'error';
|
|
50
|
+
subtitleSearchError: string | null;
|
|
51
|
+
captionSettings: CaptionSettings;
|
|
44
52
|
activeQuality: string;
|
|
45
53
|
qualities: string[];
|
|
46
54
|
}
|
|
@@ -71,8 +79,16 @@ export interface ErrorSlice {
|
|
|
71
79
|
isReconnecting: boolean;
|
|
72
80
|
} | null;
|
|
73
81
|
}
|
|
82
|
+
export type ResumeState = {
|
|
83
|
+
status: 'idle';
|
|
84
|
+
} | {
|
|
85
|
+
status: 'loading';
|
|
86
|
+
} | {
|
|
87
|
+
status: 'prompt';
|
|
88
|
+
progress: PlaybackProgress;
|
|
89
|
+
};
|
|
74
90
|
export interface PlaybackProgressSlice {
|
|
75
|
-
|
|
91
|
+
resumeState: ResumeState;
|
|
76
92
|
}
|
|
77
93
|
/**
|
|
78
94
|
* Full MediaState — flat at runtime, logically organized here.
|
|
@@ -97,7 +113,7 @@ export declare const selectMedia: (s: MediaState) => {
|
|
|
97
113
|
bufferedPercent: number;
|
|
98
114
|
playbackRate: number;
|
|
99
115
|
isLive: boolean;
|
|
100
|
-
|
|
116
|
+
resumeState: ResumeState;
|
|
101
117
|
};
|
|
102
118
|
export declare const selectAudio: (s: MediaState) => {
|
|
103
119
|
volume: number;
|
|
@@ -109,6 +125,14 @@ export declare const selectPreferences: (s: MediaState) => {
|
|
|
109
125
|
aspectRatio: AspectRatioState;
|
|
110
126
|
activeSubtitle: SubtitleTrack | null;
|
|
111
127
|
subtitleTracks: SubtitleTrack[];
|
|
128
|
+
subtitleCues: SubtitleCue[];
|
|
129
|
+
subtitleStatus: "error" | "idle" | "loading" | "ready";
|
|
130
|
+
subtitleError: string | null;
|
|
131
|
+
subtitleProviders: SubtitleProviderInfo[];
|
|
132
|
+
subtitleSearchResults: SubtitleProviderResult[];
|
|
133
|
+
subtitleSearchStatus: "error" | "idle" | "loading" | "ready";
|
|
134
|
+
subtitleSearchError: string | null;
|
|
135
|
+
captionSettings: CaptionSettings;
|
|
112
136
|
activeQuality: string;
|
|
113
137
|
qualities: string[];
|
|
114
138
|
};
|
package/dist/storage.d.ts
CHANGED
|
@@ -13,12 +13,13 @@ export declare class Storage {
|
|
|
13
13
|
}
|
|
14
14
|
/** Pre-defined persistence keys */
|
|
15
15
|
export declare const STORAGE_KEYS: {
|
|
16
|
-
readonly VOLUME:
|
|
17
|
-
readonly MUTED:
|
|
18
|
-
readonly PLAYBACK_RATE:
|
|
19
|
-
readonly SUBTITLE_LANG:
|
|
20
|
-
readonly
|
|
21
|
-
readonly
|
|
22
|
-
readonly
|
|
23
|
-
readonly
|
|
16
|
+
readonly VOLUME: 'volume';
|
|
17
|
+
readonly MUTED: 'muted';
|
|
18
|
+
readonly PLAYBACK_RATE: 'playbackRate';
|
|
19
|
+
readonly SUBTITLE_LANG: 'subtitleLang';
|
|
20
|
+
readonly CAPTION_SETTINGS: 'captionSettings';
|
|
21
|
+
readonly QUALITY: 'quality';
|
|
22
|
+
readonly LOOP: 'loop';
|
|
23
|
+
readonly FLIP: 'flip';
|
|
24
|
+
readonly ASPECT_RATIO: 'aspectRatio';
|
|
24
25
|
};
|
|
@@ -1,23 +1,105 @@
|
|
|
1
|
+
export type SubtitleFormat = 'vtt' | 'srt';
|
|
1
2
|
export interface SubtitleCue {
|
|
2
3
|
index: number;
|
|
3
4
|
start: number;
|
|
4
5
|
end: number;
|
|
5
6
|
text: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
settings?: string;
|
|
6
9
|
}
|
|
7
10
|
export interface SubtitleTrack {
|
|
8
|
-
|
|
11
|
+
id?: string;
|
|
12
|
+
src?: string;
|
|
13
|
+
content?: string;
|
|
9
14
|
lang: string;
|
|
10
15
|
label: string;
|
|
16
|
+
format?: SubtitleFormat;
|
|
11
17
|
default?: boolean;
|
|
18
|
+
local?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface SubtitleSearchQuery {
|
|
21
|
+
query?: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
year?: number;
|
|
24
|
+
season?: number;
|
|
25
|
+
episode?: number;
|
|
26
|
+
imdbId?: string;
|
|
27
|
+
languages?: string[];
|
|
28
|
+
providerId?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface SubtitleSearchItem {
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
language: string;
|
|
34
|
+
format?: SubtitleFormat;
|
|
35
|
+
release?: string;
|
|
36
|
+
downloads?: number;
|
|
37
|
+
hearingImpaired?: boolean;
|
|
38
|
+
machineTranslated?: boolean;
|
|
39
|
+
providerData?: unknown;
|
|
40
|
+
}
|
|
41
|
+
export interface SubtitleProviderResult extends SubtitleSearchItem {
|
|
42
|
+
providerId: string;
|
|
43
|
+
providerLabel: string;
|
|
44
|
+
}
|
|
45
|
+
export interface SubtitleSearchResult {
|
|
46
|
+
items: SubtitleSearchItem[];
|
|
47
|
+
}
|
|
48
|
+
export type SubtitleSource = {
|
|
49
|
+
content: string;
|
|
50
|
+
src?: never;
|
|
51
|
+
format?: SubtitleFormat;
|
|
52
|
+
} | {
|
|
53
|
+
src: string;
|
|
54
|
+
content?: never;
|
|
55
|
+
format?: SubtitleFormat;
|
|
56
|
+
};
|
|
57
|
+
export interface SubtitleProvider {
|
|
58
|
+
id: string;
|
|
59
|
+
label: string;
|
|
60
|
+
search(query: SubtitleSearchQuery, signal: AbortSignal): Promise<SubtitleSearchResult | SubtitleSearchItem[]>;
|
|
61
|
+
fetch(item: SubtitleSearchItem, signal: AbortSignal): Promise<SubtitleSource>;
|
|
62
|
+
}
|
|
63
|
+
export type SubtitleProviderInfo = Pick<SubtitleProvider, 'id' | 'label'>;
|
|
64
|
+
export interface CaptionSettings {
|
|
65
|
+
fontSize: 'small' | 'medium' | 'large';
|
|
66
|
+
fontScale: number;
|
|
67
|
+
fontFamily: 'sans' | 'serif' | 'monospace';
|
|
68
|
+
textColor: string;
|
|
69
|
+
textOpacity: number;
|
|
70
|
+
backgroundColor: string;
|
|
71
|
+
backgroundOpacity: number;
|
|
72
|
+
edgeStyle: 'none' | 'shadow' | 'outline';
|
|
73
|
+
edgeColor: string;
|
|
74
|
+
position: number;
|
|
75
|
+
lineHeight: number;
|
|
76
|
+
delay: number;
|
|
77
|
+
}
|
|
78
|
+
export declare const DEFAULT_CAPTION_SETTINGS: CaptionSettings;
|
|
79
|
+
export interface SubtitleParseError {
|
|
80
|
+
code: 'unsupported-format' | 'malformed';
|
|
81
|
+
message: string;
|
|
12
82
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
83
|
+
export type SubtitleParseResult = {
|
|
84
|
+
ok: true;
|
|
85
|
+
format: SubtitleFormat;
|
|
86
|
+
cues: SubtitleCue[];
|
|
87
|
+
} | {
|
|
88
|
+
ok: false;
|
|
89
|
+
format?: undefined;
|
|
90
|
+
error: SubtitleParseError;
|
|
91
|
+
};
|
|
92
|
+
/** Parse HH:MM:SS.mmm, MM:SS.mmm, and comma-separated variants. */
|
|
93
|
+
export declare function parseTimestamp(timestamp: string): number;
|
|
16
94
|
export declare function parseSRT(content: string): SubtitleCue[];
|
|
17
|
-
/** Parse VTT format text into cues */
|
|
18
95
|
export declare function parseVTT(content: string): SubtitleCue[];
|
|
19
|
-
|
|
20
|
-
|
|
96
|
+
export declare function parseSubtitles(content: string, hint?: {
|
|
97
|
+
format?: SubtitleFormat;
|
|
98
|
+
fileName?: string;
|
|
99
|
+
mimeType?: string;
|
|
100
|
+
}): SubtitleParseResult;
|
|
101
|
+
/** Fetch and parse subtitles from URL. */
|
|
102
|
+
export declare function fetchSubtitles(track: SubtitleTrack, signal?: AbortSignal): Promise<SubtitleCue[]>;
|
|
21
103
|
/** Get active cue at a given time */
|
|
22
104
|
export declare function getActiveCue(cues: SubtitleCue[], time: number): SubtitleCue | null;
|
|
23
105
|
export interface ThumbnailCue {
|
package/dist/types.d.ts
CHANGED
|
@@ -8,11 +8,10 @@ import type { PlaybackProgressOptions } from './playback-progress';
|
|
|
8
8
|
import type { PlayerPlugin } from './plugin-api';
|
|
9
9
|
import type { AspectRatioState, FlipState } from './plugin-api';
|
|
10
10
|
import type { PlayerSource } from './source-resolver';
|
|
11
|
-
import type { PlaybackStatus } from './state/slices';
|
|
12
|
-
import type { MediaState } from './state/slices';
|
|
11
|
+
import type { MediaState, PlaybackStatus, ResumeState } from './state/slices';
|
|
13
12
|
import type { Storage } from './storage';
|
|
14
|
-
import type { SubtitleTrack } from './subtitle-parser';
|
|
15
|
-
export type { MediaState };
|
|
13
|
+
import type { CaptionSettings, SubtitleProvider, SubtitleProviderResult, SubtitleSearchQuery, SubtitleTrack } from './subtitle-parser';
|
|
14
|
+
export type { MediaState, ResumeState };
|
|
16
15
|
export interface PlayerOptions {
|
|
17
16
|
src: string;
|
|
18
17
|
/** MIME/content type hint used by source provider selection. */
|
|
@@ -21,6 +20,7 @@ export interface PlayerOptions {
|
|
|
21
20
|
title?: string;
|
|
22
21
|
poster?: string;
|
|
23
22
|
subtitles?: SubtitleTrack[];
|
|
23
|
+
subtitleProviders?: SubtitleProvider[];
|
|
24
24
|
qualities?: string[];
|
|
25
25
|
autoPlay?: boolean;
|
|
26
26
|
thumbnails?: string;
|
|
@@ -88,6 +88,13 @@ export interface MediaRemote {
|
|
|
88
88
|
toggleFullscreen: () => void;
|
|
89
89
|
togglePiP: () => void;
|
|
90
90
|
setActiveSubtitle: (track: SubtitleTrack | null) => void;
|
|
91
|
+
addSubtitleTrack: (track: SubtitleTrack) => void;
|
|
92
|
+
removeSubtitleTrack: (id: string) => void;
|
|
93
|
+
searchSubtitles: (query?: SubtitleSearchQuery) => void;
|
|
94
|
+
selectSubtitleResult: (result: SubtitleProviderResult) => void;
|
|
95
|
+
clearSubtitleSearch: () => void;
|
|
96
|
+
setCaptionSettings: (patch: Partial<CaptionSettings>) => void;
|
|
97
|
+
resetCaptionSettings: () => void;
|
|
91
98
|
setActiveQuality: (q: string) => void;
|
|
92
99
|
takeScreenshot: () => void;
|
|
93
100
|
setFlip: (flip: FlipState) => void;
|
|
@@ -113,6 +120,38 @@ export interface PlayerLabels {
|
|
|
113
120
|
quality: string;
|
|
114
121
|
subtitles: string;
|
|
115
122
|
off: string;
|
|
123
|
+
loadSubtitleFile: string;
|
|
124
|
+
findSubtitlesOnline: string;
|
|
125
|
+
subtitleSearch: string;
|
|
126
|
+
subtitleSearchPlaceholder: string;
|
|
127
|
+
subtitleSource: string;
|
|
128
|
+
subtitleAllSources: string;
|
|
129
|
+
subtitleLanguage: string;
|
|
130
|
+
subtitleAllLanguages: string;
|
|
131
|
+
subtitleNoResults: string;
|
|
132
|
+
subtitleSearching: string;
|
|
133
|
+
captionAppearance: string;
|
|
134
|
+
captionSize: string;
|
|
135
|
+
captionTextColor: string;
|
|
136
|
+
captionBackgroundColor: string;
|
|
137
|
+
captionBackgroundOpacity: string;
|
|
138
|
+
captionSmall: string;
|
|
139
|
+
captionMedium: string;
|
|
140
|
+
captionLarge: string;
|
|
141
|
+
captionFontFamily: string;
|
|
142
|
+
captionFontScale: string;
|
|
143
|
+
captionTextOpacity: string;
|
|
144
|
+
captionEdgeStyle: string;
|
|
145
|
+
captionEdgeNone: string;
|
|
146
|
+
captionEdgeShadow: string;
|
|
147
|
+
captionEdgeOutline: string;
|
|
148
|
+
captionEdgeColor: string;
|
|
149
|
+
captionPosition: string;
|
|
150
|
+
captionLineHeight: string;
|
|
151
|
+
captionDelay: string;
|
|
152
|
+
captionPreview: string;
|
|
153
|
+
captionReset: string;
|
|
154
|
+
subtitleLoadError: string;
|
|
116
155
|
endedTitle: string;
|
|
117
156
|
screenshot: string;
|
|
118
157
|
flip: string;
|
|
@@ -152,7 +191,7 @@ export interface PlayerInstance {
|
|
|
152
191
|
hotkeys: HotkeyRegistry;
|
|
153
192
|
/** The active media engine. Null before mount and after unmount. */
|
|
154
193
|
engine: MediaEngine | null;
|
|
155
|
-
updateOptions(opts: Partial<Pick<PlayerOptions, 'src' | 'type' | 'title' | 'poster' | 'autoPlay' | 'subtitles' | 'qualities' | 'thumbnails' | 'transformThumbnailVTT' | 'playbackProgress'>>): void;
|
|
194
|
+
updateOptions(opts: Partial<Pick<PlayerOptions, 'src' | 'type' | 'title' | 'poster' | 'autoPlay' | 'subtitles' | 'subtitleProviders' | 'qualities' | 'thumbnails' | 'transformThumbnailVTT' | 'playbackProgress'>>): void;
|
|
156
195
|
setThumbnails(url?: string): void;
|
|
157
196
|
initPlugins(plugins: PlayerPlugin[]): () => void;
|
|
158
197
|
mount(videoEl: HTMLVideoElement, containerEl: HTMLDivElement): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vplayer/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"test:coverage": "vitest run --coverage"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@tanstack/store": "^0.
|
|
37
|
-
"dashjs": "^5.
|
|
38
|
-
"hls.js": "^1.
|
|
36
|
+
"@tanstack/store": "^0.11.1",
|
|
37
|
+
"dashjs": "^5.2.1",
|
|
38
|
+
"hls.js": "^1.7.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"typescript": "^
|
|
42
|
-
"vite": "^8.
|
|
41
|
+
"typescript": "^7.0.2",
|
|
42
|
+
"vite": "^8.2.2"
|
|
43
43
|
}
|
|
44
44
|
}
|