multi_embed_player 3.0.1 → 3.1.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/.github/workflows/build-and-deploy.yml +44 -0
- package/.gitmodules +3 -0
- package/CLAUDE.md +92 -0
- package/README.md +0 -24
- package/add_types.sh +61 -0
- package/browserExtention/chrome/background.js +55 -0
- package/browserExtention/chrome/extention.json +1 -0
- package/browserExtention/chrome/liteplayer.js +26439 -0
- package/browserExtention/chrome/manifest.json +31 -0
- package/browserExtention/chrome/player-selector.js +1854 -0
- package/browserExtention/firefox/background.js +27 -0
- package/browserExtention/firefox/extention.json +1 -0
- package/browserExtention/firefox/liteplayer.js +26439 -0
- package/browserExtention/firefox/manifest.json +19 -0
- package/browserExtention/firefox/player-selector.js +1854 -0
- package/documents/.hugo_build.lock +0 -0
- package/documents/archetypes/default.md +5 -0
- package/documents/assets/jsconfig.json +11 -0
- package/documents/content/docs/install.md +103 -0
- package/documents/content/docs/quickstart.md +51 -0
- package/documents/content/docs/reference/HTML.md +31 -0
- package/documents/content/docs/reference/_index.md +10 -0
- package/documents/content/docs/reference/error_code.md +23 -0
- package/documents/content/docs/reference/iframe_api.md +737 -0
- package/documents/content/docs/reference/iframe_class.md +230 -0
- package/documents/content/docs/reference/multi_embed_player_class.md +113 -0
- package/documents/content/docs/reference/reserved_words.md +71 -0
- package/documents/content/docs/usage/GDPR_mode.md +77 -0
- package/documents/content/docs/usage/_index.md +10 -0
- package/documents/content/docs/usage/custom_playlist.md +239 -0
- package/documents/content/docs/usage/embed_api.md +163 -0
- package/documents/content/docs/usage/embed_various_service.md +81 -0
- package/documents/content/docs/usage/thumbnail_click.md +57 -0
- package/documents/go.mod +8 -0
- package/documents/go.sum +14 -0
- package/documents/hugo.toml +18 -0
- package/documents/layouts/partials/docs/sidebar.html +117 -0
- package/documents/layouts/partials/landing/features.html +47 -0
- package/documents/layouts/robots.txt +4 -0
- package/documents/static/_headers +7 -0
- package/documents/static/localStorageCheck.html +27 -0
- package/documents/static/no_extention.json +1 -0
- package/example.html +27 -0
- package/extention.json +1 -0
- package/icon/video_not_found.odg +0 -0
- package/icon/video_not_found.svgz +0 -0
- package/iframe_api/bilibili.ts +1095 -0
- package/iframe_api/niconico.ts +429 -0
- package/iframe_api/soundcloud.ts +450 -0
- package/iframe_api/youtube.ts +311 -0
- package/multi_embed_player.ts +989 -0
- package/package.json +10 -41
- package/player_api_gate/bilibili-api-gate/cgi/cpp/bilibili-api-gate-cgi.cpp +281 -0
- package/player_api_gate/bilibili-api-gate/cgi/go/src.go +46 -0
- package/player_api_gate/bilibili-api-gate/cloudflare_workers/package-lock.json +1356 -0
- package/player_api_gate/bilibili-api-gate/cloudflare_workers/package.json +12 -0
- package/player_api_gate/bilibili-api-gate/cloudflare_workers/src/index.js +50 -0
- package/player_api_gate/bilibili-api-gate/cloudflare_workers/wrangler.toml +3 -0
- package/player_api_gate/iframe-api-ts/.editorconfig +12 -0
- package/player_api_gate/iframe-api-ts/.prettierrc +6 -0
- package/player_api_gate/iframe-api-ts/package-lock.json +3054 -0
- package/player_api_gate/iframe-api-ts/package.json +18 -0
- package/player_api_gate/iframe-api-ts/src/bilibili.ts +49 -0
- package/player_api_gate/iframe-api-ts/src/index.ts +35 -0
- package/player_api_gate/iframe-api-ts/src/niconico.ts +95 -0
- package/player_api_gate/iframe-api-ts/src/soundcloud.ts +38 -0
- package/player_api_gate/iframe-api-ts/src/types.ts +115 -0
- package/player_api_gate/iframe-api-ts/src/url-proxy.ts +29 -0
- package/player_api_gate/iframe-api-ts/src/utils.ts +82 -0
- package/player_api_gate/iframe-api-ts/src/youtube.ts +41 -0
- package/player_api_gate/iframe-api-ts/test/bilibili.spec.ts +47 -0
- package/player_api_gate/iframe-api-ts/test/env.d.ts +3 -0
- package/player_api_gate/iframe-api-ts/test/index.spec.ts +59 -0
- package/player_api_gate/iframe-api-ts/test/niconico.spec.ts +55 -0
- package/player_api_gate/iframe-api-ts/test/soundcloud.spec.ts +55 -0
- package/player_api_gate/iframe-api-ts/test/tsconfig.json +8 -0
- package/player_api_gate/iframe-api-ts/test/url-proxy.spec.ts +46 -0
- package/player_api_gate/iframe-api-ts/test/youtube.spec.ts +45 -0
- package/player_api_gate/iframe-api-ts/tsconfig.json +45 -0
- package/player_api_gate/iframe-api-ts/vitest.config.mts +11 -0
- package/player_api_gate/iframe-api-ts/worker-configuration.d.ts +5768 -0
- package/player_api_gate/iframe-api-ts/wrangler.jsonc +47 -0
- package/player_api_gate/iframe_api/.editorconfig +13 -0
- package/player_api_gate/iframe_api/.prettierrc +6 -0
- package/player_api_gate/iframe_api/package-lock.json +1307 -0
- package/player_api_gate/iframe_api/package.json +12 -0
- package/player_api_gate/iframe_api/src/bilibili_api.js +60 -0
- package/player_api_gate/iframe_api/src/index.js +47 -0
- package/player_api_gate/iframe_api/src/niconico_api.js +112 -0
- package/player_api_gate/iframe_api/src/soundcloud_api.js +57 -0
- package/player_api_gate/iframe_api/src/url_proxy.js +28 -0
- package/player_api_gate/iframe_api/src/youtube_api.js +44 -0
- package/player_api_gate/iframe_api/wrangler.toml +51 -0
- package/player_api_gate/niconico-imager/cgi/go/src.go +74 -0
- package/player_api_gate/niconico-imager/cloudflare_workers/package-lock.json +2175 -0
- package/player_api_gate/niconico-imager/cloudflare_workers/package.json +12 -0
- package/player_api_gate/niconico-imager/cloudflare_workers/src/index.js +78 -0
- package/player_api_gate/niconico-imager/cloudflare_workers/wrangler.toml +3 -0
- package/test_script.html +172 -0
- package/tsconfig.json +36 -0
- package/dist/iframe_api/bilibili.d.ts +0 -91
- package/dist/iframe_api/bilibili.d.ts.map +0 -1
- package/dist/iframe_api/bilibili.js +0 -451
- package/dist/iframe_api/bilibili.js.map +0 -1
- package/dist/iframe_api/index.d.ts +0 -6
- package/dist/iframe_api/index.d.ts.map +0 -1
- package/dist/iframe_api/index.js +0 -8
- package/dist/iframe_api/index.js.map +0 -1
- package/dist/iframe_api/niconico.d.ts +0 -42
- package/dist/iframe_api/niconico.d.ts.map +0 -1
- package/dist/iframe_api/niconico.js +0 -181
- package/dist/iframe_api/niconico.js.map +0 -1
- package/dist/iframe_api/soundcloud.d.ts +0 -80
- package/dist/iframe_api/soundcloud.d.ts.map +0 -1
- package/dist/iframe_api/soundcloud.js +0 -188
- package/dist/iframe_api/soundcloud.js.map +0 -1
- package/dist/iframe_api/youtube.d.ts +0 -133
- package/dist/iframe_api/youtube.d.ts.map +0 -1
- package/dist/iframe_api/youtube.js +0 -278
- package/dist/iframe_api/youtube.js.map +0 -1
- package/dist/multi_embed_player.d.ts +0 -48
- package/dist/multi_embed_player.d.ts.map +0 -1
- package/dist/multi_embed_player.js +0 -318
- package/dist/multi_embed_player.js.map +0 -1
- package/dist/types.d.ts +0 -126
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -22
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
declare var YT: any;
|
|
2
|
+
|
|
3
|
+
//Notice! This file JSDOC is generated by cloude 3.5 sonnet and github copilot
|
|
4
|
+
// So some of the comments may include wrong
|
|
5
|
+
// Please refer to documents https://multi-embed-player.pages.dev/docs/reference/iframe_class/#mep_youtube
|
|
6
|
+
|
|
7
|
+
interface MepYoutubeLoadObject {
|
|
8
|
+
videoId: string;
|
|
9
|
+
startSeconds?: number;
|
|
10
|
+
endSeconds?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface MepYoutubePlayerVars {
|
|
14
|
+
autoplay?: number;
|
|
15
|
+
startSeconds?: number;
|
|
16
|
+
endSeconds?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface MepYoutubeContent {
|
|
20
|
+
videoId: string;
|
|
21
|
+
playerVars?: MepYoutubePlayerVars;
|
|
22
|
+
width?: number;
|
|
23
|
+
height?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Class representing a YouTube player.
|
|
28
|
+
*/
|
|
29
|
+
class mep_youtube{
|
|
30
|
+
static youtube_api_loaded: number = 0;
|
|
31
|
+
static youtube_api_promise: (() => void)[] = [];
|
|
32
|
+
|
|
33
|
+
player: HTMLElement = document.createElement("div");
|
|
34
|
+
autoplay: number = 0;
|
|
35
|
+
startSeconds: number = 0;
|
|
36
|
+
endSeconds: number = -1;
|
|
37
|
+
el: HTMLElement = document.createElement("div");
|
|
38
|
+
YT_player: any;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Load YouTube Iframe API asynchronously.
|
|
42
|
+
* @returns {Promise} Promise that resolves when the API is loaded.
|
|
43
|
+
*/
|
|
44
|
+
async #load_youtube_api(){
|
|
45
|
+
return new Promise<void>(async(resolve,reject)=>{
|
|
46
|
+
if((window as any).mep_youtube.youtube_api_loaded===0){
|
|
47
|
+
(window as any).mep_youtube.youtube_api_loaded = 1;
|
|
48
|
+
const script_doc = document.createElement("script");
|
|
49
|
+
script_doc.src = "https://www.youtube.com/iframe_api";
|
|
50
|
+
//script_doc.addEventListener("error",this.#dispatchEvent(new CustomEvent("onError",{detail:{code:1001}})));
|
|
51
|
+
script_doc.addEventListener("load",()=>{YT.ready(()=>{(window as any).mep_youtube.youtube_api_promise.forEach((func: any)=>func());(window as any).mep_youtube.youtube_api_loaded = 2;resolve()})});
|
|
52
|
+
document.body.appendChild(script_doc);
|
|
53
|
+
}
|
|
54
|
+
else if((window as any).mep_youtube.youtube_api_loaded==1){
|
|
55
|
+
(window as any).mep_youtube.youtube_api_promise.push(resolve);
|
|
56
|
+
}
|
|
57
|
+
else{
|
|
58
|
+
resolve();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a new YouTube player instance.
|
|
65
|
+
*/
|
|
66
|
+
constructor(replacing_element: string | HTMLElement, content: MepYoutubeContent, player_set_event_function?: (player: HTMLElement) => void){
|
|
67
|
+
this.#load(replacing_element,content,player_set_event_function);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Load the YouTube player.
|
|
72
|
+
*/
|
|
73
|
+
async #load(replacing_element: string | HTMLElement, content: MepYoutubeContent, player_set_event_function?: (player: HTMLElement) => void): Promise<void>{
|
|
74
|
+
this.player = document.createElement("div");//dummy
|
|
75
|
+
if(typeof player_set_event_function === "function"){
|
|
76
|
+
player_set_event_function(this.player);
|
|
77
|
+
}
|
|
78
|
+
await this.#load_youtube_api();
|
|
79
|
+
let iframe_replace_node: HTMLElement | null = null;
|
|
80
|
+
if(typeof replacing_element==="string"){
|
|
81
|
+
iframe_replace_node = document.getElementById(replacing_element);
|
|
82
|
+
} else {
|
|
83
|
+
iframe_replace_node = replacing_element;
|
|
84
|
+
}
|
|
85
|
+
const playerVars = content.playerVars || {};
|
|
86
|
+
let playerVars_pass_over = {};
|
|
87
|
+
if(playerVars.autoplay){
|
|
88
|
+
this.autoplay = 1;
|
|
89
|
+
(playerVars_pass_over as any).autoplay = 1;
|
|
90
|
+
}
|
|
91
|
+
else{
|
|
92
|
+
(playerVars_pass_over as any).autoplay = 0;
|
|
93
|
+
}
|
|
94
|
+
if(playerVars.startSeconds){
|
|
95
|
+
this.startSeconds = playerVars.startSeconds;
|
|
96
|
+
(playerVars_pass_over as any).start = playerVars.startSeconds;
|
|
97
|
+
}
|
|
98
|
+
if(playerVars.endSeconds){
|
|
99
|
+
this.endSeconds = playerVars.endSeconds;
|
|
100
|
+
(playerVars_pass_over as any).end = playerVars.endSeconds;
|
|
101
|
+
}
|
|
102
|
+
if (iframe_replace_node) {
|
|
103
|
+
this.el = iframe_replace_node;
|
|
104
|
+
this.YT_player = new YT.Player(iframe_replace_node,{
|
|
105
|
+
height: "315",
|
|
106
|
+
width: "560",
|
|
107
|
+
videoId: content.videoId,
|
|
108
|
+
playerVars: playerVars_pass_over,
|
|
109
|
+
host: "https://www.youtube-nocookie.com",
|
|
110
|
+
events:{
|
|
111
|
+
"onReady":()=>{this.#dispatchEvent(new Event("onReady"))},
|
|
112
|
+
"onError":(e: { data: number })=>{this.#error_event_handler(e)},
|
|
113
|
+
"onStateChange":()=>{this.#dispatchEvent(new CustomEvent("onStateChange",{detail:this.getPlayerState()}));if(this.getPlayerState()==4){this.#dispatchEvent(new Event("onEndVideo"))}}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
if(!this.autoplay){
|
|
117
|
+
this.player.addEventListener("onReady",()=>{this.pauseVideo()},{once: true});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Handle error events from the player.
|
|
124
|
+
*/
|
|
125
|
+
#error_event_handler(event: { data: number }): void{
|
|
126
|
+
//change status code to mep error code
|
|
127
|
+
let code = 520;
|
|
128
|
+
switch(event.data){
|
|
129
|
+
case 2:
|
|
130
|
+
code = 401;
|
|
131
|
+
break;
|
|
132
|
+
case 5:
|
|
133
|
+
code = 500;
|
|
134
|
+
break;
|
|
135
|
+
case 100:
|
|
136
|
+
code = 404;
|
|
137
|
+
break;
|
|
138
|
+
case 101:
|
|
139
|
+
case 150:
|
|
140
|
+
code = 403;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
this.player.dispatchEvent(new CustomEvent("onError",{detail:{code:code}}));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Play the video.
|
|
148
|
+
*/
|
|
149
|
+
playVideo(){
|
|
150
|
+
this.YT_player.playVideo();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Pause the video.
|
|
155
|
+
*/
|
|
156
|
+
pauseVideo(){
|
|
157
|
+
this.YT_player.pauseVideo();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get the current time of the video.
|
|
162
|
+
*/
|
|
163
|
+
getCurrentTime(): number{
|
|
164
|
+
return this.YT_player.getCurrentTime();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get the duration of the video.
|
|
169
|
+
*/
|
|
170
|
+
getDuration(): number{
|
|
171
|
+
return this.YT_player.getDuration();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get the actual duration between the start and end times.
|
|
176
|
+
*/
|
|
177
|
+
getRealDulation(): number{
|
|
178
|
+
if(this.endSeconds==-1){
|
|
179
|
+
return this.getDuration() - this.startSeconds;
|
|
180
|
+
}
|
|
181
|
+
else{
|
|
182
|
+
return this.endSeconds - this.startSeconds;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Seek to a specific time in the video.
|
|
188
|
+
*/
|
|
189
|
+
seekTo(time: number): void{
|
|
190
|
+
//try to time as number
|
|
191
|
+
time = Number(time);
|
|
192
|
+
if(isNaN(time)){
|
|
193
|
+
console.error("time is not a number(Nan error)");
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if(time<0){
|
|
197
|
+
time = 0;
|
|
198
|
+
}
|
|
199
|
+
this.YT_player.seekTo(time);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Set the volume of the player.
|
|
204
|
+
*/
|
|
205
|
+
setVolume(volume: number): void{
|
|
206
|
+
if(typeof volume==="number"&&volume>=0&&volume<=100){
|
|
207
|
+
this.YT_player.setVolume(volume);
|
|
208
|
+
}
|
|
209
|
+
else{
|
|
210
|
+
console.error("volume is not a number or not in range 0-100");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Mute the player.
|
|
216
|
+
*/
|
|
217
|
+
mute(){
|
|
218
|
+
this.YT_player.mute();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Unmute the player.
|
|
223
|
+
*/
|
|
224
|
+
unMute(){
|
|
225
|
+
this.YT_player.unMute();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Check if the player is muted.
|
|
230
|
+
*/
|
|
231
|
+
isMuted(): boolean{
|
|
232
|
+
return this.YT_player.isMuted();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get the current volume of the player.
|
|
237
|
+
*/
|
|
238
|
+
getVolume(): number{
|
|
239
|
+
return this.YT_player.getVolume();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get the current state of the player.
|
|
244
|
+
*/
|
|
245
|
+
getPlayerState(): number{
|
|
246
|
+
let nowstatus = this.YT_player.getPlayerState();
|
|
247
|
+
if((this.getCurrentTime()>this.getDuration()-1&&this.getCurrentTime()!=0&&this.getDuration()!=0)||(this.endSeconds!=-1&&this.endSeconds-1<=this.getCurrentTime())){
|
|
248
|
+
return 4
|
|
249
|
+
}
|
|
250
|
+
else if(nowstatus==-1){
|
|
251
|
+
return 0
|
|
252
|
+
}
|
|
253
|
+
else if(nowstatus==0){
|
|
254
|
+
return 4
|
|
255
|
+
}
|
|
256
|
+
else if(nowstatus==1){
|
|
257
|
+
return 2
|
|
258
|
+
}
|
|
259
|
+
else if(nowstatus==2){
|
|
260
|
+
return 3
|
|
261
|
+
}
|
|
262
|
+
else if(nowstatus==3||nowstatus==5){
|
|
263
|
+
return 1
|
|
264
|
+
}
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get the title of the currently loaded video.
|
|
270
|
+
*/
|
|
271
|
+
getTitle(): string{
|
|
272
|
+
return this.YT_player.getVideoData().title;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Load a new video by ID.
|
|
277
|
+
*/
|
|
278
|
+
loadVideoById(content: MepYoutubeLoadObject | string, startSeconds?: number): void{
|
|
279
|
+
if(typeof content==="object"){
|
|
280
|
+
this.YT_player.loadVideoById(content);
|
|
281
|
+
}
|
|
282
|
+
else{
|
|
283
|
+
this.YT_player.loadVideoById(content,startSeconds);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Cue a new video by ID.
|
|
289
|
+
*/
|
|
290
|
+
cueVideoById(content: MepYoutubeLoadObject | string, startSeconds?: number): void{
|
|
291
|
+
if(typeof content==="object"){
|
|
292
|
+
this.YT_player.cueVideoById(content);
|
|
293
|
+
}
|
|
294
|
+
else{
|
|
295
|
+
this.YT_player.cueVideoById(content,startSeconds);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Dispatch an event on the player.
|
|
301
|
+
*/
|
|
302
|
+
#dispatchEvent(event: Event): void{
|
|
303
|
+
try{
|
|
304
|
+
this.player.dispatchEvent(event);
|
|
305
|
+
}
|
|
306
|
+
catch(e){
|
|
307
|
+
console.error(e);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
(window as any).mep_youtube = mep_youtube;
|