sanity-plugin-mux-input 2.11.1 → 2.12.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 +49 -5
- package/dist/index.d.mts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +186 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +186 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/_exports/index.ts +26 -2
- package/src/actions/upload.ts +4 -3
- package/src/components/Player.tsx +14 -5
- package/src/components/UploadConfiguration.tsx +190 -30
- package/src/components/Uploader.tsx +1 -1
- package/src/components/documentPreview/PaneItemPreview.tsx +8 -8
- package/src/hooks/useMuxPolling.ts +20 -4
- package/src/sanity-ui.d.ts +5 -0
- package/src/schema.ts +9 -3
- package/src/util/types.ts +47 -10
package/README.md
CHANGED
|
@@ -198,21 +198,65 @@ sanity documents delete secrets.mux
|
|
|
198
198
|
|
|
199
199
|
More information on signed URLs is available on Mux's [docs](https://docs.mux.com/docs/headless-cms-sanity#advanced-signed-urls)
|
|
200
200
|
|
|
201
|
-
###
|
|
201
|
+
### Static Renditions (downloadable videos or offline viewing)
|
|
202
202
|
|
|
203
|
-
To enable [static MP4 renditions](https://docs.mux.com/guides/video/enable-static-mp4-renditions), add `
|
|
203
|
+
To enable [static MP4 renditions](https://docs.mux.com/guides/video/enable-static-mp4-renditions), add `static_renditions` to your plugin configuration. This allows users to download videos for offline viewing.
|
|
204
|
+
|
|
205
|
+
#### Standard Mode (Recommended)
|
|
204
206
|
|
|
205
207
|
```js
|
|
206
208
|
import {muxInput} from 'sanity-plugin-mux-input'
|
|
207
209
|
|
|
208
210
|
export default defineConfig({
|
|
209
|
-
plugins: [
|
|
211
|
+
plugins: [
|
|
212
|
+
muxInput({
|
|
213
|
+
static_renditions: ['highest'], // Enables MP4 downloads at the highest quality (up to 4K)
|
|
214
|
+
// or
|
|
215
|
+
static_renditions: ['highest', 'audio-only'], // Also includes audio-only (M4A) downloads
|
|
216
|
+
}),
|
|
217
|
+
],
|
|
210
218
|
})
|
|
211
219
|
```
|
|
212
220
|
|
|
213
|
-
|
|
221
|
+
**Standard mode options:**
|
|
222
|
+
- `'highest'`: Produces an MP4 file with video resolution up to 4K (2160p)
|
|
223
|
+
- `'audio-only'`: Produces an M4A (audio-only MP4) file
|
|
224
|
+
|
|
225
|
+
#### Advanced Mode (Specific Resolutions)
|
|
226
|
+
|
|
227
|
+
For more control, you can specify exact resolutions:
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
import {muxInput} from 'sanity-plugin-mux-input'
|
|
231
|
+
|
|
232
|
+
export default defineConfig({
|
|
233
|
+
plugins: [
|
|
234
|
+
muxInput({
|
|
235
|
+
static_renditions: ['1080p', '720p', 'audio-only'],
|
|
236
|
+
}),
|
|
237
|
+
],
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Advanced mode options:**
|
|
242
|
+
- Specific resolutions: `'270p'`, `'360p'`, `'480p'`, `'540p'`, `'720p'`, `'1080p'`, `'1440p'`, `'2160p'`
|
|
243
|
+
- `'audio-only'`: M4A file
|
|
244
|
+
|
|
245
|
+
**Important notes:**
|
|
246
|
+
- You cannot mix `'highest'` with specific resolutions (e.g., `['highest', '1080p']` is invalid)
|
|
247
|
+
- Mux will not upscale videos - renditions requiring upscaling are automatically skipped
|
|
248
|
+
- When uploading new assets, editors can choose different rendition settings on a per-video basis
|
|
249
|
+
|
|
250
|
+
#### Backward Compatibility
|
|
251
|
+
|
|
252
|
+
The deprecated `mp4_support` field is still supported for backward compatibility:
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
// ⚠️ Deprecated - use static_renditions instead
|
|
256
|
+
muxInput({mp4_support: 'standard'}) // Equivalent to static_renditions: ['highest']
|
|
257
|
+
```
|
|
214
258
|
|
|
215
|
-
|
|
259
|
+
More information can be found on Mux's [documentation](https://docs.mux.com/guides/enable-static-mp4-renditions).
|
|
216
260
|
|
|
217
261
|
### Video resolution (max_resolution_tier)
|
|
218
262
|
|
package/dist/index.d.mts
CHANGED
|
@@ -30,12 +30,18 @@ declare interface MuxAsset {
|
|
|
30
30
|
static_renditions?: {
|
|
31
31
|
status: 'ready' | 'preparing' | 'disabled' | 'errored'
|
|
32
32
|
files: {
|
|
33
|
-
name:
|
|
33
|
+
name: string
|
|
34
34
|
ext: 'mp4' | 'm4a'
|
|
35
35
|
height: number
|
|
36
36
|
width: number
|
|
37
37
|
bitrate: number
|
|
38
|
-
filesize:
|
|
38
|
+
filesize: string
|
|
39
|
+
type: 'standard' | 'advanced'
|
|
40
|
+
status: 'ready' | 'preparing' | 'skipped' | 'errored'
|
|
41
|
+
resolution_tier?: string
|
|
42
|
+
resolution?: string
|
|
43
|
+
id: string
|
|
44
|
+
passthrough?: string
|
|
39
45
|
}[]
|
|
40
46
|
}
|
|
41
47
|
recording_times?: {
|
|
@@ -78,6 +84,19 @@ export declare const muxInput: Plugin_2<void | Partial<PluginConfig>>
|
|
|
78
84
|
|
|
79
85
|
declare interface MuxInputConfig {
|
|
80
86
|
/**
|
|
87
|
+
* Enable static renditions by default. Can be overwritten on a per-asset basis.
|
|
88
|
+
* Supports:
|
|
89
|
+
* - Standard mode: 'highest' (up to 4K MP4) and/or 'audio-only' (M4A)
|
|
90
|
+
* - Advanced mode: Specific resolutions ('270p', '360p', '480p', '540p', '720p', '1080p', '1440p', '2160p') and/or 'audio-only'
|
|
91
|
+
*
|
|
92
|
+
* **Important**: 'highest' cannot be mixed with specific resolutions. If both are provided, only 'highest' will be used.
|
|
93
|
+
*
|
|
94
|
+
* @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions}
|
|
95
|
+
* @defaultValue []
|
|
96
|
+
*/
|
|
97
|
+
static_renditions: StaticRenditionResolution[]
|
|
98
|
+
/**
|
|
99
|
+
* @deprecated Use `static_renditions` instead. This field is kept for backward compatibility.
|
|
81
100
|
* Enable static renditions by setting this to 'standard'. Can be overwritten on a per-asset basis.
|
|
82
101
|
* Requires `"video_quality": "plus"`
|
|
83
102
|
* @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions#why-enable-mp4-support}
|
|
@@ -195,6 +214,21 @@ declare interface PluginConfig extends MuxInputConfig {
|
|
|
195
214
|
allowedRolesForConfiguration: string[]
|
|
196
215
|
}
|
|
197
216
|
|
|
217
|
+
/**
|
|
218
|
+
* All static rendition resolution options supported by Mux
|
|
219
|
+
*/
|
|
220
|
+
declare type StaticRenditionResolution =
|
|
221
|
+
| 'highest'
|
|
222
|
+
| 'audio-only'
|
|
223
|
+
| '270p'
|
|
224
|
+
| '360p'
|
|
225
|
+
| '480p'
|
|
226
|
+
| '540p'
|
|
227
|
+
| '720p'
|
|
228
|
+
| '1080p'
|
|
229
|
+
| '1440p'
|
|
230
|
+
| '2160p'
|
|
231
|
+
|
|
198
232
|
declare const SUPPORTED_MUX_LANGUAGES_VALUES: (
|
|
199
233
|
| 'en'
|
|
200
234
|
| 'es'
|
package/dist/index.d.ts
CHANGED
|
@@ -30,12 +30,18 @@ declare interface MuxAsset {
|
|
|
30
30
|
static_renditions?: {
|
|
31
31
|
status: 'ready' | 'preparing' | 'disabled' | 'errored'
|
|
32
32
|
files: {
|
|
33
|
-
name:
|
|
33
|
+
name: string
|
|
34
34
|
ext: 'mp4' | 'm4a'
|
|
35
35
|
height: number
|
|
36
36
|
width: number
|
|
37
37
|
bitrate: number
|
|
38
|
-
filesize:
|
|
38
|
+
filesize: string
|
|
39
|
+
type: 'standard' | 'advanced'
|
|
40
|
+
status: 'ready' | 'preparing' | 'skipped' | 'errored'
|
|
41
|
+
resolution_tier?: string
|
|
42
|
+
resolution?: string
|
|
43
|
+
id: string
|
|
44
|
+
passthrough?: string
|
|
39
45
|
}[]
|
|
40
46
|
}
|
|
41
47
|
recording_times?: {
|
|
@@ -78,6 +84,19 @@ export declare const muxInput: Plugin_2<void | Partial<PluginConfig>>
|
|
|
78
84
|
|
|
79
85
|
declare interface MuxInputConfig {
|
|
80
86
|
/**
|
|
87
|
+
* Enable static renditions by default. Can be overwritten on a per-asset basis.
|
|
88
|
+
* Supports:
|
|
89
|
+
* - Standard mode: 'highest' (up to 4K MP4) and/or 'audio-only' (M4A)
|
|
90
|
+
* - Advanced mode: Specific resolutions ('270p', '360p', '480p', '540p', '720p', '1080p', '1440p', '2160p') and/or 'audio-only'
|
|
91
|
+
*
|
|
92
|
+
* **Important**: 'highest' cannot be mixed with specific resolutions. If both are provided, only 'highest' will be used.
|
|
93
|
+
*
|
|
94
|
+
* @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions}
|
|
95
|
+
* @defaultValue []
|
|
96
|
+
*/
|
|
97
|
+
static_renditions: StaticRenditionResolution[]
|
|
98
|
+
/**
|
|
99
|
+
* @deprecated Use `static_renditions` instead. This field is kept for backward compatibility.
|
|
81
100
|
* Enable static renditions by setting this to 'standard'. Can be overwritten on a per-asset basis.
|
|
82
101
|
* Requires `"video_quality": "plus"`
|
|
83
102
|
* @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions#why-enable-mp4-support}
|
|
@@ -195,6 +214,21 @@ declare interface PluginConfig extends MuxInputConfig {
|
|
|
195
214
|
allowedRolesForConfiguration: string[]
|
|
196
215
|
}
|
|
197
216
|
|
|
217
|
+
/**
|
|
218
|
+
* All static rendition resolution options supported by Mux
|
|
219
|
+
*/
|
|
220
|
+
declare type StaticRenditionResolution =
|
|
221
|
+
| 'highest'
|
|
222
|
+
| 'audio-only'
|
|
223
|
+
| '270p'
|
|
224
|
+
| '360p'
|
|
225
|
+
| '480p'
|
|
226
|
+
| '540p'
|
|
227
|
+
| '720p'
|
|
228
|
+
| '1080p'
|
|
229
|
+
| '1440p'
|
|
230
|
+
| '2160p'
|
|
231
|
+
|
|
198
232
|
declare const SUPPORTED_MUX_LANGUAGES_VALUES: (
|
|
199
233
|
| 'en'
|
|
200
234
|
| 'es'
|
package/dist/index.js
CHANGED
|
@@ -1527,7 +1527,7 @@ function VideoPlayer({
|
|
|
1527
1527
|
crossOrigin: "anonymous",
|
|
1528
1528
|
metadata: {
|
|
1529
1529
|
player_name: "Sanity Admin Dashboard",
|
|
1530
|
-
player_version: "2.
|
|
1530
|
+
player_version: "2.12.0",
|
|
1531
1531
|
page_type: "Preview Player"
|
|
1532
1532
|
},
|
|
1533
1533
|
audio: isAudio,
|
|
@@ -1618,21 +1618,21 @@ function PublishedStatus(props) {
|
|
|
1618
1618
|
}
|
|
1619
1619
|
function PaneItemPreview(props) {
|
|
1620
1620
|
const { icon, layout, presence, schemaType, value } = props, title = sanity.isRecord(value.title) && React.isValidElement(value.title) || isString__default.default(value.title) || isNumber__default.default(value.title) ? value.title : null, observable = React.useMemo(
|
|
1621
|
-
() => sanity.getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id
|
|
1622
|
-
[props.documentPreviewStore, schemaType,
|
|
1623
|
-
), {
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1621
|
+
() => sanity.getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id),
|
|
1622
|
+
[props.documentPreviewStore, schemaType, value._id]
|
|
1623
|
+
), { snapshot, original, isLoading } = reactRx.useObservable(observable, {
|
|
1624
|
+
isLoading: !0,
|
|
1625
|
+
snapshot: null,
|
|
1626
|
+
original: null
|
|
1627
1627
|
}), status = isLoading ? null : /* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 4, children: [
|
|
1628
1628
|
presence && presence.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(sanity.DocumentPreviewPresence, { presence }),
|
|
1629
|
-
/* @__PURE__ */ jsxRuntime.jsx(PublishedStatus, { document:
|
|
1630
|
-
/* @__PURE__ */ jsxRuntime.jsx(DraftStatus, { document:
|
|
1629
|
+
/* @__PURE__ */ jsxRuntime.jsx(PublishedStatus, { document: original }),
|
|
1630
|
+
/* @__PURE__ */ jsxRuntime.jsx(DraftStatus, { document: snapshot })
|
|
1631
1631
|
] });
|
|
1632
1632
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1633
1633
|
sanity.SanityDefaultPreview,
|
|
1634
1634
|
{
|
|
1635
|
-
...sanity.getPreviewValueWithFallback({
|
|
1635
|
+
...sanity.getPreviewValueWithFallback({ snapshot, original, fallback: { title } }),
|
|
1636
1636
|
isPlaceholder: isLoading,
|
|
1637
1637
|
icon,
|
|
1638
1638
|
layout,
|
|
@@ -2437,9 +2437,14 @@ const useAccessControl = (config) => {
|
|
|
2437
2437
|
sanity.isReference(asset) ? asset._ref : "",
|
|
2438
2438
|
path
|
|
2439
2439
|
), useMuxPolling = (asset) => {
|
|
2440
|
-
const client = useClient(), projectId = sanity.useProjectId(), dataset = sanity.useDataset(),
|
|
2441
|
-
|
|
2442
|
-
|
|
2440
|
+
const client = useClient(), projectId = sanity.useProjectId(), dataset = sanity.useDataset(), isPreparingStaticRenditions = React.useMemo(() => {
|
|
2441
|
+
if (asset?.data?.static_renditions?.status && asset?.data?.static_renditions?.status !== "disabled")
|
|
2442
|
+
return !1;
|
|
2443
|
+
const files = asset?.data?.static_renditions?.files;
|
|
2444
|
+
return !files || files.length === 0 ? !1 : files.some((file) => file.status === "preparing");
|
|
2445
|
+
}, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files]), shouldFetch = React.useMemo(
|
|
2446
|
+
() => !!asset?.assetId && (asset?.status === "preparing" || isPreparingStaticRenditions),
|
|
2447
|
+
[asset?.assetId, asset?.status, isPreparingStaticRenditions]
|
|
2443
2448
|
);
|
|
2444
2449
|
return useSWR__default.default(
|
|
2445
2450
|
shouldFetch ? `/${projectId}/addons/mux/assets/${dataset}/data/${asset?.assetId}` : null,
|
|
@@ -2454,7 +2459,7 @@ const useAccessControl = (config) => {
|
|
|
2454
2459
|
{ refreshInterval: 2e3, refreshWhenHidden: !0, dedupingInterval: 1e3 }
|
|
2455
2460
|
);
|
|
2456
2461
|
};
|
|
2457
|
-
var c = function(r) {
|
|
2462
|
+
var c = (function(r) {
|
|
2458
2463
|
var t, e;
|
|
2459
2464
|
function n(t2) {
|
|
2460
2465
|
var e2;
|
|
@@ -2470,7 +2475,7 @@ var c = function(r) {
|
|
|
2470
2475
|
var r2 = this.state, t2 = this.props, e2 = t2.render, n2 = t2.children, o2 = t2.renderError;
|
|
2471
2476
|
return r2.hasError ? o2 ? o2({ error: r2.error }) : null : e2 ? e2() : n2 || null;
|
|
2472
2477
|
}, n;
|
|
2473
|
-
}(React.PureComponent), u = function(r, t) {
|
|
2478
|
+
})(React.PureComponent), u = function(r, t) {
|
|
2474
2479
|
switch (t.type) {
|
|
2475
2480
|
case "catch":
|
|
2476
2481
|
return { didCatch: !0, error: t.error };
|
|
@@ -2746,13 +2751,14 @@ function testUrl(url) {
|
|
|
2746
2751
|
const error = new Error("Invalid URL");
|
|
2747
2752
|
if (typeof url != "string")
|
|
2748
2753
|
return rxjs.throwError(error);
|
|
2754
|
+
const trimmedUrl = url.trim();
|
|
2749
2755
|
let parsed;
|
|
2750
2756
|
try {
|
|
2751
|
-
parsed = new URL(
|
|
2757
|
+
parsed = new URL(trimmedUrl);
|
|
2752
2758
|
} catch {
|
|
2753
2759
|
return rxjs.throwError(error);
|
|
2754
2760
|
}
|
|
2755
|
-
return parsed && !parsed.protocol.match(/http:|https:/) ? rxjs.throwError(error) : rxjs.of(
|
|
2761
|
+
return parsed && !parsed.protocol.match(/http:|https:/) ? rxjs.throwError(error) : rxjs.of(trimmedUrl);
|
|
2756
2762
|
}
|
|
2757
2763
|
function optionsFromFile(opts, file) {
|
|
2758
2764
|
if (!(typeof window > "u" || !(file instanceof window.File)))
|
|
@@ -2927,7 +2933,12 @@ const TopControls = styledComponents.styled.div`
|
|
|
2927
2933
|
) : null
|
|
2928
2934
|
] }) });
|
|
2929
2935
|
}, Player = ({ asset, buttons, readOnly, onChange }) => {
|
|
2930
|
-
const isLoading = React.useMemo(() => asset?.status === "preparing" ? "Preparing the video" : asset?.status === "waiting_for_upload" ? "Waiting for upload to start" : asset?.status === "waiting" ? "Processing upload" : !(asset?.status === "ready" || typeof asset?.status > "u"), [asset]), isPreparingStaticRenditions = React.useMemo(() =>
|
|
2936
|
+
const isLoading = React.useMemo(() => asset?.status === "preparing" ? "Preparing the video" : asset?.status === "waiting_for_upload" ? "Waiting for upload to start" : asset?.status === "waiting" ? "Processing upload" : !(asset?.status === "ready" || typeof asset?.status > "u"), [asset]), isPreparingStaticRenditions = React.useMemo(() => {
|
|
2937
|
+
if (asset?.data?.static_renditions?.status && asset?.data?.static_renditions?.status !== "disabled")
|
|
2938
|
+
return !1;
|
|
2939
|
+
const files = asset?.data?.static_renditions?.files;
|
|
2940
|
+
return !files || files.length === 0 ? !1 : files.some((file) => file.status === "preparing");
|
|
2941
|
+
}, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files]), playRef = React.useRef(null), muteRef = React.useRef(null), handleCancelUpload = useCancelUpload(asset, onChange);
|
|
2931
2942
|
return React.useEffect(() => {
|
|
2932
2943
|
const style = document.createElement("style");
|
|
2933
2944
|
style.innerHTML = "button svg { vertical-align: middle; }", playRef.current?.shadowRoot && playRef.current.shadowRoot.appendChild(style), muteRef?.current?.shadowRoot && muteRef.current.shadowRoot.appendChild(style.cloneNode(!0));
|
|
@@ -3348,7 +3359,20 @@ const VIDEO_QUALITY_LEVELS = [
|
|
|
3348
3359
|
{ value: "1080p", label: "1080p" },
|
|
3349
3360
|
{ value: "1440p", label: "1440p (2k)" },
|
|
3350
3361
|
{ value: "2160p", label: "2160p (4k)" }
|
|
3362
|
+
], ADVANCED_RESOLUTIONS = [
|
|
3363
|
+
{ value: "270p", label: "270p" },
|
|
3364
|
+
{ value: "360p", label: "360p" },
|
|
3365
|
+
{ value: "480p", label: "480p" },
|
|
3366
|
+
{ value: "540p", label: "540p" },
|
|
3367
|
+
{ value: "720p", label: "720p" },
|
|
3368
|
+
{ value: "1080p", label: "1080p" },
|
|
3369
|
+
{ value: "1440p", label: "1440p" },
|
|
3370
|
+
{ value: "2160p", label: "2160p" }
|
|
3351
3371
|
];
|
|
3372
|
+
function sanitizeStaticRenditions(renditions) {
|
|
3373
|
+
const hasHighest = renditions.includes("highest"), hasSpecificResolutions = renditions.some((r) => r !== "highest" && r !== "audio-only");
|
|
3374
|
+
return hasHighest && hasSpecificResolutions ? renditions.filter((r) => r === "highest" || r === "audio-only") : renditions;
|
|
3375
|
+
}
|
|
3352
3376
|
function UploadConfiguration({
|
|
3353
3377
|
stagedUpload,
|
|
3354
3378
|
secrets,
|
|
@@ -3371,18 +3395,18 @@ function UploadConfiguration({
|
|
|
3371
3395
|
case "video_quality":
|
|
3372
3396
|
return action.value === "basic" ? Object.assign({}, prev, {
|
|
3373
3397
|
video_quality: action.value,
|
|
3374
|
-
|
|
3398
|
+
static_renditions: [],
|
|
3375
3399
|
max_resolution_tier: "1080p",
|
|
3376
3400
|
text_tracks: prev.text_tracks?.filter(({ type }) => type !== "autogenerated"),
|
|
3377
3401
|
public_policy: !0,
|
|
3378
3402
|
signed_policy: !1
|
|
3379
3403
|
}) : Object.assign({}, prev, {
|
|
3380
3404
|
video_quality: action.value,
|
|
3381
|
-
|
|
3405
|
+
static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),
|
|
3382
3406
|
max_resolution_tier: pluginConfig.max_resolution_tier,
|
|
3383
3407
|
text_tracks: [...autoTextTracks, ...prev.text_tracks || []]
|
|
3384
3408
|
});
|
|
3385
|
-
case "
|
|
3409
|
+
case "static_renditions":
|
|
3386
3410
|
case "max_resolution_tier":
|
|
3387
3411
|
case "normalize_audio":
|
|
3388
3412
|
case "signed_policy":
|
|
@@ -3421,13 +3445,34 @@ function UploadConfiguration({
|
|
|
3421
3445
|
{
|
|
3422
3446
|
video_quality: pluginConfig.video_quality,
|
|
3423
3447
|
max_resolution_tier: pluginConfig.max_resolution_tier,
|
|
3424
|
-
|
|
3448
|
+
static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),
|
|
3425
3449
|
signed_policy: secrets.enableSignedUrls && pluginConfig.defaultSigned,
|
|
3426
3450
|
public_policy: pluginConfig.defaultPublic,
|
|
3427
3451
|
normalize_audio: pluginConfig.normalize_audio,
|
|
3428
3452
|
text_tracks: autoTextTracks
|
|
3429
3453
|
}
|
|
3430
|
-
),
|
|
3454
|
+
), isAdvancedMode = React.useMemo(() => config.static_renditions.filter(
|
|
3455
|
+
(r) => r !== "highest" && r !== "audio-only"
|
|
3456
|
+
).length > 0, [config.static_renditions]), [renditionMode, setRenditionMode] = React.useState(
|
|
3457
|
+
isAdvancedMode ? "advanced" : "standard"
|
|
3458
|
+
), toggleRendition = (rendition) => {
|
|
3459
|
+
const current = config.static_renditions, hasRendition = current.includes(rendition);
|
|
3460
|
+
dispatch(hasRendition ? {
|
|
3461
|
+
action: "static_renditions",
|
|
3462
|
+
value: current.filter((r) => r !== rendition)
|
|
3463
|
+
} : {
|
|
3464
|
+
action: "static_renditions",
|
|
3465
|
+
value: [...current, rendition]
|
|
3466
|
+
});
|
|
3467
|
+
}, handleModeChange = (mode) => {
|
|
3468
|
+
setRenditionMode(mode), dispatch(mode === "standard" ? {
|
|
3469
|
+
action: "static_renditions",
|
|
3470
|
+
value: config.static_renditions.filter((r) => r === "highest" || r === "audio-only")
|
|
3471
|
+
} : {
|
|
3472
|
+
action: "static_renditions",
|
|
3473
|
+
value: config.static_renditions.filter((r) => r !== "highest")
|
|
3474
|
+
});
|
|
3475
|
+
}, { disableTextTrackConfig, disableUploadConfig } = pluginConfig, skipConfig = disableTextTrackConfig && disableUploadConfig;
|
|
3431
3476
|
if (React.useEffect(() => {
|
|
3432
3477
|
skipConfig && startUpload(formatUploadConfig(config));
|
|
3433
3478
|
}, []), skipConfig) return null;
|
|
@@ -3542,25 +3587,101 @@ function UploadConfiguration({
|
|
|
3542
3587
|
}) })
|
|
3543
3588
|
}
|
|
3544
3589
|
),
|
|
3545
|
-
!basicConfig && /* @__PURE__ */ jsxRuntime.jsx(sanity.FormField, { title: "Additional Configuration", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space:
|
|
3590
|
+
!basicConfig && /* @__PURE__ */ jsxRuntime.jsx(sanity.FormField, { title: "Additional Configuration", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3546
3591
|
/* @__PURE__ */ jsxRuntime.jsx(PlaybackPolicy, { id, config, secrets, dispatch }),
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3592
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 3, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3593
|
+
sanity.FormField,
|
|
3594
|
+
{
|
|
3595
|
+
title: "Static Renditions",
|
|
3596
|
+
description: "Generate downloadable MP4 or M4A files. Note: Mux will not upscale to produce MP4 renditions - renditions that would cause upscaling are skipped.",
|
|
3597
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3598
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 3, children: [
|
|
3599
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, children: [
|
|
3600
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3601
|
+
ui.Radio,
|
|
3602
|
+
{
|
|
3603
|
+
checked: renditionMode === "standard",
|
|
3604
|
+
name: "rendition-mode",
|
|
3605
|
+
onChange: () => handleModeChange("standard"),
|
|
3606
|
+
value: "standard",
|
|
3607
|
+
id: `${id}--mode-standard`
|
|
3608
|
+
}
|
|
3609
|
+
),
|
|
3610
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: `${id}--mode-standard`, children: "Standard" })
|
|
3611
|
+
] }),
|
|
3612
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, children: [
|
|
3613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3614
|
+
ui.Radio,
|
|
3615
|
+
{
|
|
3616
|
+
checked: renditionMode === "advanced",
|
|
3617
|
+
name: "rendition-mode",
|
|
3618
|
+
onChange: () => handleModeChange("advanced"),
|
|
3619
|
+
value: "advanced",
|
|
3620
|
+
id: `${id}--mode-advanced`
|
|
3621
|
+
}
|
|
3622
|
+
),
|
|
3623
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: `${id}--mode-advanced`, children: "Advanced" })
|
|
3624
|
+
] })
|
|
3625
|
+
] }),
|
|
3626
|
+
renditionMode === "standard" && /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3627
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, padding: [0, 2], children: [
|
|
3628
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3629
|
+
ui.Checkbox,
|
|
3630
|
+
{
|
|
3631
|
+
id: `${id}--highest`,
|
|
3632
|
+
style: { display: "block" },
|
|
3633
|
+
checked: config.static_renditions.includes("highest"),
|
|
3634
|
+
onChange: () => toggleRendition("highest")
|
|
3635
|
+
}
|
|
3636
|
+
),
|
|
3637
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: `${id}--highest`, children: "Highest Resolution (up to 4K)" })
|
|
3638
|
+
] }),
|
|
3639
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, padding: [0, 2], children: [
|
|
3640
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3641
|
+
ui.Checkbox,
|
|
3642
|
+
{
|
|
3643
|
+
id: `${id}--audio-only-standard`,
|
|
3644
|
+
style: { display: "block" },
|
|
3645
|
+
checked: config.static_renditions.includes("audio-only"),
|
|
3646
|
+
onChange: () => toggleRendition("audio-only")
|
|
3647
|
+
}
|
|
3648
|
+
),
|
|
3649
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: `${id}--audio-only-standard`, children: "Audio Only (M4A)" })
|
|
3650
|
+
] })
|
|
3651
|
+
] }),
|
|
3652
|
+
renditionMode === "advanced" && /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3653
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 1, muted: !0, children: "Select specific resolutions:" }),
|
|
3654
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { gap: 2, wrap: "wrap", children: ADVANCED_RESOLUTIONS.map(({ value, label }) => {
|
|
3655
|
+
const inputId = `${id}--resolution-${value}`;
|
|
3656
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, children: [
|
|
3657
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3658
|
+
ui.Checkbox,
|
|
3659
|
+
{
|
|
3660
|
+
id: inputId,
|
|
3661
|
+
style: { display: "block" },
|
|
3662
|
+
checked: config.static_renditions.includes(value),
|
|
3663
|
+
onChange: () => toggleRendition(value)
|
|
3664
|
+
}
|
|
3665
|
+
),
|
|
3666
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: inputId, size: 1, children: label })
|
|
3667
|
+
] }, value);
|
|
3668
|
+
}) }),
|
|
3669
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", gap: 2, padding: [2, 2, 0, 2], children: [
|
|
3670
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3671
|
+
ui.Checkbox,
|
|
3672
|
+
{
|
|
3673
|
+
id: `${id}--audio-only-advanced`,
|
|
3674
|
+
style: { display: "block" },
|
|
3675
|
+
checked: config.static_renditions.includes("audio-only"),
|
|
3676
|
+
onChange: () => toggleRendition("audio-only")
|
|
3677
|
+
}
|
|
3678
|
+
),
|
|
3679
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "label", htmlFor: `${id}--audio-only-advanced`, children: "Audio Only (M4A)" })
|
|
3680
|
+
] })
|
|
3681
|
+
] })
|
|
3682
|
+
] })
|
|
3683
|
+
}
|
|
3684
|
+
) })
|
|
3564
3685
|
] }) })
|
|
3565
3686
|
] }),
|
|
3566
3687
|
!disableTextTrackConfig && !basicConfig && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3612,7 +3733,7 @@ function formatUploadConfig(config) {
|
|
|
3612
3733
|
[]
|
|
3613
3734
|
)
|
|
3614
3735
|
],
|
|
3615
|
-
|
|
3736
|
+
static_renditions: config.static_renditions.length > 0 ? config.static_renditions.map((resolution) => ({ resolution })) : void 0,
|
|
3616
3737
|
playback_policy: setPlaybackPolicy(config),
|
|
3617
3738
|
max_resolution_tier: config.max_resolution_tier,
|
|
3618
3739
|
video_quality: config.video_quality,
|
|
@@ -3790,7 +3911,7 @@ function Uploader(props) {
|
|
|
3790
3911
|
const events$ = new rxjs.Subject();
|
|
3791
3912
|
return {
|
|
3792
3913
|
observable: events$.asObservable(),
|
|
3793
|
-
handleClick: (event) => events$.next(event)
|
|
3914
|
+
handleClick: ((event) => events$.next(event))
|
|
3794
3915
|
};
|
|
3795
3916
|
})()
|
|
3796
3917
|
).current, uploadRef = React.useRef(null), uploadingDocumentId = React.useRef(null), [state, dispatch] = React.useReducer(
|
|
@@ -3801,7 +3922,7 @@ function Uploader(props) {
|
|
|
3801
3922
|
case "commitUpload":
|
|
3802
3923
|
return Object.assign({}, prev, { uploadStatus: { progress: 0 } });
|
|
3803
3924
|
case "progressInfo": {
|
|
3804
|
-
const { ...payload } = action;
|
|
3925
|
+
const { type, action: _, ...payload } = action;
|
|
3805
3926
|
return Object.assign({}, prev, {
|
|
3806
3927
|
uploadStatus: {
|
|
3807
3928
|
...prev.uploadStatus,
|
|
@@ -3909,7 +4030,7 @@ function Uploader(props) {
|
|
|
3909
4030
|
});
|
|
3910
4031
|
}, handlePaste = (event) => {
|
|
3911
4032
|
event.preventDefault(), event.stopPropagation();
|
|
3912
|
-
const url = (event.clipboardData || window.clipboardData).getData("text");
|
|
4033
|
+
const url = (event.clipboardData || window.clipboardData).getData("text")?.trim();
|
|
3913
4034
|
if (!isValidUrl(url)) {
|
|
3914
4035
|
toast.push({ status: "error", title: "Invalid URL for Mux video input." });
|
|
3915
4036
|
return;
|
|
@@ -4115,12 +4236,18 @@ const muxVideoSchema = {
|
|
|
4115
4236
|
name: "mux.staticRenditionFile",
|
|
4116
4237
|
type: "object",
|
|
4117
4238
|
fields: [
|
|
4118
|
-
{ type: "string", name: "ext" },
|
|
4119
4239
|
{ type: "string", name: "name" },
|
|
4240
|
+
{ type: "string", name: "ext" },
|
|
4241
|
+
{ type: "number", name: "height" },
|
|
4120
4242
|
{ type: "number", name: "width" },
|
|
4121
4243
|
{ type: "number", name: "bitrate" },
|
|
4122
|
-
{ type: "
|
|
4123
|
-
{ type: "
|
|
4244
|
+
{ type: "string", name: "filesize" },
|
|
4245
|
+
{ type: "string", name: "type" },
|
|
4246
|
+
{ type: "string", name: "status" },
|
|
4247
|
+
{ type: "string", name: "resolution_tier" },
|
|
4248
|
+
{ type: "string", name: "resolution" },
|
|
4249
|
+
{ type: "string", name: "id" },
|
|
4250
|
+
{ type: "string", name: "passthrough" }
|
|
4124
4251
|
]
|
|
4125
4252
|
}, muxStaticRenditions = {
|
|
4126
4253
|
name: "mux.staticRenditions",
|
|
@@ -4251,6 +4378,7 @@ const muxVideoSchema = {
|
|
|
4251
4378
|
muxAssetData,
|
|
4252
4379
|
muxVideoAsset
|
|
4253
4380
|
], defaultConfig = {
|
|
4381
|
+
static_renditions: [],
|
|
4254
4382
|
mp4_support: "none",
|
|
4255
4383
|
video_quality: "plus",
|
|
4256
4384
|
max_resolution_tier: "1080p",
|
|
@@ -4259,12 +4387,20 @@ const muxVideoSchema = {
|
|
|
4259
4387
|
defaultSigned: !1,
|
|
4260
4388
|
tool: DEFAULT_TOOL_CONFIG,
|
|
4261
4389
|
allowedRolesForConfiguration: []
|
|
4262
|
-
}
|
|
4390
|
+
};
|
|
4391
|
+
function convertLegacyConfig(config) {
|
|
4392
|
+
return config.static_renditions && config.static_renditions.length > 0 ? { static_renditions: config.static_renditions } : config.mp4_support === "standard" ? { static_renditions: ["highest"] } : { static_renditions: [] };
|
|
4393
|
+
}
|
|
4394
|
+
const muxInput = sanity.definePlugin((userConfig) => {
|
|
4263
4395
|
if (typeof userConfig == "object" && "encoding_tier" in userConfig) {
|
|
4264
4396
|
const deprecated_encoding_tier = userConfig.encoding_tier;
|
|
4265
4397
|
userConfig.video_quality || (deprecated_encoding_tier === "baseline" && (userConfig.video_quality = "basic"), deprecated_encoding_tier === "smart" && (userConfig.video_quality = "plus"));
|
|
4266
4398
|
}
|
|
4267
|
-
const config = {
|
|
4399
|
+
const config = {
|
|
4400
|
+
...defaultConfig,
|
|
4401
|
+
...userConfig || {},
|
|
4402
|
+
...convertLegacyConfig(userConfig || {})
|
|
4403
|
+
};
|
|
4268
4404
|
return {
|
|
4269
4405
|
name: "mux-input",
|
|
4270
4406
|
schema: {
|