box-content-preview 3.89.0 → 3.90.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 +7 -7
- package/dist/lib/index.js +475 -246
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://mergify.io)
|
|
3
3
|
[](https://github.com/prettier/prettier)
|
|
4
4
|
[](https://travis-ci.org/box/box-content-preview)
|
|
5
|
-
[](https://github.com/box/box-content-preview)
|
|
6
6
|
[](https://www.npmjs.com/package/box-ui-elements)
|
|
7
7
|
|
|
8
8
|
# [Box Content Preview](https://developer.box.com/docs/box-content-preview)
|
|
@@ -22,11 +22,11 @@ We encourage all users to update their applications to utilize modern browsers f
|
|
|
22
22
|
|
|
23
23
|
## Current Version
|
|
24
24
|
|
|
25
|
-
- Version: v3.
|
|
25
|
+
- Version: v3.90.0
|
|
26
26
|
- Locale: en-US
|
|
27
27
|
|
|
28
|
-
https://cdn01.boxcdn.net/platform/preview/3.
|
|
29
|
-
https://cdn01.boxcdn.net/platform/preview/3.
|
|
28
|
+
https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.js
|
|
29
|
+
https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.css
|
|
30
30
|
|
|
31
31
|
## Supported Locales
|
|
32
32
|
|
|
@@ -52,10 +52,10 @@ You can self-host the Box Content Preview library or reference the versions avai
|
|
|
52
52
|
<title>Box Content Preview Demo</title>
|
|
53
53
|
|
|
54
54
|
<!-- Latest version of Preview SDK for your locale -->
|
|
55
|
-
<script src="https://cdn01.boxcdn.net/platform/preview/3.
|
|
55
|
+
<script src="https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.js"></script>
|
|
56
56
|
<link
|
|
57
57
|
rel="stylesheet"
|
|
58
|
-
href="https://cdn01.boxcdn.net/platform/preview/3.
|
|
58
|
+
href="https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.css"
|
|
59
59
|
/>
|
|
60
60
|
</head>
|
|
61
61
|
<body>
|
|
@@ -76,7 +76,7 @@ To self-host the Box Content Preview library, follow these steps:
|
|
|
76
76
|
|
|
77
77
|
1. Either fork the repo and check out the version you want to host or download the specific version as a zip:
|
|
78
78
|
|
|
79
|
-
- Check out a specific version with `git checkout v3.
|
|
79
|
+
- Check out a specific version with `git checkout v3.90.0`
|
|
80
80
|
- Download a specific version as a zip from https://github.com/box/box-content-preview/releases
|
|
81
81
|
|
|
82
82
|
2. Install dependencies and build the library with `yarn install && yarn build:i18n && yarn build:prod`
|
package/dist/lib/index.js
CHANGED
|
@@ -327,6 +327,7 @@ class PreviewError extends Error {
|
|
|
327
327
|
/* harmony export */ Jm: () => (/* binding */ SELECTOR_BOX_PREVIEW_LOGO_CUSTOM),
|
|
328
328
|
/* harmony export */ Kb: () => (/* binding */ CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER),
|
|
329
329
|
/* harmony export */ Kh: () => (/* binding */ SELECTOR_NAVIGATION_RIGHT),
|
|
330
|
+
/* harmony export */ Ku: () => (/* binding */ AUDIO_PLAYER_V2),
|
|
330
331
|
/* harmony export */ Lq: () => (/* binding */ PREVIEW_SCRIPT_NAME),
|
|
331
332
|
/* harmony export */ Lz: () => (/* binding */ CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE),
|
|
332
333
|
/* harmony export */ M$: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_WRAPPER_DOCUMENT),
|
|
@@ -379,6 +380,7 @@ class PreviewError extends Error {
|
|
|
379
380
|
/* harmony export */ jF: () => (/* binding */ CLASS_IS_VISIBLE),
|
|
380
381
|
/* harmony export */ jP: () => (/* binding */ CLASS_PREVIEW_LOADED),
|
|
381
382
|
/* harmony export */ jf: () => (/* binding */ CLASS_FULLSCREEN_UNSUPPORTED),
|
|
383
|
+
/* harmony export */ jr: () => (/* binding */ X_REP_HINT_WAVEFORM),
|
|
382
384
|
/* harmony export */ lM: () => (/* binding */ CLASS_BOX_PREVIEW_MOBILE),
|
|
383
385
|
/* harmony export */ lR: () => (/* binding */ SELECTOR_BOX_PREVIEW_HEADER_CONTAINER),
|
|
384
386
|
/* harmony export */ lX: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_OVERLAY),
|
|
@@ -396,6 +398,8 @@ class PreviewError extends Error {
|
|
|
396
398
|
/* harmony export */ rR: () => (/* binding */ CLASS_BOX_PREVIEW_THEME_DARK),
|
|
397
399
|
/* harmony export */ rZ: () => (/* binding */ CLASS_BOX_PREVIEW_OVERLAY),
|
|
398
400
|
/* harmony export */ rr: () => (/* binding */ CLASS_IS_BUFFERING),
|
|
401
|
+
/* harmony export */ u4: () => (/* binding */ WAVEFORM_REP_NAME),
|
|
402
|
+
/* harmony export */ uD: () => (/* binding */ STATUS_ERROR),
|
|
399
403
|
/* harmony export */ uN: () => (/* binding */ MEDIA_PLAYBACK_SKIP_DURATION),
|
|
400
404
|
/* harmony export */ vV: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_WRAPPER_PRESENTATION),
|
|
401
405
|
/* harmony export */ v_: () => (/* binding */ SELECTOR_BOX_PREVIEW_BTN_DOWNLOAD),
|
|
@@ -415,7 +419,7 @@ class PreviewError extends Error {
|
|
|
415
419
|
/* harmony export */ zb: () => (/* binding */ CLASS_DOC_FIRST_IMAGE),
|
|
416
420
|
/* harmony export */ ze: () => (/* binding */ STATUS_PENDING)
|
|
417
421
|
/* harmony export */ });
|
|
418
|
-
/* unused harmony exports CLASS_ACTIVE, CLASS_BOX_PREVIEW, CLASS_BOX_PREVIEW_CONTAINER, CLASS_BOX_PREVIEW_HEADER_CONTAINER, CLASS_BOX_PREVIEW_ICON, CLASS_BOX_PREVIEW_LOGO_CUSTOM, CLASS_BOX_PREVIEW_LOGO_DEFAULT, CLASS_PREFETCHED_IMAGE, SELECTOR_BOX_PREVIEW_HEADER, SELECTOR_BOX_PREVIEW_NOTIFICATION
|
|
422
|
+
/* unused harmony exports CLASS_ACTIVE, CLASS_BOX_PREVIEW, CLASS_BOX_PREVIEW_CONTAINER, CLASS_BOX_PREVIEW_HEADER_CONTAINER, CLASS_BOX_PREVIEW_ICON, CLASS_BOX_PREVIEW_LOGO_CUSTOM, CLASS_BOX_PREVIEW_LOGO_DEFAULT, CLASS_PREFETCHED_IMAGE, SELECTOR_BOX_PREVIEW_HEADER, SELECTOR_BOX_PREVIEW_NOTIFICATION */
|
|
419
423
|
const CLASS_ACTIVE = 'bp-is-active';
|
|
420
424
|
const CLASS_ANNOTATIONS_CREATE_DRAWING = 'bp-annotations-create--drawing';
|
|
421
425
|
const CLASS_ANNOTATIONS_CREATE_HIGHLIGHT = 'bp-annotations-create--highlight';
|
|
@@ -502,6 +506,7 @@ const APP_HOST = 'https://app.box.com';
|
|
|
502
506
|
const ORIGINAL_REP_NAME = 'ORIGINAL';
|
|
503
507
|
const PRELOAD_REP_NAME = 'jpg';
|
|
504
508
|
const PRELOAD_PAGED_REP_NAME = 'webp';
|
|
509
|
+
const WAVEFORM_REP_NAME = 'waveform';
|
|
505
510
|
const VIDEO_VIEWER_NAMES = ['Dash', 'MP4'];
|
|
506
511
|
const STATUS_ERROR = 'error';
|
|
507
512
|
const STATUS_NONE = 'none';
|
|
@@ -516,7 +521,9 @@ const X_REP_HINT_IMAGE = '[jpg?dimensions=2048x2048,png?dimensions=2048x2048]';
|
|
|
516
521
|
const X_REP_HINT_VIDEO_DASH = '[dash,mp4][filmstrip]';
|
|
517
522
|
const X_REP_HINT_VIDEO_DASH_EXTRACTED_TEXT = '[extracted_text]';
|
|
518
523
|
const X_REP_HINT_VIDEO_MP4 = '[mp4]';
|
|
524
|
+
const X_REP_HINT_WAVEFORM = '[waveform]';
|
|
519
525
|
const AI_TRANSCRIPTION_FOR_VIDEO_SUBTITLES = 'aiTranscriptionForVideoSubtitles';
|
|
526
|
+
const AUDIO_PLAYER_V2 = 'audioPlayerV2.enabled';
|
|
520
527
|
const PDFJS_CSS_UNITS = 96.0 / 72.0; // Should match CSS_UNITS in pdf_viewer.js
|
|
521
528
|
const PDFJS_MAX_AUTO_SCALE = 1.25; // Should match MAX_AUTO_SCALE in pdf_viewer.js
|
|
522
529
|
const PDFJS_WIDTH_PADDING_PX = 40; // Should match SCROLLBAR_PADDING in pdf_viewer.js
|
|
@@ -1010,7 +1017,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
1010
1017
|
const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
|
|
1011
1018
|
const CLIENT_NAME_KEY = 'box_client_name';
|
|
1012
1019
|
const CLIENT_VERSION_KEY = 'box_client_version';
|
|
1013
|
-
const CLIENT_VERSION = "3.
|
|
1020
|
+
const CLIENT_VERSION = "3.90.0"; // eslint-disable-line no-undef
|
|
1014
1021
|
const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
|
|
1015
1022
|
const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
|
|
1016
1023
|
const PROMISE_MAP = {};
|
|
@@ -6375,14 +6382,16 @@ function MP3ControlsV2({
|
|
|
6375
6382
|
volume
|
|
6376
6383
|
}) {
|
|
6377
6384
|
const durationValue = typeof durationTime === 'number' && isFinite_default()(durationTime) ? durationTime : 0;
|
|
6385
|
+
const mediaDuration = mediaEl ? mediaEl.duration : NaN;
|
|
6386
|
+
const hasMediaMetadata = typeof mediaDuration === 'number' && Number.isFinite(mediaDuration) && mediaDuration > 0;
|
|
6387
|
+
const hasWaveformDuration = durationValue > 0;
|
|
6378
6388
|
const [zoomLevel, setZoomLevel] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
|
|
6379
6389
|
const [maxZoom, setMaxZoom] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
|
|
6380
6390
|
const [isZoomRevealed, setIsZoomRevealed] = (0,external_react_.useState)(false);
|
|
6381
6391
|
const zoomRevealTimerRef = (0,external_react_.useRef)(0);
|
|
6382
6392
|
const hasRealPeaks = !!(peaks && peaks.length);
|
|
6383
6393
|
const waveformPeaks = hasRealPeaks ? peaks : PLACEHOLDER_PEAKS;
|
|
6384
|
-
const
|
|
6385
|
-
const waveformDurationSec = hasMetadata ? durationValue : PLACEHOLDER_DURATION_SEC;
|
|
6394
|
+
const waveformDurationSec = hasWaveformDuration ? durationValue : PLACEHOLDER_DURATION_SEC;
|
|
6386
6395
|
const [playRequested, setPlayRequested] = (0,external_react_.useState)(false);
|
|
6387
6396
|
const [viewport, setViewport] = (0,external_react_.useState)(null);
|
|
6388
6397
|
const handleViewportChange = (0,external_react_.useCallback)(next => {
|
|
@@ -6427,11 +6436,11 @@ function MP3ControlsV2({
|
|
|
6427
6436
|
}
|
|
6428
6437
|
onTimeChange(marker.time);
|
|
6429
6438
|
}, [onCommentMarkerClick, onPlayPause, onTimeChange]);
|
|
6430
|
-
const isWaveformInteractive = playRequested &&
|
|
6431
|
-
const isWaitingToPlay = playRequested && !
|
|
6439
|
+
const isWaveformInteractive = playRequested && hasMediaMetadata;
|
|
6440
|
+
const isWaitingToPlay = playRequested && !hasMediaMetadata;
|
|
6432
6441
|
const showPlayOverlay = !playRequested && !isPlaying;
|
|
6433
6442
|
const hasZoomHandlers = hasRealPeaks && !showPlayOverlay;
|
|
6434
|
-
const hasZoomControl = hasZoomHandlers &&
|
|
6443
|
+
const hasZoomControl = hasZoomHandlers && hasMediaMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
6435
6444
|
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6436
6445
|
className: "bp-MP3ControlsV2",
|
|
6437
6446
|
"data-testid": "media-controls-wrapper-v2"
|
|
@@ -6452,7 +6461,7 @@ function MP3ControlsV2({
|
|
|
6452
6461
|
zoomLevel: hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW
|
|
6453
6462
|
}), /*#__PURE__*/external_react_["default"].createElement(WaveformCommentMarkers, {
|
|
6454
6463
|
commentMarkers: waveformMarkers,
|
|
6455
|
-
durationSec:
|
|
6464
|
+
durationSec: hasWaveformDuration ? durationValue : 0,
|
|
6456
6465
|
onCommentMarkerClick: handleCommentMarkerClick,
|
|
6457
6466
|
selectedId: selectedMarkerId,
|
|
6458
6467
|
viewport: viewport
|
|
@@ -6479,7 +6488,7 @@ function MP3ControlsV2({
|
|
|
6479
6488
|
}), isWaitingToPlay && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6480
6489
|
className: "bp-media-buffering-spinner",
|
|
6481
6490
|
"data-testid": "bp-MP3ControlsV2-loading"
|
|
6482
|
-
})),
|
|
6491
|
+
})), hasMediaMetadata && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6483
6492
|
className: "bp-MP3ControlsV2-bar",
|
|
6484
6493
|
"data-testid": "bp-MP3ControlsV2-bar"
|
|
6485
6494
|
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
@@ -6650,25 +6659,19 @@ const WAVEFORM_HEIGHT = 140;
|
|
|
6650
6659
|
|
|
6651
6660
|
/***/ },
|
|
6652
6661
|
|
|
6653
|
-
/***/
|
|
6662
|
+
/***/ 4971
|
|
6654
6663
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
6655
6664
|
|
|
6656
6665
|
|
|
6657
6666
|
// EXPORTS
|
|
6658
6667
|
__webpack_require__.d(__webpack_exports__, {
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6668
|
+
oz: () => (/* binding */ WaveformLoadError),
|
|
6669
|
+
iY: () => (/* binding */ createCappedWaveformState),
|
|
6670
|
+
nR: () => (/* binding */ createWaveformLoader),
|
|
6671
|
+
Vq: () => (/* binding */ errorFromUnknown),
|
|
6672
|
+
zf: () => (/* binding */ isAbortError)
|
|
6664
6673
|
});
|
|
6665
|
-
// ESM COMPAT FLAG
|
|
6666
|
-
__webpack_require__.r(__webpack_exports__);
|
|
6667
6674
|
|
|
6668
|
-
// EXTERNAL MODULE: ./src/lib/util.js + 1 modules
|
|
6669
|
-
var util = __webpack_require__(4410);
|
|
6670
|
-
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/constants.ts
|
|
6671
|
-
var constants = __webpack_require__(4929);
|
|
6672
6675
|
;// ./src/lib/viewers/media/waveform/types.ts
|
|
6673
6676
|
/**
|
|
6674
6677
|
* Box V1 is the in-viewer form: unsigned mono peaks in [0, 1] (peak envelope, mono_max).
|
|
@@ -6704,9 +6707,9 @@ function isWaveformErrorCode(value) {
|
|
|
6704
6707
|
* Wavesurfer's two paints: left of the playhead (`progressColor`) and right of it (`waveColor`).
|
|
6705
6708
|
* A string is a solid fill; a stop list is a left-to-right step gradient.
|
|
6706
6709
|
*/
|
|
6710
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
|
|
6711
|
+
var validateWaveformPayload = __webpack_require__(1053);
|
|
6707
6712
|
;// ./src/lib/viewers/media/waveform/createWaveformLoader.ts
|
|
6708
|
-
/* unused harmony import specifier */ var isRetryableWaveformError;
|
|
6709
|
-
/* unused harmony import specifier */ var validateWaveformPayload;
|
|
6710
6713
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
6711
6714
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6712
6715
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
@@ -6753,7 +6756,7 @@ function failedLoadState(error) {
|
|
|
6753
6756
|
return {
|
|
6754
6757
|
status: 'failed',
|
|
6755
6758
|
error,
|
|
6756
|
-
retryable: isRetryableWaveformError(error.code)
|
|
6759
|
+
retryable: (0,validateWaveformPayload/* isRetryableWaveformError */.Oe)(error.code)
|
|
6757
6760
|
};
|
|
6758
6761
|
}
|
|
6759
6762
|
function readyLoadState(payload) {
|
|
@@ -6835,7 +6838,7 @@ function createWaveformLoader(fetchPayload, options = {}) {
|
|
|
6835
6838
|
if (staleAfterFetch) {
|
|
6836
6839
|
return staleAfterFetch;
|
|
6837
6840
|
}
|
|
6838
|
-
const validation = validateWaveformPayload(raw, options);
|
|
6841
|
+
const validation = (0,validateWaveformPayload/* validateWaveformPayload */.a9)(raw, options);
|
|
6839
6842
|
const staleAfterValidate = cancelledIfStale(request);
|
|
6840
6843
|
if (staleAfterValidate) {
|
|
6841
6844
|
return staleAfterValidate;
|
|
@@ -6877,185 +6880,29 @@ function createCappedWaveformState(message) {
|
|
|
6877
6880
|
}
|
|
6878
6881
|
};
|
|
6879
6882
|
}
|
|
6880
|
-
;// ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
|
|
6881
6883
|
|
|
6882
|
-
|
|
6883
|
-
const DEFAULT_CHANNEL_POLICY = 'mono_max';
|
|
6884
|
-
const DEFAULT_ENVELOPE = 'peak';
|
|
6885
|
-
function fail(code, message, retryable = false) {
|
|
6886
|
-
return {
|
|
6887
|
-
ok: false,
|
|
6888
|
-
error: {
|
|
6889
|
-
code,
|
|
6890
|
-
message
|
|
6891
|
-
},
|
|
6892
|
-
retryable
|
|
6893
|
-
};
|
|
6894
|
-
}
|
|
6895
|
-
function isPlainObject(value) {
|
|
6896
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6897
|
-
}
|
|
6898
|
-
function payloadByteLength(raw) {
|
|
6899
|
-
try {
|
|
6900
|
-
const serialized = JSON.stringify(raw);
|
|
6901
|
-
if (typeof Buffer !== 'undefined') {
|
|
6902
|
-
return Buffer.byteLength(serialized, 'utf8');
|
|
6903
|
-
}
|
|
6904
|
-
if (typeof TextEncoder !== 'undefined') {
|
|
6905
|
-
return new TextEncoder().encode(serialized).length;
|
|
6906
|
-
}
|
|
6907
|
-
return serialized.length;
|
|
6908
|
-
} catch {
|
|
6909
|
-
return Number.MAX_SAFE_INTEGER;
|
|
6910
|
-
}
|
|
6911
|
-
}
|
|
6912
|
-
function readOptionalPolicy(raw, key, allowed) {
|
|
6913
|
-
if (!(key in raw) || raw[key] === undefined) {
|
|
6914
|
-
return undefined;
|
|
6915
|
-
}
|
|
6916
|
-
return raw[key] === allowed ? allowed : null;
|
|
6917
|
-
}
|
|
6918
|
-
function asWaveformPayloadV1(raw) {
|
|
6919
|
-
const {
|
|
6920
|
-
version,
|
|
6921
|
-
durationSec,
|
|
6922
|
-
peaks
|
|
6923
|
-
} = raw;
|
|
6924
|
-
if (version !== constants/* WAVEFORM_PAYLOAD_VERSION */.sh || typeof durationSec !== 'number' || !Array.isArray(peaks)) {
|
|
6925
|
-
return null;
|
|
6926
|
-
}
|
|
6927
|
-
const peakScale = readOptionalPolicy(raw, 'peakScale', DEFAULT_PEAK_SCALE);
|
|
6928
|
-
const channelPolicy = readOptionalPolicy(raw, 'channelPolicy', DEFAULT_CHANNEL_POLICY);
|
|
6929
|
-
const envelope = readOptionalPolicy(raw, 'envelope', DEFAULT_ENVELOPE);
|
|
6930
|
-
if (peakScale === null || channelPolicy === null || envelope === null) {
|
|
6931
|
-
return null;
|
|
6932
|
-
}
|
|
6933
|
-
if ('channels' in raw && raw.channels !== undefined && raw.channels !== 1) {
|
|
6934
|
-
return null;
|
|
6935
|
-
}
|
|
6936
|
-
return {
|
|
6937
|
-
version: constants/* WAVEFORM_PAYLOAD_VERSION */.sh,
|
|
6938
|
-
durationSec,
|
|
6939
|
-
peaks: peaks,
|
|
6940
|
-
peakScale: peakScale ?? DEFAULT_PEAK_SCALE,
|
|
6941
|
-
channelPolicy: channelPolicy ?? DEFAULT_CHANNEL_POLICY,
|
|
6942
|
-
envelope: envelope ?? DEFAULT_ENVELOPE,
|
|
6943
|
-
channels: 1
|
|
6944
|
-
};
|
|
6945
|
-
}
|
|
6946
|
-
function readPayloadObject(raw, maxPayloadBytes, isPayloadByteCheckSkipped = false) {
|
|
6947
|
-
if (raw === null || raw === undefined) {
|
|
6948
|
-
return fail('INVALID_PAYLOAD', 'Payload is null or undefined');
|
|
6949
|
-
}
|
|
6950
|
-
if (!isPayloadByteCheckSkipped) {
|
|
6951
|
-
const byteLength = payloadByteLength(raw);
|
|
6952
|
-
if (byteLength > maxPayloadBytes) {
|
|
6953
|
-
return fail('PAYLOAD_TOO_LARGE', `Payload size ${byteLength} exceeds limit ${maxPayloadBytes}`);
|
|
6954
|
-
}
|
|
6955
|
-
}
|
|
6956
|
-
if (!isPlainObject(raw)) {
|
|
6957
|
-
return fail('INVALID_PAYLOAD', 'Payload must be an object');
|
|
6958
|
-
}
|
|
6959
|
-
return {
|
|
6960
|
-
ok: true,
|
|
6961
|
-
value: raw
|
|
6962
|
-
};
|
|
6963
|
-
}
|
|
6964
|
-
function checkVersion(raw) {
|
|
6965
|
-
if (raw.version === constants/* WAVEFORM_PAYLOAD_VERSION */.sh) {
|
|
6966
|
-
return null;
|
|
6967
|
-
}
|
|
6968
|
-
const {
|
|
6969
|
-
version
|
|
6970
|
-
} = raw;
|
|
6971
|
-
if (typeof version === 'number' && version > constants/* WAVEFORM_PAYLOAD_VERSION */.sh) {
|
|
6972
|
-
return fail('UNSUPPORTED_VERSION', `Unsupported waveform version ${version}; max supported is ${constants/* WAVEFORM_PAYLOAD_VERSION */.sh}`);
|
|
6973
|
-
}
|
|
6974
|
-
return fail('INVALID_PAYLOAD', 'Missing or invalid version field');
|
|
6975
|
-
}
|
|
6976
|
-
function checkDuration(payload, expectedDurationSec) {
|
|
6977
|
-
if (!Number.isFinite(payload.durationSec) || payload.durationSec <= 0) {
|
|
6978
|
-
return fail('INVALID_DURATION', 'durationSec must be a positive finite number');
|
|
6979
|
-
}
|
|
6980
|
-
if (expectedDurationSec !== undefined && Number.isFinite(expectedDurationSec) && Math.abs(payload.durationSec - expectedDurationSec) > constants/* DURATION_MISMATCH_TOLERANCE_SEC */.GQ) {
|
|
6981
|
-
return fail('DURATION_MISMATCH', `Payload duration ${payload.durationSec}s differs from media duration ${expectedDurationSec}s`, true);
|
|
6982
|
-
}
|
|
6983
|
-
return null;
|
|
6984
|
-
}
|
|
6985
|
-
function normalizePeaks(peaks, maxPeakCount) {
|
|
6986
|
-
if (peaks.length === 0) {
|
|
6987
|
-
return fail('EMPTY_PEAKS', 'peaks array must not be empty');
|
|
6988
|
-
}
|
|
6989
|
-
if (peaks.length > maxPeakCount) {
|
|
6990
|
-
return fail('PEAK_COUNT_EXCEEDED', `peaks length ${peaks.length} exceeds max ${maxPeakCount}`);
|
|
6991
|
-
}
|
|
6992
|
-
const normalized = new Float32Array(peaks.length);
|
|
6993
|
-
for (let i = 0; i < peaks.length; i += 1) {
|
|
6994
|
-
const value = peaks[i];
|
|
6995
|
-
if (!Number.isFinite(value)) {
|
|
6996
|
-
return fail('NON_FINITE_PEAK', `Peak at index ${i} is not finite`);
|
|
6997
|
-
}
|
|
6998
|
-
if (value < constants/* PEAK_UNIT_MIN */.mJ || value > constants/* PEAK_UNIT_MAX */.i8) {
|
|
6999
|
-
return fail('PEAK_OUT_OF_RANGE', `Peak at index ${i} is outside [${constants/* PEAK_UNIT_MIN */.mJ}, ${constants/* PEAK_UNIT_MAX */.i8}]`);
|
|
7000
|
-
}
|
|
7001
|
-
normalized[i] = value;
|
|
7002
|
-
}
|
|
7003
|
-
return {
|
|
7004
|
-
ok: true,
|
|
7005
|
-
peaks: normalized
|
|
7006
|
-
};
|
|
7007
|
-
}
|
|
6884
|
+
/***/ },
|
|
7008
6885
|
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
* Wire JSON requires version, durationSec, and peaks. sampleCount and source are ignored.
|
|
7012
|
-
*/
|
|
7013
|
-
function validateWaveformPayload_validateWaveformPayload(raw, options = {}) {
|
|
7014
|
-
const maxPeakCount = options.maxPeakCount ?? constants/* MAX_PEAK_COUNT */.FY;
|
|
7015
|
-
const maxPayloadBytes = options.maxPayloadBytes ?? constants/* MAX_PAYLOAD_BYTES */.qY;
|
|
7016
|
-
const objectResult = readPayloadObject(raw, maxPayloadBytes, options.isPayloadByteCheckSkipped === true);
|
|
7017
|
-
if (!objectResult.ok) {
|
|
7018
|
-
return objectResult;
|
|
7019
|
-
}
|
|
7020
|
-
const versionFailure = checkVersion(objectResult.value);
|
|
7021
|
-
if (versionFailure) {
|
|
7022
|
-
return versionFailure;
|
|
7023
|
-
}
|
|
7024
|
-
const payload = asWaveformPayloadV1(objectResult.value);
|
|
7025
|
-
if (!payload) {
|
|
7026
|
-
return fail('INVALID_PAYLOAD', 'Payload failed structural validation');
|
|
7027
|
-
}
|
|
7028
|
-
const durationFailure = checkDuration(payload, options.expectedDurationSec);
|
|
7029
|
-
if (durationFailure) {
|
|
7030
|
-
return durationFailure;
|
|
7031
|
-
}
|
|
7032
|
-
const peaksResult = normalizePeaks(payload.peaks, maxPeakCount);
|
|
7033
|
-
if (!peaksResult.ok) {
|
|
7034
|
-
return peaksResult;
|
|
7035
|
-
}
|
|
7036
|
-
return {
|
|
7037
|
-
ok: true,
|
|
7038
|
-
payload: {
|
|
7039
|
-
version: constants/* WAVEFORM_PAYLOAD_VERSION */.sh,
|
|
7040
|
-
durationSec: payload.durationSec,
|
|
7041
|
-
peaks: peaksResult.peaks,
|
|
7042
|
-
peakScale: payload.peakScale ?? DEFAULT_PEAK_SCALE,
|
|
7043
|
-
channelPolicy: payload.channelPolicy ?? DEFAULT_CHANNEL_POLICY,
|
|
7044
|
-
envelope: payload.envelope ?? DEFAULT_ENVELOPE
|
|
7045
|
-
}
|
|
7046
|
-
};
|
|
7047
|
-
}
|
|
6886
|
+
/***/ 8296
|
|
6887
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
7048
6888
|
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
6889
|
+
__webpack_require__.r(__webpack_exports__);
|
|
6890
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
6891
|
+
/* harmony export */ decodeToPeaks: () => (/* binding */ decodeToPeaks),
|
|
6892
|
+
/* harmony export */ extractPeaks: () => (/* binding */ extractPeaks),
|
|
6893
|
+
/* harmony export */ getDecodeDecision: () => (/* binding */ getDecodeDecision),
|
|
6894
|
+
/* harmony export */ loadPeaks: () => (/* binding */ loadPeaks),
|
|
6895
|
+
/* harmony export */ runClientDecode: () => (/* binding */ runClientDecode)
|
|
6896
|
+
/* harmony export */ });
|
|
6897
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4410);
|
|
6898
|
+
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4929);
|
|
6899
|
+
/* harmony import */ var _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4971);
|
|
6900
|
+
/* harmony import */ var _validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1053);
|
|
7054
6901
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7055
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
|
7056
|
-
function
|
|
7057
|
-
function
|
|
7058
|
-
function
|
|
6902
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6903
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
6904
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6905
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7059
6906
|
|
|
7060
6907
|
|
|
7061
6908
|
|
|
@@ -7067,9 +6914,6 @@ const EMPTY_TIMINGS = {
|
|
|
7067
6914
|
function createAbortError() {
|
|
7068
6915
|
return new DOMException('Aborted', 'AbortError');
|
|
7069
6916
|
}
|
|
7070
|
-
function isPositiveFinite(value) {
|
|
7071
|
-
return typeof value === 'number' && Number.isFinite(value) && value > 0;
|
|
7072
|
-
}
|
|
7073
6917
|
function getAudioContextConstructor() {
|
|
7074
6918
|
if (typeof window === 'undefined') {
|
|
7075
6919
|
return undefined;
|
|
@@ -7102,7 +6946,7 @@ function createSkippedDecodeResult(reason) {
|
|
|
7102
6946
|
reason
|
|
7103
6947
|
};
|
|
7104
6948
|
}
|
|
7105
|
-
return _objectSpread(_objectSpread({}, createCappedWaveformState(getDecodeSkipMessage(reason))), {}, {
|
|
6949
|
+
return _objectSpread(_objectSpread({}, (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .createCappedWaveformState */ .iY)(getDecodeSkipMessage(reason))), {}, {
|
|
7106
6950
|
isDecodeSkipped: true,
|
|
7107
6951
|
timings: EMPTY_TIMINGS,
|
|
7108
6952
|
reason
|
|
@@ -7126,11 +6970,11 @@ function decodeWithContext(context, buffer, signal) {
|
|
|
7126
6970
|
}
|
|
7127
6971
|
isSettled = true;
|
|
7128
6972
|
signal?.removeEventListener('abort', onAbort);
|
|
7129
|
-
if (isAbortError(error)) {
|
|
6973
|
+
if ((0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
|
|
7130
6974
|
reject(error instanceof DOMException ? error : createAbortError());
|
|
7131
6975
|
return;
|
|
7132
6976
|
}
|
|
7133
|
-
reject(error instanceof WaveformLoadError ? error : new WaveformLoadError('DECODE_FAILED', 'decodeAudioData failed'));
|
|
6977
|
+
reject(error instanceof _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz ? error : new _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz('DECODE_FAILED', 'decodeAudioData failed'));
|
|
7134
6978
|
};
|
|
7135
6979
|
onAbort = () => onFailure(createAbortError());
|
|
7136
6980
|
if (signal?.aborted) {
|
|
@@ -7156,13 +7000,13 @@ function decodeWithContext(context, buffer, signal) {
|
|
|
7156
7000
|
* skips decode so playback is never blocked by expanding the full audio buffer.
|
|
7157
7001
|
*/
|
|
7158
7002
|
function getDecodeDecision(media, caps = {}) {
|
|
7159
|
-
const maxCompressedBytes = caps.maxCompressedBytes ??
|
|
7160
|
-
const maxDurationSec = caps.maxDurationSec ??
|
|
7003
|
+
const maxCompressedBytes = caps.maxCompressedBytes ?? _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_MAX_COMPRESSED_BYTES */ .EB;
|
|
7004
|
+
const maxDurationSec = caps.maxDurationSec ?? _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_MAX_DURATION_SEC */ .nG;
|
|
7161
7005
|
const {
|
|
7162
7006
|
compressedBytes,
|
|
7163
7007
|
durationSec
|
|
7164
7008
|
} = media;
|
|
7165
|
-
if (!isPositiveFinite(compressedBytes) || !isPositiveFinite(durationSec)) {
|
|
7009
|
+
if (!(0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isPositiveFinite */ .Ze)(compressedBytes) || !(0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isPositiveFinite */ .Ze)(durationSec)) {
|
|
7166
7010
|
return {
|
|
7167
7011
|
isAllowed: false,
|
|
7168
7012
|
reason: 'missing_metadata'
|
|
@@ -7189,7 +7033,7 @@ function getDecodeDecision(media, caps = {}) {
|
|
|
7189
7033
|
* Collapse audio channels to one unsigned peak per time bucket (max abs, then clamp to unit).
|
|
7190
7034
|
* Accepts an AudioBuffer so callers can extract before closing the AudioContext.
|
|
7191
7035
|
*/
|
|
7192
|
-
function extractPeaks(audio, peakCount =
|
|
7036
|
+
function extractPeaks(audio, peakCount = _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_PEAK_COUNT */ .f3) {
|
|
7193
7037
|
const channels = Array.isArray(audio) ? audio : Array.from({
|
|
7194
7038
|
length: audio.numberOfChannels
|
|
7195
7039
|
}, (_, channelIndex) => audio.getChannelData(channelIndex));
|
|
@@ -7214,7 +7058,7 @@ function extractPeaks(audio, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */
|
|
|
7214
7058
|
}
|
|
7215
7059
|
}
|
|
7216
7060
|
}
|
|
7217
|
-
peaks[i] = Math.min(
|
|
7061
|
+
peaks[i] = Math.min(_constants__WEBPACK_IMPORTED_MODULE_1__/* .PEAK_UNIT_MAX */ .i8, Math.max(_constants__WEBPACK_IMPORTED_MODULE_1__/* .PEAK_UNIT_MIN */ .mJ, maxAbs));
|
|
7218
7062
|
}
|
|
7219
7063
|
return peaks;
|
|
7220
7064
|
}
|
|
@@ -7223,13 +7067,13 @@ function extractPeaks(audio, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */
|
|
|
7223
7067
|
* Decode compressed audio and extract unit peaks while the AudioBuffer is live.
|
|
7224
7068
|
* Does not attach a media element or fetch a URL. Does not copy channel data.
|
|
7225
7069
|
*/
|
|
7226
|
-
async function decodeToPeaks(arrayBuffer, signal, peakCount =
|
|
7070
|
+
async function decodeToPeaks(arrayBuffer, signal, peakCount = _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_PEAK_COUNT */ .f3) {
|
|
7227
7071
|
if (signal?.aborted) {
|
|
7228
7072
|
throw createAbortError();
|
|
7229
7073
|
}
|
|
7230
7074
|
const AudioContextConstructor = getAudioContextConstructor();
|
|
7231
7075
|
if (!AudioContextConstructor) {
|
|
7232
|
-
throw new WaveformLoadError('DECODE_FAILED', 'AudioContext is not available');
|
|
7076
|
+
throw new _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz('DECODE_FAILED', 'AudioContext is not available');
|
|
7233
7077
|
}
|
|
7234
7078
|
const context = new AudioContextConstructor();
|
|
7235
7079
|
try {
|
|
@@ -7237,15 +7081,15 @@ async function decodeToPeaks(arrayBuffer, signal, peakCount = constants/* CLIENT
|
|
|
7237
7081
|
if (signal?.aborted) {
|
|
7238
7082
|
throw createAbortError();
|
|
7239
7083
|
}
|
|
7240
|
-
const extractStarted = (0,
|
|
7084
|
+
const extractStarted = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)();
|
|
7241
7085
|
const peaks = extractPeaks(audioBuffer, peakCount);
|
|
7242
7086
|
return {
|
|
7243
7087
|
durationSec: audioBuffer.duration,
|
|
7244
7088
|
peaks,
|
|
7245
|
-
extractMs: (0,
|
|
7089
|
+
extractMs: (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - extractStarted
|
|
7246
7090
|
};
|
|
7247
7091
|
} catch (error) {
|
|
7248
|
-
if (signal?.aborted || isAbortError(error)) {
|
|
7092
|
+
if (signal?.aborted || (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
|
|
7249
7093
|
throw createAbortError();
|
|
7250
7094
|
}
|
|
7251
7095
|
throw error;
|
|
@@ -7278,31 +7122,31 @@ async function runClientDecode(options) {
|
|
|
7278
7122
|
};
|
|
7279
7123
|
}
|
|
7280
7124
|
const signal = options.signal ?? new AbortController().signal;
|
|
7281
|
-
const decodeStarted = (0,
|
|
7125
|
+
const decodeStarted = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)();
|
|
7282
7126
|
let decodeOutput;
|
|
7283
7127
|
try {
|
|
7284
7128
|
decodeOutput = await options.decode(signal);
|
|
7285
7129
|
} catch (error) {
|
|
7286
|
-
if (signal.aborted || isAbortError(error)) {
|
|
7130
|
+
if (signal.aborted || (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
|
|
7287
7131
|
return {
|
|
7288
7132
|
status: 'cancelled',
|
|
7289
7133
|
isDecodeSkipped: false,
|
|
7290
7134
|
timings: EMPTY_TIMINGS
|
|
7291
7135
|
};
|
|
7292
7136
|
}
|
|
7293
|
-
const waveformError = errorFromUnknown(error, 'DECODE_FAILED');
|
|
7137
|
+
const waveformError = (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .errorFromUnknown */ .Vq)(error, 'DECODE_FAILED');
|
|
7294
7138
|
return {
|
|
7295
7139
|
status: 'failed',
|
|
7296
7140
|
error: waveformError,
|
|
7297
|
-
retryable:
|
|
7141
|
+
retryable: (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isRetryableWaveformError */ .Oe)(waveformError.code),
|
|
7298
7142
|
isDecodeSkipped: false,
|
|
7299
7143
|
timings: {
|
|
7300
|
-
attemptMs: (0,
|
|
7144
|
+
attemptMs: (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - decodeStarted,
|
|
7301
7145
|
extractMs: null
|
|
7302
7146
|
}
|
|
7303
7147
|
};
|
|
7304
7148
|
}
|
|
7305
|
-
const attemptMs = (0,
|
|
7149
|
+
const attemptMs = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - decodeStarted;
|
|
7306
7150
|
if (signal.aborted) {
|
|
7307
7151
|
return {
|
|
7308
7152
|
status: 'cancelled',
|
|
@@ -7313,8 +7157,8 @@ async function runClientDecode(options) {
|
|
|
7313
7157
|
}
|
|
7314
7158
|
};
|
|
7315
7159
|
}
|
|
7316
|
-
const validation =
|
|
7317
|
-
version:
|
|
7160
|
+
const validation = (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .validateWaveformPayload */ .a9)({
|
|
7161
|
+
version: _constants__WEBPACK_IMPORTED_MODULE_1__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
|
|
7318
7162
|
durationSec: options.durationSec ?? decodeOutput.durationSec,
|
|
7319
7163
|
peaks: decodeOutput.peaks
|
|
7320
7164
|
}, {
|
|
@@ -7324,7 +7168,7 @@ async function runClientDecode(options) {
|
|
|
7324
7168
|
return {
|
|
7325
7169
|
status: 'failed',
|
|
7326
7170
|
error: validation.error,
|
|
7327
|
-
retryable:
|
|
7171
|
+
retryable: (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isRetryableWaveformError */ .Oe)(validation.error.code),
|
|
7328
7172
|
isDecodeSkipped: false,
|
|
7329
7173
|
timings: {
|
|
7330
7174
|
attemptMs,
|
|
@@ -7361,6 +7205,193 @@ function loadPeaks(request) {
|
|
|
7361
7205
|
|
|
7362
7206
|
/***/ },
|
|
7363
7207
|
|
|
7208
|
+
/***/ 1053
|
|
7209
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
7210
|
+
|
|
7211
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
7212
|
+
/* harmony export */ Oe: () => (/* binding */ isRetryableWaveformError),
|
|
7213
|
+
/* harmony export */ Ze: () => (/* binding */ isPositiveFinite),
|
|
7214
|
+
/* harmony export */ a9: () => (/* binding */ validateWaveformPayload)
|
|
7215
|
+
/* harmony export */ });
|
|
7216
|
+
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4929);
|
|
7217
|
+
|
|
7218
|
+
const DEFAULT_PEAK_SCALE = 'unit';
|
|
7219
|
+
const DEFAULT_CHANNEL_POLICY = 'mono_max';
|
|
7220
|
+
const DEFAULT_ENVELOPE = 'peak';
|
|
7221
|
+
function fail(code, message, retryable = false) {
|
|
7222
|
+
return {
|
|
7223
|
+
ok: false,
|
|
7224
|
+
error: {
|
|
7225
|
+
code,
|
|
7226
|
+
message
|
|
7227
|
+
},
|
|
7228
|
+
retryable
|
|
7229
|
+
};
|
|
7230
|
+
}
|
|
7231
|
+
function isPositiveFinite(value) {
|
|
7232
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0;
|
|
7233
|
+
}
|
|
7234
|
+
function isPlainObject(value) {
|
|
7235
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7236
|
+
}
|
|
7237
|
+
function payloadByteLength(raw) {
|
|
7238
|
+
try {
|
|
7239
|
+
const serialized = JSON.stringify(raw);
|
|
7240
|
+
if (typeof Buffer !== 'undefined') {
|
|
7241
|
+
return Buffer.byteLength(serialized, 'utf8');
|
|
7242
|
+
}
|
|
7243
|
+
if (typeof TextEncoder !== 'undefined') {
|
|
7244
|
+
return new TextEncoder().encode(serialized).length;
|
|
7245
|
+
}
|
|
7246
|
+
return serialized.length;
|
|
7247
|
+
} catch {
|
|
7248
|
+
return Number.MAX_SAFE_INTEGER;
|
|
7249
|
+
}
|
|
7250
|
+
}
|
|
7251
|
+
function readOptionalPolicy(raw, key, allowed) {
|
|
7252
|
+
if (!(key in raw) || raw[key] === undefined) {
|
|
7253
|
+
return undefined;
|
|
7254
|
+
}
|
|
7255
|
+
return raw[key] === allowed ? allowed : null;
|
|
7256
|
+
}
|
|
7257
|
+
function asWaveformPayloadV1(raw) {
|
|
7258
|
+
const {
|
|
7259
|
+
version,
|
|
7260
|
+
durationSec,
|
|
7261
|
+
peaks
|
|
7262
|
+
} = raw;
|
|
7263
|
+
if (version !== _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh || typeof durationSec !== 'number' || !Array.isArray(peaks)) {
|
|
7264
|
+
return null;
|
|
7265
|
+
}
|
|
7266
|
+
const peakScale = readOptionalPolicy(raw, 'peakScale', DEFAULT_PEAK_SCALE);
|
|
7267
|
+
const channelPolicy = readOptionalPolicy(raw, 'channelPolicy', DEFAULT_CHANNEL_POLICY);
|
|
7268
|
+
const envelope = readOptionalPolicy(raw, 'envelope', DEFAULT_ENVELOPE);
|
|
7269
|
+
if (peakScale === null || channelPolicy === null || envelope === null) {
|
|
7270
|
+
return null;
|
|
7271
|
+
}
|
|
7272
|
+
if ('channels' in raw && raw.channels !== undefined && raw.channels !== 1) {
|
|
7273
|
+
return null;
|
|
7274
|
+
}
|
|
7275
|
+
return {
|
|
7276
|
+
version: _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
|
|
7277
|
+
durationSec,
|
|
7278
|
+
peaks: peaks,
|
|
7279
|
+
peakScale: peakScale ?? DEFAULT_PEAK_SCALE,
|
|
7280
|
+
channelPolicy: channelPolicy ?? DEFAULT_CHANNEL_POLICY,
|
|
7281
|
+
envelope: envelope ?? DEFAULT_ENVELOPE,
|
|
7282
|
+
channels: 1
|
|
7283
|
+
};
|
|
7284
|
+
}
|
|
7285
|
+
function readPayloadObject(raw, maxPayloadBytes, isPayloadByteCheckSkipped = false) {
|
|
7286
|
+
if (raw === null || raw === undefined) {
|
|
7287
|
+
return fail('INVALID_PAYLOAD', 'Payload is null or undefined');
|
|
7288
|
+
}
|
|
7289
|
+
if (!isPayloadByteCheckSkipped) {
|
|
7290
|
+
const byteLength = payloadByteLength(raw);
|
|
7291
|
+
if (byteLength > maxPayloadBytes) {
|
|
7292
|
+
return fail('PAYLOAD_TOO_LARGE', `Payload size ${byteLength} exceeds limit ${maxPayloadBytes}`);
|
|
7293
|
+
}
|
|
7294
|
+
}
|
|
7295
|
+
if (!isPlainObject(raw)) {
|
|
7296
|
+
return fail('INVALID_PAYLOAD', 'Payload must be an object');
|
|
7297
|
+
}
|
|
7298
|
+
return {
|
|
7299
|
+
ok: true,
|
|
7300
|
+
value: raw
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
function checkVersion(raw) {
|
|
7304
|
+
if (raw.version === _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh) {
|
|
7305
|
+
return null;
|
|
7306
|
+
}
|
|
7307
|
+
const {
|
|
7308
|
+
version
|
|
7309
|
+
} = raw;
|
|
7310
|
+
if (typeof version === 'number' && version > _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh) {
|
|
7311
|
+
return fail('UNSUPPORTED_VERSION', `Unsupported waveform version ${version}; max supported is ${_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh}`);
|
|
7312
|
+
}
|
|
7313
|
+
return fail('INVALID_PAYLOAD', 'Missing or invalid version field');
|
|
7314
|
+
}
|
|
7315
|
+
function checkDuration(payload, expectedDurationSec) {
|
|
7316
|
+
if (!isPositiveFinite(payload.durationSec)) {
|
|
7317
|
+
return fail('INVALID_DURATION', 'durationSec must be a positive finite number');
|
|
7318
|
+
}
|
|
7319
|
+
if (expectedDurationSec !== undefined && Number.isFinite(expectedDurationSec) && Math.abs(payload.durationSec - expectedDurationSec) > _constants__WEBPACK_IMPORTED_MODULE_0__/* .DURATION_MISMATCH_TOLERANCE_SEC */ .GQ) {
|
|
7320
|
+
return fail('DURATION_MISMATCH', `Payload duration ${payload.durationSec}s differs from media duration ${expectedDurationSec}s`, true);
|
|
7321
|
+
}
|
|
7322
|
+
return null;
|
|
7323
|
+
}
|
|
7324
|
+
function normalizePeaks(peaks, maxPeakCount) {
|
|
7325
|
+
if (peaks.length === 0) {
|
|
7326
|
+
return fail('EMPTY_PEAKS', 'peaks array must not be empty');
|
|
7327
|
+
}
|
|
7328
|
+
if (peaks.length > maxPeakCount) {
|
|
7329
|
+
return fail('PEAK_COUNT_EXCEEDED', `peaks length ${peaks.length} exceeds max ${maxPeakCount}`);
|
|
7330
|
+
}
|
|
7331
|
+
const normalized = new Float32Array(peaks.length);
|
|
7332
|
+
for (let i = 0; i < peaks.length; i += 1) {
|
|
7333
|
+
const value = peaks[i];
|
|
7334
|
+
if (!Number.isFinite(value)) {
|
|
7335
|
+
return fail('NON_FINITE_PEAK', `Peak at index ${i} is not finite`);
|
|
7336
|
+
}
|
|
7337
|
+
if (value < _constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MIN */ .mJ || value > _constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MAX */ .i8) {
|
|
7338
|
+
return fail('PEAK_OUT_OF_RANGE', `Peak at index ${i} is outside [${_constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MIN */ .mJ}, ${_constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MAX */ .i8}]`);
|
|
7339
|
+
}
|
|
7340
|
+
normalized[i] = value;
|
|
7341
|
+
}
|
|
7342
|
+
return {
|
|
7343
|
+
ok: true,
|
|
7344
|
+
peaks: normalized
|
|
7345
|
+
};
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
/**
|
|
7349
|
+
* Validates a version-1 waveform payload and returns normalized peaks for rendering.
|
|
7350
|
+
* Wire JSON requires version, durationSec, and peaks. sampleCount and source are ignored.
|
|
7351
|
+
*/
|
|
7352
|
+
function validateWaveformPayload(raw, options = {}) {
|
|
7353
|
+
const maxPeakCount = options.maxPeakCount ?? _constants__WEBPACK_IMPORTED_MODULE_0__/* .MAX_PEAK_COUNT */ .FY;
|
|
7354
|
+
const maxPayloadBytes = options.maxPayloadBytes ?? _constants__WEBPACK_IMPORTED_MODULE_0__/* .MAX_PAYLOAD_BYTES */ .qY;
|
|
7355
|
+
const objectResult = readPayloadObject(raw, maxPayloadBytes, options.isPayloadByteCheckSkipped === true);
|
|
7356
|
+
if (!objectResult.ok) {
|
|
7357
|
+
return objectResult;
|
|
7358
|
+
}
|
|
7359
|
+
const versionFailure = checkVersion(objectResult.value);
|
|
7360
|
+
if (versionFailure) {
|
|
7361
|
+
return versionFailure;
|
|
7362
|
+
}
|
|
7363
|
+
const payload = asWaveformPayloadV1(objectResult.value);
|
|
7364
|
+
if (!payload) {
|
|
7365
|
+
return fail('INVALID_PAYLOAD', 'Payload failed structural validation');
|
|
7366
|
+
}
|
|
7367
|
+
const durationFailure = checkDuration(payload, options.expectedDurationSec);
|
|
7368
|
+
if (durationFailure) {
|
|
7369
|
+
return durationFailure;
|
|
7370
|
+
}
|
|
7371
|
+
const peaksResult = normalizePeaks(payload.peaks, maxPeakCount);
|
|
7372
|
+
if (!peaksResult.ok) {
|
|
7373
|
+
return peaksResult;
|
|
7374
|
+
}
|
|
7375
|
+
return {
|
|
7376
|
+
ok: true,
|
|
7377
|
+
payload: {
|
|
7378
|
+
version: _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
|
|
7379
|
+
durationSec: payload.durationSec,
|
|
7380
|
+
peaks: peaksResult.peaks,
|
|
7381
|
+
peakScale: payload.peakScale ?? DEFAULT_PEAK_SCALE,
|
|
7382
|
+
channelPolicy: payload.channelPolicy ?? DEFAULT_CHANNEL_POLICY,
|
|
7383
|
+
envelope: payload.envelope ?? DEFAULT_ENVELOPE
|
|
7384
|
+
}
|
|
7385
|
+
};
|
|
7386
|
+
}
|
|
7387
|
+
|
|
7388
|
+
/** Maps validation / load failures to retry policy for loaders. */
|
|
7389
|
+
function isRetryableWaveformError(code) {
|
|
7390
|
+
return code === 'DURATION_MISMATCH' || code === 'DECODE_FAILED' || code === 'LOAD_FAILED';
|
|
7391
|
+
}
|
|
7392
|
+
|
|
7393
|
+
/***/ },
|
|
7394
|
+
|
|
7364
7395
|
/***/ 2485
|
|
7365
7396
|
(module, exports) {
|
|
7366
7397
|
|
|
@@ -23024,7 +23055,7 @@ class Browser {
|
|
|
23024
23055
|
;// ./src/lib/Logger.js
|
|
23025
23056
|
/* eslint-disable no-undef */
|
|
23026
23057
|
const CLIENT_NAME = "box-content-preview";
|
|
23027
|
-
const CLIENT_VERSION = "3.
|
|
23058
|
+
const CLIENT_VERSION = "3.90.0";
|
|
23028
23059
|
/* eslint-enable no-undef */
|
|
23029
23060
|
|
|
23030
23061
|
class Logger {
|
|
@@ -35709,6 +35740,12 @@ class MP3ControlsRoot {
|
|
|
35709
35740
|
this.root.render(controls);
|
|
35710
35741
|
}
|
|
35711
35742
|
}
|
|
35743
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/constants.ts
|
|
35744
|
+
var waveform_constants = __webpack_require__(4929);
|
|
35745
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/createWaveformLoader.ts + 1 modules
|
|
35746
|
+
var createWaveformLoader = __webpack_require__(4971);
|
|
35747
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
|
|
35748
|
+
var validateWaveformPayload = __webpack_require__(1053);
|
|
35712
35749
|
;// ./src/lib/viewers/media/MP3.scss
|
|
35713
35750
|
// extracted by mini-css-extract-plugin
|
|
35714
35751
|
|
|
@@ -35723,6 +35760,11 @@ function MP3Viewer_toPrimitive(t, r) { if ("object" != typeof t || !t) return t;
|
|
|
35723
35760
|
|
|
35724
35761
|
|
|
35725
35762
|
|
|
35763
|
+
|
|
35764
|
+
|
|
35765
|
+
|
|
35766
|
+
|
|
35767
|
+
|
|
35726
35768
|
const CSS_CLASS_MP3 = 'bp-media-mp3';
|
|
35727
35769
|
function createLoadFailedError(message) {
|
|
35728
35770
|
const error = new Error(message);
|
|
@@ -35738,7 +35780,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35738
35780
|
MP3Viewer_defineProperty(this, "handlePlayRequest", () => {
|
|
35739
35781
|
this.userRequestedPlay = true;
|
|
35740
35782
|
this.togglePlay();
|
|
35741
|
-
if (this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
|
|
35783
|
+
if (this.shouldRaceClientWaveformDecode() && this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
|
|
35742
35784
|
this.hasUsedWaveformDecodePlayRetry = true;
|
|
35743
35785
|
this.isWaveformDecodeRetryPending = false;
|
|
35744
35786
|
this.startClientWaveformDecode();
|
|
@@ -35775,11 +35817,11 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35775
35817
|
});
|
|
35776
35818
|
MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
|
|
35777
35819
|
this.hostSelectedMarkerId = marker.id;
|
|
35778
|
-
this.pendingHostSelectedSeek =
|
|
35820
|
+
this.pendingHostSelectedSeek = marker;
|
|
35779
35821
|
if (this.mediaEl) {
|
|
35780
35822
|
this.mediaEl.pause();
|
|
35781
|
-
this.mediaEl.currentTime = marker.time;
|
|
35782
35823
|
}
|
|
35824
|
+
this.applyPendingHostSelectedSeek();
|
|
35783
35825
|
// Overlay paints the ring from click optimism until the host re-emits selected.
|
|
35784
35826
|
this.emit('comment_marker_select', {
|
|
35785
35827
|
id: marker.id,
|
|
@@ -35811,11 +35853,16 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35811
35853
|
this.wrapperEl.classList.add(CSS_CLASS_MP3);
|
|
35812
35854
|
this.isAudioPlayerV2 = this.getIsAudioPlayerV2();
|
|
35813
35855
|
this.waveformPeaks = [];
|
|
35856
|
+
this.waveformPeaksSource = null;
|
|
35857
|
+
this.waveformDurationSec = 0;
|
|
35814
35858
|
if (this.isAudioPlayerV2) {
|
|
35815
35859
|
this.wrapperEl.classList.add('bp-media--v2');
|
|
35816
35860
|
this.mediaContainerEl.classList.add('bp-media-container--v2');
|
|
35817
35861
|
this.ensureV2Controls();
|
|
35818
35862
|
this.importWaveformDecode();
|
|
35863
|
+
// Listen on the loading shell. The waveform is on
|
|
35864
|
+
// screen before the audio blob is playable; getViewer() is still null.
|
|
35865
|
+
this.bindCommentMarkersListener();
|
|
35819
35866
|
}
|
|
35820
35867
|
|
|
35821
35868
|
// Audio element
|
|
@@ -35823,6 +35870,13 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35823
35870
|
this.mediaEl.setAttribute('preload', 'auto');
|
|
35824
35871
|
this.commentMarkers = [];
|
|
35825
35872
|
}
|
|
35873
|
+
bindCommentMarkersListener() {
|
|
35874
|
+
if (!this.isAudioPlayerV2) {
|
|
35875
|
+
return;
|
|
35876
|
+
}
|
|
35877
|
+
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35878
|
+
this.addListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35879
|
+
}
|
|
35826
35880
|
|
|
35827
35881
|
/**
|
|
35828
35882
|
* Audio player v2 (waveform). Off unless the host enables `audioPlayerV2`
|
|
@@ -35831,7 +35885,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35831
35885
|
* @return {boolean} whether v2 treatment is on
|
|
35832
35886
|
*/
|
|
35833
35887
|
getIsAudioPlayerV2() {
|
|
35834
|
-
return this.featureEnabled(
|
|
35888
|
+
return this.featureEnabled(constants/* AUDIO_PLAYER_V2 */.Ku) && this.useReactControls();
|
|
35835
35889
|
}
|
|
35836
35890
|
|
|
35837
35891
|
/**
|
|
@@ -35863,6 +35917,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35863
35917
|
*/
|
|
35864
35918
|
fallbackToV1Controls() {
|
|
35865
35919
|
this.isAudioPlayerV2 = false;
|
|
35920
|
+
this.abortWaveformLoads();
|
|
35866
35921
|
if (this.wrapperEl) {
|
|
35867
35922
|
this.wrapperEl.classList.remove('bp-media--v2');
|
|
35868
35923
|
}
|
|
@@ -35883,7 +35938,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35883
35938
|
*/
|
|
35884
35939
|
async importWaveformDecode() {
|
|
35885
35940
|
if (!this.waveformDecodeImport) {
|
|
35886
|
-
this.waveformDecodeImport = Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
35941
|
+
this.waveformDecodeImport = Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 8296));
|
|
35887
35942
|
}
|
|
35888
35943
|
try {
|
|
35889
35944
|
return await this.waveformDecodeImport;
|
|
@@ -35898,7 +35953,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35898
35953
|
*/
|
|
35899
35954
|
destroy() {
|
|
35900
35955
|
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35901
|
-
this.
|
|
35956
|
+
this.abortWaveformLoads();
|
|
35902
35957
|
super.destroy();
|
|
35903
35958
|
}
|
|
35904
35959
|
|
|
@@ -35908,6 +35963,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35908
35963
|
load() {
|
|
35909
35964
|
if (this.isAudioPlayerV2) {
|
|
35910
35965
|
this.showAudioLoadingShell();
|
|
35966
|
+
this.startConversionWaveformLoad();
|
|
35911
35967
|
}
|
|
35912
35968
|
return super.load();
|
|
35913
35969
|
}
|
|
@@ -35945,6 +36001,9 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35945
36001
|
* @inheritdoc
|
|
35946
36002
|
*/
|
|
35947
36003
|
loadeddataHandler() {
|
|
36004
|
+
if (this.isAudioPlayerV2) {
|
|
36005
|
+
this.dropConversionPeaksOnDurationMismatch();
|
|
36006
|
+
}
|
|
35948
36007
|
super.loadeddataHandler();
|
|
35949
36008
|
if (!this.isAudioPlayerV2) {
|
|
35950
36009
|
return;
|
|
@@ -35955,7 +36014,173 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35955
36014
|
if (this.userRequestedPlay) {
|
|
35956
36015
|
this.play();
|
|
35957
36016
|
}
|
|
35958
|
-
this.
|
|
36017
|
+
if (this.shouldRaceClientWaveformDecode()) {
|
|
36018
|
+
this.startClientWaveformDecode();
|
|
36019
|
+
}
|
|
36020
|
+
}
|
|
36021
|
+
|
|
36022
|
+
/**
|
|
36023
|
+
* Client decode races conversion until some source applies peaks. Size and
|
|
36024
|
+
* duration caps still apply. First source to apply peaks wins; later
|
|
36025
|
+
* results are ignored.
|
|
36026
|
+
*
|
|
36027
|
+
* @return {boolean}
|
|
36028
|
+
*/
|
|
36029
|
+
shouldRaceClientWaveformDecode() {
|
|
36030
|
+
if (!this.isAudioPlayerV2 || this.destroyed || this.waveformPeaksSource) {
|
|
36031
|
+
return false;
|
|
36032
|
+
}
|
|
36033
|
+
const compressedBytes = this.options.file?.size;
|
|
36034
|
+
const durationSec = this.mediaEl?.duration;
|
|
36035
|
+
return (0,validateWaveformPayload/* isPositiveFinite */.Ze)(compressedBytes) && compressedBytes <= waveform_constants/* CLIENT_DECODE_MAX_COMPRESSED_BYTES */.EB && (0,validateWaveformPayload/* isPositiveFinite */.Ze)(durationSec) && durationSec <= waveform_constants/* CLIENT_DECODE_MAX_DURATION_SEC */.nG;
|
|
36036
|
+
}
|
|
36037
|
+
|
|
36038
|
+
/**
|
|
36039
|
+
* @param {number} durationSec
|
|
36040
|
+
* @return {boolean}
|
|
36041
|
+
*/
|
|
36042
|
+
isConversionDurationMismatch(durationSec) {
|
|
36043
|
+
const mediaDuration = this.mediaEl?.duration;
|
|
36044
|
+
return (0,validateWaveformPayload/* isPositiveFinite */.Ze)(mediaDuration) && (0,validateWaveformPayload/* isPositiveFinite */.Ze)(durationSec) && Math.abs(durationSec - mediaDuration) > waveform_constants/* DURATION_MISMATCH_TOLERANCE_SEC */.GQ;
|
|
36045
|
+
}
|
|
36046
|
+
|
|
36047
|
+
/**
|
|
36048
|
+
* Conversion JSON fetched before metadata skipped duration matching. Drop
|
|
36049
|
+
* those peaks once media duration is known if they disagree.
|
|
36050
|
+
*
|
|
36051
|
+
* @return {void}
|
|
36052
|
+
*/
|
|
36053
|
+
dropConversionPeaksOnDurationMismatch() {
|
|
36054
|
+
if (this.waveformPeaksSource !== 'conversion' || !this.isConversionDurationMismatch(this.waveformDurationSec)) {
|
|
36055
|
+
return;
|
|
36056
|
+
}
|
|
36057
|
+
this.waveformPeaks = [];
|
|
36058
|
+
this.waveformPeaksSource = null;
|
|
36059
|
+
this.waveformDurationSec = 0;
|
|
36060
|
+
this.renderUI();
|
|
36061
|
+
}
|
|
36062
|
+
|
|
36063
|
+
/**
|
|
36064
|
+
* Poll the conversion waveform representation and fetch its JSON.
|
|
36065
|
+
* Missing, failed, or unloadable conversion falls back to client decode
|
|
36066
|
+
* when the file is under size and duration caps.
|
|
36067
|
+
*
|
|
36068
|
+
* @return {Promise<void>}
|
|
36069
|
+
*/
|
|
36070
|
+
async startConversionWaveformLoad() {
|
|
36071
|
+
if (!this.isAudioPlayerV2 || this.destroyed) {
|
|
36072
|
+
return;
|
|
36073
|
+
}
|
|
36074
|
+
const {
|
|
36075
|
+
file
|
|
36076
|
+
} = this.options;
|
|
36077
|
+
const waveform = file?.representations?.entries ? getRepresentation(file, constants/* WAVEFORM_REP_NAME */.u4) : null;
|
|
36078
|
+
const template = waveform?.content?.url_template;
|
|
36079
|
+
const conversionStatus = waveform?.status;
|
|
36080
|
+
const statusState = conversionStatus && typeof conversionStatus === 'object' ? conversionStatus.state : null;
|
|
36081
|
+
if (!waveform || !template || !statusState || statusState === constants/* STATUS_ERROR */.uD) {
|
|
36082
|
+
this.startClientWaveformDecode();
|
|
36083
|
+
return;
|
|
36084
|
+
}
|
|
36085
|
+
this.abortConversionWaveformLoad();
|
|
36086
|
+
this.waveformStatus = this.getRepStatus(waveform);
|
|
36087
|
+
this.waveformStatus.removeListener('conversionpending', this.resetLoadTimeout);
|
|
36088
|
+
const status = this.waveformStatus;
|
|
36089
|
+
try {
|
|
36090
|
+
await status.getPromise();
|
|
36091
|
+
if (this.destroyed || this.waveformStatus !== status || this.waveformPeaksSource) {
|
|
36092
|
+
return;
|
|
36093
|
+
}
|
|
36094
|
+
const result = await this.loadConversionWaveformPayload(template);
|
|
36095
|
+
this.handleConversionWaveformResult(result, status);
|
|
36096
|
+
} catch {
|
|
36097
|
+
this.startClientWaveformDecode();
|
|
36098
|
+
}
|
|
36099
|
+
}
|
|
36100
|
+
|
|
36101
|
+
/**
|
|
36102
|
+
* Fetch and validate conversion waveform JSON after the rep is ready.
|
|
36103
|
+
* `{+asset_path}` is empty. Auth is a header, not a query token.
|
|
36104
|
+
*
|
|
36105
|
+
* @param {string} template - content URL template
|
|
36106
|
+
* @return {Promise<import('./waveform/types').WaveformLoadState>}
|
|
36107
|
+
*/
|
|
36108
|
+
loadConversionWaveformPayload(template) {
|
|
36109
|
+
const url = this.createContentUrlV2(template);
|
|
36110
|
+
const durationSec = this.mediaEl?.duration;
|
|
36111
|
+
const source = (0,createWaveformLoader/* createWaveformLoader */.nR)(signal => this.api.get(url, {
|
|
36112
|
+
headers: this.appendAuthHeader(),
|
|
36113
|
+
signal
|
|
36114
|
+
}), Number.isFinite(durationSec) ? {
|
|
36115
|
+
expectedDurationSec: durationSec
|
|
36116
|
+
} : {});
|
|
36117
|
+
this.waveformSource = source;
|
|
36118
|
+
return source.load();
|
|
36119
|
+
}
|
|
36120
|
+
abortWaveformLoads() {
|
|
36121
|
+
this.abortConversionWaveformLoad();
|
|
36122
|
+
this.abortClientWaveformDecode();
|
|
36123
|
+
}
|
|
36124
|
+
abortConversionWaveformLoad() {
|
|
36125
|
+
if (this.waveformSource) {
|
|
36126
|
+
this.waveformSource.abort();
|
|
36127
|
+
this.waveformSource = null;
|
|
36128
|
+
}
|
|
36129
|
+
if (this.waveformStatus) {
|
|
36130
|
+
this.waveformStatus.destroy();
|
|
36131
|
+
this.waveformStatus = null;
|
|
36132
|
+
}
|
|
36133
|
+
}
|
|
36134
|
+
|
|
36135
|
+
/**
|
|
36136
|
+
* First source to apply peaks wins. Later results are ignored.
|
|
36137
|
+
*
|
|
36138
|
+
* @param {'conversion'|'client'} source
|
|
36139
|
+
* @param {{ peaks: ArrayLike<number>, durationSec?: number }} payload
|
|
36140
|
+
* @return {boolean} true when this source claimed peaks
|
|
36141
|
+
*/
|
|
36142
|
+
applyWaveformPeaks(source, payload) {
|
|
36143
|
+
if (this.waveformPeaksSource) {
|
|
36144
|
+
return false;
|
|
36145
|
+
}
|
|
36146
|
+
this.waveformPeaks = payload.peaks;
|
|
36147
|
+
this.waveformPeaksSource = source;
|
|
36148
|
+
this.isWaveformDecodeRetryPending = false;
|
|
36149
|
+
if (source === 'conversion') {
|
|
36150
|
+
this.waveformDurationSec = payload.durationSec;
|
|
36151
|
+
this.abortClientWaveformDecode();
|
|
36152
|
+
} else if (this.waveformSource) {
|
|
36153
|
+
// RepStatus.destroy() does not reject getPromise().
|
|
36154
|
+
this.waveformSource.abort();
|
|
36155
|
+
this.waveformSource = null;
|
|
36156
|
+
}
|
|
36157
|
+
this.renderUI();
|
|
36158
|
+
return true;
|
|
36159
|
+
}
|
|
36160
|
+
|
|
36161
|
+
/**
|
|
36162
|
+
* Apply conversion peaks when the load is still current. Ignored if client
|
|
36163
|
+
* decode already applied peaks.
|
|
36164
|
+
*
|
|
36165
|
+
* @param {import('./waveform/types').WaveformLoadState} result
|
|
36166
|
+
* @param {Object} status - RepStatus instance that started this load
|
|
36167
|
+
* @return {void}
|
|
36168
|
+
*/
|
|
36169
|
+
handleConversionWaveformResult(result, status) {
|
|
36170
|
+
if (!result || this.destroyed || !this.isAudioPlayerV2 || this.waveformStatus !== status) {
|
|
36171
|
+
return;
|
|
36172
|
+
}
|
|
36173
|
+
if (result.status !== 'ready') {
|
|
36174
|
+
if (result.status !== 'cancelled') {
|
|
36175
|
+
this.startClientWaveformDecode();
|
|
36176
|
+
}
|
|
36177
|
+
return;
|
|
36178
|
+
}
|
|
36179
|
+
if (this.isConversionDurationMismatch(result.payload.durationSec)) {
|
|
36180
|
+
this.startClientWaveformDecode();
|
|
36181
|
+
return;
|
|
36182
|
+
}
|
|
36183
|
+
this.applyWaveformPeaks('conversion', result.payload);
|
|
35959
36184
|
}
|
|
35960
36185
|
/**
|
|
35961
36186
|
* Fetch compressed audio bytes for client decode. Prefers an already-fetched blob URL.
|
|
@@ -35996,16 +36221,19 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35996
36221
|
}
|
|
35997
36222
|
|
|
35998
36223
|
/**
|
|
35999
|
-
* Decode peaks in the background
|
|
36000
|
-
*
|
|
36224
|
+
* Decode peaks in the background until conversion or client decode applies
|
|
36225
|
+
* them, when the file is under size and duration caps. Does not block
|
|
36226
|
+
* playback. First source to apply peaks wins.
|
|
36001
36227
|
*
|
|
36002
36228
|
* @return {Promise<void>}
|
|
36003
36229
|
*/
|
|
36004
36230
|
async startClientWaveformDecode() {
|
|
36005
|
-
if (!this.
|
|
36231
|
+
if (!this.shouldRaceClientWaveformDecode()) {
|
|
36232
|
+
return;
|
|
36233
|
+
}
|
|
36234
|
+
if (this.waveformDecodeController && !this.waveformDecodeController.signal.aborted) {
|
|
36006
36235
|
return;
|
|
36007
36236
|
}
|
|
36008
|
-
this.abortClientWaveformDecode();
|
|
36009
36237
|
const controller = new AbortController();
|
|
36010
36238
|
this.waveformDecodeController = controller;
|
|
36011
36239
|
const {
|
|
@@ -36054,9 +36282,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36054
36282
|
return;
|
|
36055
36283
|
}
|
|
36056
36284
|
if (result.status === 'ready') {
|
|
36057
|
-
this.
|
|
36058
|
-
this.isWaveformDecodeRetryPending = false;
|
|
36059
|
-
this.renderUI();
|
|
36285
|
+
this.applyWaveformPeaks('client', result.payload);
|
|
36060
36286
|
return;
|
|
36061
36287
|
}
|
|
36062
36288
|
if (result.status === 'cancelled') {
|
|
@@ -36086,10 +36312,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36086
36312
|
containerEl: this.mediaContainerEl
|
|
36087
36313
|
});
|
|
36088
36314
|
}
|
|
36089
|
-
|
|
36090
|
-
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
36091
|
-
this.addListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
36092
|
-
}
|
|
36315
|
+
this.bindCommentMarkersListener();
|
|
36093
36316
|
this.renderUI();
|
|
36094
36317
|
}
|
|
36095
36318
|
/**
|
|
@@ -36117,11 +36340,13 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36117
36340
|
if (!this.controls) {
|
|
36118
36341
|
return;
|
|
36119
36342
|
}
|
|
36343
|
+
const mediaDuration = this.mediaEl.duration;
|
|
36344
|
+
const durationTime = typeof mediaDuration === 'number' && mediaDuration > 0 ? mediaDuration : this.waveformDurationSec;
|
|
36120
36345
|
const sharedProps = {
|
|
36121
36346
|
autoplay: this.isAutoplayEnabled(),
|
|
36122
36347
|
bufferedRange: this.mediaEl.buffered,
|
|
36123
36348
|
currentTime: this.mediaEl.currentTime,
|
|
36124
|
-
durationTime
|
|
36349
|
+
durationTime,
|
|
36125
36350
|
isPlaying: !this.mediaEl.paused,
|
|
36126
36351
|
movePlayback: this.movePlayback,
|
|
36127
36352
|
onAutoplayChange: this.setAutoplay,
|
|
@@ -54353,8 +54578,12 @@ class Preview extends (events_default()) {
|
|
|
54353
54578
|
if (isDash && isFeatureEnabled(this.options.features, constants/* AI_TRANSCRIPTION_FOR_VIDEO_SUBTITLES */.Iu)) {
|
|
54354
54579
|
videoHint += constants/* X_REP_HINT_VIDEO_DASH_EXTRACTED_TEXT */.xU;
|
|
54355
54580
|
}
|
|
54581
|
+
let hints = `${constants/* X_REP_HINT_BASE */.pl}${constants/* X_REP_HINT_DOC_THUMBNAIL */.nC}${constants/* X_REP_HINT_IMAGE */.h3}${videoHint}`;
|
|
54582
|
+
if (isFeatureEnabled(this.options.features, constants/* AUDIO_PLAYER_V2 */.Ku)) {
|
|
54583
|
+
hints += constants/* X_REP_HINT_WAVEFORM */.jr;
|
|
54584
|
+
}
|
|
54356
54585
|
const headers = {
|
|
54357
|
-
'X-Rep-Hints':
|
|
54586
|
+
'X-Rep-Hints': hints
|
|
54358
54587
|
};
|
|
54359
54588
|
return (0,util/* getHeaders */.dJ)(headers, token || this.options.token, this.options.sharedLink, this.options.sharedLinkPassword);
|
|
54360
54589
|
}
|