diff --git a/README.md b/README.md
index 782e4fba..ea2bd544 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,18 @@ To enable [signed urls](https://docs.mux.com/docs/security-signed-urls) with con
More information for this feature of the plugin can be found on Mux's [documentation](https://docs.mux.com/docs/headless-cms-sanity#advanced-signed-urls)
+# Enabling MP4 support
+
+To enable [static MP4 renditions](https://docs.mux.com/guides/video/enable-static-mp4-renditions), create or open the config file found in `config/mux-input.json` in your studio folder. This file is automatically created the first time the studio starts after adding the plugin.
+
+```
+{
+ "mp4_support": "standard"
+}
+```
+
+Currently `mp4_support` is the only supported MUX option and this supports a value of either `standard` or `none` (the default).
+
# Contributing
Issues are actively monitored and PRs are welcome. When developing this plugin the easiest setup is:
diff --git a/config.dist.json b/config.dist.json
new file mode 100644
index 00000000..9859cb7b
--- /dev/null
+++ b/config.dist.json
@@ -0,0 +1,3 @@
+{
+ "mp4_support": "none"
+}
diff --git a/src/actions/upload.js b/src/actions/upload.js
index fe6ae5b8..6b98aebb 100644
--- a/src/actions/upload.js
+++ b/src/actions/upload.js
@@ -1,5 +1,6 @@
/* eslint-disable camelcase */
import {uuid as generateUuid} from '@sanity/uuid'
+import config from '../config'
import {isString} from 'lodash'
import {concat, defer, from, of, throwError} from 'rxjs'
import {catchError, mergeMap, mergeMapTo, switchMap} from 'rxjs/operators'
@@ -31,11 +32,13 @@ export function uploadUrl(url, options = {}) {
const muxBody = {
input: validUrl,
playback_policy: [enableSignedUrls ? 'signed' : 'public'],
+ mp4_support: config.mp4_support,
}
const query = {
muxBody: JSON.stringify(muxBody),
filename: validUrl.split('/').slice(-1)[0],
}
+
const dataset = client.clientConfig.dataset
return defer(() =>
client.observable.request({
@@ -53,6 +56,7 @@ export function uploadUrl(url, options = {}) {
const asset =
(result && result.results && result.results[0] && result.results[0].document) ||
null
+
if (!asset) {
return throwError(new Error('No asset document returned'))
}
@@ -79,12 +83,10 @@ export function uploadFile(file, options = {}) {
const uuid = generateUuid()
const {enableSignedUrls} = options
const body = {
+ mp4_support: config.mp4_support,
playback_policy: [enableSignedUrls ? 'signed' : 'public'],
- // TODO: These parameters were enabled by Sanity, but we are not using them yet
- // mp4_support: false (default),
- // normalize_audio: false (default),
- // master_access: false (default),
}
+
return concat(
of({type: 'uuid', uuid}),
defer(() =>
@@ -178,6 +180,7 @@ async function updateAssetDocumentFromUpload(uuid) {
} catch (err) {
return Promise.reject(err)
}
+
const doc = {
_id: uuid,
_type: 'mux.videoAsset',
diff --git a/src/components/Input.js b/src/components/Input.js
index 1ac51f4c..651ef47c 100644
--- a/src/components/Input.js
+++ b/src/components/Input.js
@@ -33,6 +33,7 @@ import SelectAsset from './SelectAsset'
import Setup from './Setup'
import Uploader from './Uploader'
import Video from './Video'
+import config from '../config'
const NOOP = () => {
/* intentional noop */
@@ -177,12 +178,31 @@ export default withDocument(
})
})
}
- if (assetDocument && assetDocument.status === 'preparing') {
+ // Poll MUX if it's preparing the main document or its own static renditions
+ if (
+ assetDocument?.status === 'preparing' ||
+ assetDocument?.data?.static_renditions?.status === 'preparing'
+ ) {
this.pollMux()
}
+ // If MP4 support is enabled: MUX will prepare static_renditions only _after_ an asset
+ // has been successfully uploaded.
+ // A _ready_ asset doesn't mean static mp4s are generated and ready for use!
+ // In these cases, wait for `static_renditions.status === 'ready'` before clearing the poll interval.
if (assetDocument && assetDocument.status === 'ready') {
- clearInterval(this.pollInterval)
- this.pollInterval = null
+ switch (config.mp4_support) {
+ case 'standard':
+ if (assetDocument?.data?.static_renditions?.status === 'ready') {
+ clearInterval(this.pollInterval)
+ this.pollInterval = null
+ }
+ break
+ case 'none':
+ default:
+ clearInterval(this.pollInterval)
+ this.pollInterval = null
+ break
+ }
}
// eslint-disable-next-line camelcase
@@ -207,6 +227,8 @@ export default withDocument(
getAsset(assetDocument.assetId)
.then((response) => {
const props = response.data
+
+ // TODO: consider a deep comparison on `props` with asset data and only patch only if it's changed
client
.patch(assetDocument._id)
.set({
diff --git a/src/components/Video.js b/src/components/Video.js
index 1bdd5691..14267766 100644
--- a/src/components/Video.js
+++ b/src/components/Video.js
@@ -1,4 +1,4 @@
-import {Card, Stack, Text} from '@sanity/ui'
+import {Box, Card, Stack, Text} from '@sanity/ui'
import Hls from 'hls.js'
import 'media-chrome'
import Button from 'part:@sanity/components/buttons/default'
@@ -37,6 +37,7 @@ class MuxVideo extends Component {
isLoading: true,
error: null,
isDeletedOnMux: false,
+ isPreparingStaticRenditions: false,
secrets: null,
}
this.playRef = React.createRef()
@@ -46,6 +47,7 @@ class MuxVideo extends Component {
// eslint-disable-next-line complexity
static getDerivedStateFromProps(nextProps) {
let isLoading = true
+ let isPreparingStaticRenditions = false
const {assetDocument} = nextProps
if (assetDocument && assetDocument.status === 'preparing') {
@@ -63,7 +65,16 @@ class MuxVideo extends Component {
if (assetDocument && typeof assetDocument.status === 'undefined') {
isLoading = false
}
- return {isLoading}
+ if (assetDocument?.data?.static_renditions?.status === 'preparing') {
+ isPreparingStaticRenditions = true
+ }
+ if (assetDocument?.data?.static_renditions?.status === 'ready') {
+ isPreparingStaticRenditions = false
+ }
+ return {
+ isLoading,
+ isPreparingStaticRenditions,
+ }
}
componentDidMount() {
@@ -234,6 +245,7 @@ class MuxVideo extends Component {
)}
+
{showControls && (
@@ -252,6 +264,23 @@ class MuxVideo extends Component {
)}
+
+ {this.state.isPreparingStaticRenditions && (
+
+
+ MUX is preparing static renditions, please stand by
+
+
+ )}
)
}
diff --git a/src/config.js b/src/config.js
new file mode 100644
index 00000000..41af231e
--- /dev/null
+++ b/src/config.js
@@ -0,0 +1,6 @@
+/* eslint-disable camelcase */
+import config from 'config:mux-input'
+
+export default {
+ mp4_support: config?.mp4_support || 'none',
+}