@geekapps/silo-elements-nextjs 0.3.16 → 0.3.18
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/VideoPlayer.js +165 -98
- package/dist/VideoPlayer.js.map +1 -1
- package/dist/index.js +165 -98
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/styles.css +1 -1
package/dist/index.js
CHANGED
|
@@ -1536,8 +1536,47 @@ function MediaUploader({
|
|
|
1536
1536
|
var AUTO_QUALITY = {
|
|
1537
1537
|
id: "auto",
|
|
1538
1538
|
label: "Auto",
|
|
1539
|
-
type: "auto"
|
|
1539
|
+
type: "auto",
|
|
1540
|
+
supported: true
|
|
1540
1541
|
};
|
|
1542
|
+
function deviceSupportsHdr() {
|
|
1543
|
+
if (typeof window === "undefined") return false;
|
|
1544
|
+
try {
|
|
1545
|
+
return window.matchMedia("(dynamic-range: high)").matches;
|
|
1546
|
+
} catch {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
function deviceSupportsOpus() {
|
|
1551
|
+
if (typeof window === "undefined") return false;
|
|
1552
|
+
try {
|
|
1553
|
+
if (typeof MediaSource !== "undefined" && MediaSource.isTypeSupported) {
|
|
1554
|
+
if (MediaSource.isTypeSupported('audio/mp4; codecs="opus"')) return true;
|
|
1555
|
+
}
|
|
1556
|
+
const a = document.createElement("audio");
|
|
1557
|
+
return a.canPlayType('audio/ogg; codecs="opus"') !== "" || a.canPlayType('video/mp4; codecs="opus"') !== "";
|
|
1558
|
+
} catch {
|
|
1559
|
+
return false;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
function deviceSupportsCodec(codecStr) {
|
|
1563
|
+
if (typeof window === "undefined") return true;
|
|
1564
|
+
try {
|
|
1565
|
+
if (typeof MediaSource !== "undefined" && MediaSource.isTypeSupported) {
|
|
1566
|
+
return MediaSource.isTypeSupported(`video/mp4; codecs="${codecStr}"`);
|
|
1567
|
+
}
|
|
1568
|
+
return true;
|
|
1569
|
+
} catch {
|
|
1570
|
+
return true;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
function isHdrLevel(level) {
|
|
1574
|
+
const range = level?.videoRange ?? level?.video_range ?? "";
|
|
1575
|
+
return range === "PQ" || range === "HLG" || range === "HDR10" || typeof level?.name === "string" && /hdr/i.test(level.name);
|
|
1576
|
+
}
|
|
1577
|
+
function isHdrAudioCodec(codecStr) {
|
|
1578
|
+
return /opus/i.test(codecStr);
|
|
1579
|
+
}
|
|
1541
1580
|
var PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];
|
|
1542
1581
|
function Source(_props) {
|
|
1543
1582
|
return null;
|
|
@@ -2292,12 +2331,14 @@ function Video({
|
|
|
2292
2331
|
if (Hls.isSupported()) {
|
|
2293
2332
|
const hls = new Hls({
|
|
2294
2333
|
enableWorker: true,
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2334
|
+
// Buffer ~20s ahead (≈1/6 of a 2min video). maxMaxBufferLength caps the
|
|
2335
|
+
// absolute ceiling so HLS.js doesn't buffer the entire file on fast connections.
|
|
2336
|
+
maxBufferLength: 20,
|
|
2337
|
+
maxMaxBufferLength: 30,
|
|
2338
|
+
maxBufferSize: 40 * 1e3 * 1e3,
|
|
2339
|
+
// Keep only 10s of back-buffer for seeking — avoids holding GB of 4K data
|
|
2340
|
+
backBufferLength: 10,
|
|
2299
2341
|
maxBufferHole: 0.5,
|
|
2300
|
-
// Be patient with large 4K/HDR fragments before declaring a stall
|
|
2301
2342
|
highBufferWatchdogPeriod: 5,
|
|
2302
2343
|
nudgeOffset: 0.2,
|
|
2303
2344
|
nudgeMaxRetry: 3,
|
|
@@ -2315,23 +2356,28 @@ function Video({
|
|
|
2315
2356
|
hls.on(Hls.Events.MANIFEST_PARSED, (_, data) => {
|
|
2316
2357
|
const levels = data.levels ?? hls.levels ?? [];
|
|
2317
2358
|
console.debug("[Silo/hls] MANIFEST_PARSED levels=", levels.length, "audioTracks=", hls.audioTracks?.length ?? 0);
|
|
2359
|
+
const hdrSupported = deviceSupportsHdr();
|
|
2360
|
+
const opusSupported = deviceSupportsOpus();
|
|
2318
2361
|
setQualities([
|
|
2319
2362
|
AUTO_QUALITY,
|
|
2320
|
-
...levels.map((level, index) =>
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
index
|
|
2325
|
-
|
|
2363
|
+
...levels.map((level, index) => {
|
|
2364
|
+
const hdr = isHdrLevel(level);
|
|
2365
|
+
const codecStr = level.videoCodec ?? level.attrs?.CODECS ?? "";
|
|
2366
|
+
const supported = hdr ? hdrSupported : deviceSupportsCodec(codecStr);
|
|
2367
|
+
const baseName = level.name ?? (level.height ? `${level.height}p` : `${index + 1}`);
|
|
2368
|
+
const label = hdr ? `${baseName} HDR` : baseName;
|
|
2369
|
+
return { id: `hls-${index}`, label, type: "hls", index, supported, hdr };
|
|
2370
|
+
})
|
|
2326
2371
|
]);
|
|
2327
2372
|
const tracks = hls.audioTracks ?? [];
|
|
2328
2373
|
console.debug("[Silo/hls] audio tracks:", tracks.map((t) => ({ name: t.name, lang: t.lang, url: t.url })));
|
|
2329
2374
|
if (tracks.length > 1) {
|
|
2330
2375
|
setAudioTracks(
|
|
2331
|
-
tracks.map((t, i) =>
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2376
|
+
tracks.map((t, i) => {
|
|
2377
|
+
const codec = t.attrs?.CODECS ?? t.codecSet ?? "";
|
|
2378
|
+
const supported = isHdrAudioCodec(codec) ? opusSupported : true;
|
|
2379
|
+
return { id: i, label: t.name ?? t.lang ?? `Track ${i + 1}`, supported };
|
|
2380
|
+
})
|
|
2335
2381
|
);
|
|
2336
2382
|
if (pinnedAudio === -1) setSelectedAudio(hls.audioTrack ?? 0);
|
|
2337
2383
|
}
|
|
@@ -2342,12 +2388,14 @@ function Video({
|
|
|
2342
2388
|
hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, (_, data) => {
|
|
2343
2389
|
const tracks = data.audioTracks ?? [];
|
|
2344
2390
|
console.debug("[Silo/hls] AUDIO_TRACKS_UPDATED", tracks.length);
|
|
2391
|
+
const opusSupported = deviceSupportsOpus();
|
|
2345
2392
|
if (tracks.length > 1) {
|
|
2346
2393
|
setAudioTracks(
|
|
2347
|
-
tracks.map((t, i) =>
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2394
|
+
tracks.map((t, i) => {
|
|
2395
|
+
const codec = t.attrs?.CODECS ?? t.codecSet ?? "";
|
|
2396
|
+
const supported = isHdrAudioCodec(codec) ? opusSupported : true;
|
|
2397
|
+
return { id: i, label: t.name ?? t.lang ?? `Track ${i + 1}`, supported };
|
|
2398
|
+
})
|
|
2351
2399
|
);
|
|
2352
2400
|
}
|
|
2353
2401
|
if (pinnedAudio >= 0 && hls.audioTrack !== pinnedAudio) {
|
|
@@ -2356,6 +2404,9 @@ function Video({
|
|
|
2356
2404
|
});
|
|
2357
2405
|
hls.on(Hls.Events.LEVEL_SWITCHED, (_, data) => {
|
|
2358
2406
|
console.debug("[Silo/hls] LEVEL_SWITCHED", data.level);
|
|
2407
|
+
if (pinnedLevel >= 0 && data.level === pinnedLevel) {
|
|
2408
|
+
hls.currentLevel = pinnedLevel;
|
|
2409
|
+
}
|
|
2359
2410
|
if (pinnedAudio >= 0 && hls.audioTrack !== pinnedAudio) {
|
|
2360
2411
|
hls.audioTrack = pinnedAudio;
|
|
2361
2412
|
}
|
|
@@ -2586,7 +2637,7 @@ function Video({
|
|
|
2586
2637
|
}
|
|
2587
2638
|
if (option.type === "hls" && hlsRef.current && option.index != null) {
|
|
2588
2639
|
hlsRef.current.__pinLevel?.(option.index);
|
|
2589
|
-
hlsRef.current.
|
|
2640
|
+
hlsRef.current.nextLevel = option.index;
|
|
2590
2641
|
return;
|
|
2591
2642
|
}
|
|
2592
2643
|
if (option.type === "dash" && dashRef.current && option.index != null) {
|
|
@@ -3038,48 +3089,56 @@ function Video({
|
|
|
3038
3089
|
]
|
|
3039
3090
|
}
|
|
3040
3091
|
),
|
|
3041
|
-
/* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) =>
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
"
|
|
3092
|
+
/* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => {
|
|
3093
|
+
const unavailable = quality.supported === false;
|
|
3094
|
+
return /* @__PURE__ */ jsxs(
|
|
3095
|
+
"button",
|
|
3096
|
+
{
|
|
3097
|
+
type: "button",
|
|
3098
|
+
onClick: () => {
|
|
3099
|
+
if (unavailable) return;
|
|
3100
|
+
changeQuality(quality.id);
|
|
3101
|
+
setSettingsTab("root");
|
|
3102
|
+
},
|
|
3103
|
+
disabled: unavailable,
|
|
3104
|
+
className: `flex w-full items-center gap-3 px-4 py-2.5 text-sm transition ${unavailable ? "cursor-not-allowed opacity-40" : "hover:bg-white/8"}`,
|
|
3105
|
+
children: [
|
|
3106
|
+
/* @__PURE__ */ jsx(
|
|
3107
|
+
"svg",
|
|
3108
|
+
{
|
|
3109
|
+
className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`,
|
|
3110
|
+
viewBox: "0 0 16 16",
|
|
3111
|
+
fill: "none",
|
|
3112
|
+
children: /* @__PURE__ */ jsx(
|
|
3113
|
+
"path",
|
|
3114
|
+
{
|
|
3115
|
+
d: "M3 8l3.5 3.5L13 4.5",
|
|
3116
|
+
stroke: "currentColor",
|
|
3117
|
+
strokeWidth: "1.8",
|
|
3118
|
+
strokeLinecap: "round",
|
|
3119
|
+
strokeLinejoin: "round"
|
|
3120
|
+
}
|
|
3121
|
+
)
|
|
3122
|
+
}
|
|
3123
|
+
),
|
|
3124
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1 text-left", children: [
|
|
3125
|
+
/* @__PURE__ */ jsxs(
|
|
3126
|
+
"span",
|
|
3059
3127
|
{
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3128
|
+
className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55",
|
|
3129
|
+
children: [
|
|
3130
|
+
quality.label,
|
|
3131
|
+
quality.id === "auto" ? " (ABR)" : ""
|
|
3132
|
+
]
|
|
3065
3133
|
}
|
|
3066
|
-
)
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
quality.label,
|
|
3075
|
-
quality.id === "auto" ? " (ABR)" : ""
|
|
3076
|
-
]
|
|
3077
|
-
}
|
|
3078
|
-
)
|
|
3079
|
-
]
|
|
3080
|
-
},
|
|
3081
|
-
quality.id
|
|
3082
|
-
)) })
|
|
3134
|
+
),
|
|
3135
|
+
unavailable && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-[10px] text-white/30", children: "N\xE3o dispon\xEDvel" })
|
|
3136
|
+
] })
|
|
3137
|
+
]
|
|
3138
|
+
},
|
|
3139
|
+
quality.id
|
|
3140
|
+
);
|
|
3141
|
+
}) })
|
|
3083
3142
|
] }),
|
|
3084
3143
|
settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
|
|
3085
3144
|
/* @__PURE__ */ jsxs(
|
|
@@ -3301,45 +3360,53 @@ function Video({
|
|
|
3301
3360
|
]
|
|
3302
3361
|
}
|
|
3303
3362
|
),
|
|
3304
|
-
/* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) =>
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
"
|
|
3363
|
+
/* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => {
|
|
3364
|
+
const unavailable = track.supported === false;
|
|
3365
|
+
return /* @__PURE__ */ jsxs(
|
|
3366
|
+
"button",
|
|
3367
|
+
{
|
|
3368
|
+
type: "button",
|
|
3369
|
+
onClick: () => {
|
|
3370
|
+
if (unavailable) return;
|
|
3371
|
+
changeAudio(track.id);
|
|
3372
|
+
setSettingsTab("root");
|
|
3373
|
+
},
|
|
3374
|
+
disabled: unavailable,
|
|
3375
|
+
className: `flex w-full items-center gap-3 px-4 py-2.5 text-sm transition ${unavailable ? "cursor-not-allowed opacity-40" : "hover:bg-white/8"}`,
|
|
3376
|
+
children: [
|
|
3377
|
+
/* @__PURE__ */ jsx(
|
|
3378
|
+
"svg",
|
|
3379
|
+
{
|
|
3380
|
+
className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`,
|
|
3381
|
+
viewBox: "0 0 16 16",
|
|
3382
|
+
fill: "none",
|
|
3383
|
+
children: /* @__PURE__ */ jsx(
|
|
3384
|
+
"path",
|
|
3385
|
+
{
|
|
3386
|
+
d: "M3 8l3.5 3.5L13 4.5",
|
|
3387
|
+
stroke: "currentColor",
|
|
3388
|
+
strokeWidth: "1.8",
|
|
3389
|
+
strokeLinecap: "round",
|
|
3390
|
+
strokeLinejoin: "round"
|
|
3391
|
+
}
|
|
3392
|
+
)
|
|
3393
|
+
}
|
|
3394
|
+
),
|
|
3395
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1 text-left", children: [
|
|
3396
|
+
/* @__PURE__ */ jsx(
|
|
3397
|
+
"span",
|
|
3322
3398
|
{
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
strokeWidth: "1.8",
|
|
3326
|
-
strokeLinecap: "round",
|
|
3327
|
-
strokeLinejoin: "round"
|
|
3399
|
+
className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55",
|
|
3400
|
+
children: track.label
|
|
3328
3401
|
}
|
|
3329
|
-
)
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
}
|
|
3338
|
-
)
|
|
3339
|
-
]
|
|
3340
|
-
},
|
|
3341
|
-
track.id
|
|
3342
|
-
)) })
|
|
3402
|
+
),
|
|
3403
|
+
unavailable && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-[10px] text-white/30", children: "N\xE3o dispon\xEDvel" })
|
|
3404
|
+
] })
|
|
3405
|
+
]
|
|
3406
|
+
},
|
|
3407
|
+
track.id
|
|
3408
|
+
);
|
|
3409
|
+
}) })
|
|
3343
3410
|
] }),
|
|
3344
3411
|
settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
|
|
3345
3412
|
/* @__PURE__ */ jsxs(
|