sanity-plugin-mux-input 2.13.0 → 2.15.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 +25 -24
- package/dist/index.d.mts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +2176 -461
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2178 -463
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/_exports/index.ts +1 -0
- package/src/actions/assets.ts +75 -0
- package/src/actions/secrets.ts +6 -1
- package/src/actions/upload.ts +1 -1
- package/src/components/AddCaptionDialog.tsx +421 -0
- package/src/components/CaptionsDialog.tsx +23 -0
- package/src/components/ConfigureApi.tsx +51 -5
- package/src/components/EditCaptionDialog.tsx +508 -0
- package/src/components/InputBrowser.tsx +8 -2
- package/src/components/Onboard.tsx +2 -2
- package/src/components/PageSelector.tsx +54 -0
- package/src/components/Player.styled.tsx +7 -2
- package/src/components/PlayerActionsMenu.tsx +14 -6
- package/src/components/SelectAsset.tsx +9 -3
- package/src/components/StudioTool.tsx +2 -2
- package/src/components/TextTracksManager.tsx +781 -0
- package/src/components/UploadConfiguration.tsx +104 -343
- package/src/components/Uploader.styled.tsx +8 -15
- package/src/components/Uploader.tsx +25 -7
- package/src/components/VideoDetails/VideoDetails.tsx +43 -7
- package/src/components/VideoInBrowser.tsx +53 -6
- package/src/components/VideoPlayer.tsx +122 -47
- package/src/components/VideoThumbnail.tsx +84 -72
- package/src/components/VideosBrowser.tsx +15 -5
- package/src/components/uploadConfiguration/PlaybackPolicy.tsx +95 -6
- package/src/components/uploadConfiguration/PlaybackPolicyOption.tsx +26 -10
- package/src/components/uploadConfiguration/ResolutionTierSelector.tsx +71 -0
- package/src/components/uploadConfiguration/StaticRenditionSelector.tsx +179 -0
- package/src/context/DrmPlaybackWarningContext.tsx +93 -0
- package/src/hooks/useAccessControl.ts +1 -0
- package/src/hooks/useDialogState.ts +1 -1
- package/src/hooks/useFetchFileSize.ts +54 -0
- package/src/hooks/useMediaMetadata.ts +100 -0
- package/src/hooks/useSaveSecrets.ts +10 -3
- package/src/hooks/useSecretsDocumentValues.ts +9 -1
- package/src/hooks/useSecretsFormState.ts +6 -3
- package/src/util/asserters.ts +14 -0
- package/src/util/createUrlParamsObject.ts +7 -3
- package/src/util/generateJwt.ts +11 -2
- package/src/util/getPlaybackPolicy.ts +63 -4
- package/src/util/getStoryboardSrc.ts +7 -3
- package/src/util/getVideoMetadata.ts +4 -1
- package/src/util/getVideoSrc.ts +9 -9
- package/src/util/readSecrets.ts +3 -1
- package/src/util/textTracks.ts +222 -0
- package/src/util/tryWithSuspend.ts +22 -0
- package/src/util/types.ts +39 -6
- package/src/util/getPlaybackId.ts +0 -9
|
@@ -1,10 +1,69 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AdvancedPlaybackPolicy,
|
|
3
|
+
MuxPlaybackId,
|
|
4
|
+
PlaybackPolicy,
|
|
5
|
+
VideoAssetDocument,
|
|
6
|
+
} from './types'
|
|
7
|
+
|
|
8
|
+
/* - Returns the playback id of the asset based on the specified priority.
|
|
9
|
+
By default chooses the "strongest" policy
|
|
10
|
+
- Otherwise, returns the first playback id in the array.
|
|
11
|
+
*/
|
|
12
|
+
export function getPlaybackId(
|
|
13
|
+
asset: Pick<VideoAssetDocument, 'data'>,
|
|
14
|
+
priority: string[] = ['drm', 'signed', 'public']
|
|
15
|
+
): string {
|
|
16
|
+
try {
|
|
17
|
+
if (!asset) {
|
|
18
|
+
throw new TypeError('Tried to get playback Id with no asset')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const playbackIds = asset.data?.playback_ids
|
|
22
|
+
if (playbackIds && playbackIds.length > 0) {
|
|
23
|
+
for (const policy of priority) {
|
|
24
|
+
const match = playbackIds.find((entry) => entry.policy === policy)
|
|
25
|
+
if (match) {
|
|
26
|
+
return match.id
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return playbackIds[0].id
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
throw new TypeError('Missing playbackId')
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.error('Asset is missing a playbackId', {asset}, e)
|
|
36
|
+
throw e
|
|
37
|
+
}
|
|
38
|
+
}
|
|
2
39
|
|
|
3
40
|
export function getPlaybackPolicy(
|
|
4
41
|
asset: Pick<VideoAssetDocument, 'data' | 'playbackId'>
|
|
5
|
-
):
|
|
42
|
+
): MuxPlaybackId | undefined {
|
|
43
|
+
return (
|
|
44
|
+
asset.data?.playback_ids?.find(
|
|
45
|
+
(playbackId) => getPlaybackId(asset, ['drm', 'signed', 'public']) === playbackId.id
|
|
46
|
+
) ?? {id: '', policy: 'public'}
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function getPlaybackPolicyById(
|
|
51
|
+
asset: Pick<VideoAssetDocument, 'data'>,
|
|
52
|
+
playbackId: string
|
|
53
|
+
): MuxPlaybackId | undefined {
|
|
54
|
+
return asset.data?.playback_ids?.find((entry) => playbackId === entry.id)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function hasPlaybackPolicy(
|
|
58
|
+
data: Partial<{
|
|
59
|
+
playback_policy?: PlaybackPolicy[]
|
|
60
|
+
advanced_playback_policies: AdvancedPlaybackPolicy[]
|
|
61
|
+
}>,
|
|
62
|
+
policy: PlaybackPolicy
|
|
63
|
+
) {
|
|
6
64
|
return (
|
|
7
|
-
|
|
8
|
-
|
|
65
|
+
(data.advanced_playback_policies &&
|
|
66
|
+
data.advanced_playback_policies.find((p) => p.policy === policy)) ||
|
|
67
|
+
data.playback_policy?.find((p) => p === policy)
|
|
9
68
|
)
|
|
10
69
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {SanityClient} from 'sanity'
|
|
2
2
|
|
|
3
|
+
import {getPlaybackId} from '../util/getPlaybackPolicy'
|
|
3
4
|
import {generateJwt} from './generateJwt'
|
|
4
|
-
import {
|
|
5
|
-
import {getPlaybackPolicy} from './getPlaybackPolicy'
|
|
5
|
+
import {getPlaybackPolicyById} from './getPlaybackPolicy'
|
|
6
6
|
import type {MuxStoryboardUrl, VideoAssetDocument} from './types'
|
|
7
7
|
|
|
8
8
|
interface StoryboardSrcOptions {
|
|
@@ -10,11 +10,15 @@ interface StoryboardSrcOptions {
|
|
|
10
10
|
client: SanityClient
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
|
|
15
|
+
*/
|
|
13
16
|
export function getStoryboardSrc({asset, client}: StoryboardSrcOptions): MuxStoryboardUrl {
|
|
14
17
|
const playbackId = getPlaybackId(asset)
|
|
15
18
|
const searchParams = new URLSearchParams()
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
const playbackPolicy = getPlaybackPolicyById(asset, playbackId)?.policy
|
|
21
|
+
if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {
|
|
18
22
|
const token = generateJwt(client, playbackId, 's')
|
|
19
23
|
searchParams.set('token', token)
|
|
20
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {formatSeconds} from './formatSeconds'
|
|
2
|
-
import {VideoAssetDocument} from './types'
|
|
2
|
+
import type {MuxTextTrack, VideoAssetDocument} from './types'
|
|
3
3
|
|
|
4
4
|
export default function getVideoMetadata(doc: VideoAssetDocument) {
|
|
5
5
|
const id = doc.assetId || doc._id || ''
|
|
@@ -13,8 +13,11 @@ export default function getVideoMetadata(doc: VideoAssetDocument) {
|
|
|
13
13
|
playbackId: doc.playbackId,
|
|
14
14
|
createdAt: date,
|
|
15
15
|
duration: doc.data?.duration ? formatSeconds(doc.data?.duration) : undefined,
|
|
16
|
+
playback_ids: doc.data?.playback_ids,
|
|
16
17
|
aspect_ratio: doc.data?.aspect_ratio,
|
|
17
18
|
max_stored_resolution: doc.data?.max_stored_resolution,
|
|
18
19
|
max_stored_frame_rate: doc.data?.max_stored_frame_rate,
|
|
20
|
+
text_tracks:
|
|
21
|
+
doc.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || [],
|
|
19
22
|
}
|
|
20
23
|
}
|
package/src/util/getVideoSrc.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type {SanityClient} from 'sanity'
|
|
2
2
|
|
|
3
3
|
import {generateJwt} from './generateJwt'
|
|
4
|
-
import {
|
|
5
|
-
import {getPlaybackPolicy} from './getPlaybackPolicy'
|
|
6
|
-
import type {MuxVideoUrl, VideoAssetDocument} from './types'
|
|
4
|
+
import type {MuxPlaybackId, MuxVideoUrl} from './types'
|
|
7
5
|
|
|
8
6
|
interface VideoSrcOptions {
|
|
9
|
-
|
|
7
|
+
muxPlaybackId: MuxPlaybackId
|
|
10
8
|
client: SanityClient
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
/**
|
|
12
|
+
* May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
|
|
13
|
+
*/
|
|
14
|
+
export function getVideoSrc({client, muxPlaybackId}: VideoSrcOptions): MuxVideoUrl {
|
|
15
15
|
const searchParams = new URLSearchParams()
|
|
16
16
|
|
|
17
|
-
if (
|
|
18
|
-
const token = generateJwt(client,
|
|
17
|
+
if (muxPlaybackId.policy === 'signed' || muxPlaybackId.policy === 'drm') {
|
|
18
|
+
const token = generateJwt(client, muxPlaybackId.id, 'v')
|
|
19
19
|
searchParams.set('token', token)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
return `https://stream.mux.com/${
|
|
22
|
+
return `https://stream.mux.com/${muxPlaybackId.id}.m3u8?${searchParams}`
|
|
23
23
|
}
|
package/src/util/readSecrets.ts
CHANGED
|
@@ -21,7 +21,8 @@ export function readSecrets(client: SanityClient): Secrets {
|
|
|
21
21
|
secretKey,
|
|
22
22
|
enableSignedUrls,
|
|
23
23
|
signingKeyId,
|
|
24
|
-
signingKeyPrivate
|
|
24
|
+
signingKeyPrivate,
|
|
25
|
+
drmConfigId
|
|
25
26
|
}`,
|
|
26
27
|
{_id}
|
|
27
28
|
)
|
|
@@ -31,6 +32,7 @@ export function readSecrets(client: SanityClient): Secrets {
|
|
|
31
32
|
enableSignedUrls: Boolean(data?.enableSignedUrls) || false,
|
|
32
33
|
signingKeyId: data?.signingKeyId || null,
|
|
33
34
|
signingKeyPrivate: data?.signingKeyPrivate || null,
|
|
35
|
+
drmConfigId: data?.drmConfigId || null,
|
|
34
36
|
}
|
|
35
37
|
}, [cacheNs, _id, projectId, dataset])
|
|
36
38
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type {SanityClient} from '@sanity/client'
|
|
2
|
+
|
|
3
|
+
import {getAsset} from '../actions/assets'
|
|
4
|
+
import {generateJwt} from './generateJwt'
|
|
5
|
+
import {getPlaybackId} from './getPlaybackPolicy'
|
|
6
|
+
import {getPlaybackPolicy} from './getPlaybackPolicy'
|
|
7
|
+
import type {MuxTextTrack, VideoAssetDocument} from './types'
|
|
8
|
+
|
|
9
|
+
export function extractErrorMessage(
|
|
10
|
+
error: unknown,
|
|
11
|
+
defaultMessage = 'Failed to process request'
|
|
12
|
+
): string {
|
|
13
|
+
let message = ''
|
|
14
|
+
|
|
15
|
+
if (error && typeof error === 'object') {
|
|
16
|
+
const err = error as {response?: {body?: {message?: string}}; message?: string}
|
|
17
|
+
message = err.response?.body?.message || err.message || ''
|
|
18
|
+
} else if (typeof error === 'string') {
|
|
19
|
+
message = error
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!message) {
|
|
23
|
+
return defaultMessage
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const match = message.match(/\(([^)]+)\)/)
|
|
27
|
+
if (match && match[1]) {
|
|
28
|
+
return match[1]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (message.includes('responded with')) {
|
|
32
|
+
const parts = message.split('(')
|
|
33
|
+
if (parts.length > 1) {
|
|
34
|
+
return parts[parts.length - 1].replace(')', '').trim()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return message
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface PollTrackStatusOptions {
|
|
42
|
+
client: SanityClient
|
|
43
|
+
assetId: string
|
|
44
|
+
trackName: string
|
|
45
|
+
trackLanguageCode: string
|
|
46
|
+
maxAttempts?: number
|
|
47
|
+
onTrackFound?: (track: MuxTextTrack) => void
|
|
48
|
+
onTrackErrored?: (track: MuxTextTrack) => void
|
|
49
|
+
onTrackReady?: (track: MuxTextTrack) => void
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface PollTrackStatusResult {
|
|
53
|
+
track: MuxTextTrack | undefined
|
|
54
|
+
found: boolean
|
|
55
|
+
status: 'ready' | 'preparing' | 'errored' | 'not-found'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Polls Mux API to find and track the status of a newly added text track.
|
|
60
|
+
* The track may be in "preparing" state initially, then become "ready" or "errored".
|
|
61
|
+
*
|
|
62
|
+
* @param options - Configuration options for polling
|
|
63
|
+
* @returns Promise resolving to the poll result
|
|
64
|
+
*/
|
|
65
|
+
export async function pollTrackStatus(
|
|
66
|
+
options: PollTrackStatusOptions
|
|
67
|
+
): Promise<PollTrackStatusResult> {
|
|
68
|
+
const {
|
|
69
|
+
client,
|
|
70
|
+
assetId,
|
|
71
|
+
trackName,
|
|
72
|
+
trackLanguageCode,
|
|
73
|
+
maxAttempts = 10,
|
|
74
|
+
onTrackFound,
|
|
75
|
+
onTrackErrored,
|
|
76
|
+
onTrackReady,
|
|
77
|
+
} = options
|
|
78
|
+
|
|
79
|
+
const trimmedName = trackName.trim()
|
|
80
|
+
const trimmedLanguageCode = trackLanguageCode.trim()
|
|
81
|
+
let newTrack: MuxTextTrack | undefined
|
|
82
|
+
let attempts = 0
|
|
83
|
+
let trackFound = false
|
|
84
|
+
|
|
85
|
+
const findTrack = (textTracks: MuxTextTrack[]): MuxTextTrack | undefined => {
|
|
86
|
+
let foundTrack = textTracks.find(
|
|
87
|
+
(track) => track.name === trimmedName && track.language_code === trimmedLanguageCode
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if (!foundTrack) {
|
|
91
|
+
foundTrack = textTracks.find((track) => track.language_code === trimmedLanguageCode)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!foundTrack && textTracks.length > 0) {
|
|
95
|
+
foundTrack = textTracks[textTracks.length - 1]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return foundTrack
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
while (attempts < maxAttempts) {
|
|
102
|
+
try {
|
|
103
|
+
if (attempts > 0) {
|
|
104
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const assetData = await getAsset(client, assetId)
|
|
108
|
+
const textTracks =
|
|
109
|
+
assetData.data.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []
|
|
110
|
+
|
|
111
|
+
const foundTrack = findTrack(textTracks)
|
|
112
|
+
|
|
113
|
+
if (!foundTrack) {
|
|
114
|
+
attempts++
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
trackFound = true
|
|
119
|
+
newTrack = foundTrack
|
|
120
|
+
|
|
121
|
+
if (onTrackFound) {
|
|
122
|
+
onTrackFound(foundTrack)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (foundTrack.status === 'ready') {
|
|
126
|
+
if (onTrackReady) {
|
|
127
|
+
onTrackReady(foundTrack)
|
|
128
|
+
}
|
|
129
|
+
break
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (foundTrack.status === 'errored') {
|
|
133
|
+
if (onTrackErrored) {
|
|
134
|
+
onTrackErrored(foundTrack)
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
track: foundTrack,
|
|
138
|
+
found: true,
|
|
139
|
+
status: 'errored',
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error('Failed to fetch updated asset:', error)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
attempts++
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!newTrack || !trackFound) {
|
|
150
|
+
return {
|
|
151
|
+
track: undefined,
|
|
152
|
+
found: false,
|
|
153
|
+
status: 'not-found',
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (newTrack.status === 'preparing') {
|
|
158
|
+
return {
|
|
159
|
+
track: newTrack,
|
|
160
|
+
found: true,
|
|
161
|
+
status: 'preparing',
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
track: newTrack,
|
|
167
|
+
found: true,
|
|
168
|
+
status: 'ready',
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
|
|
174
|
+
*/
|
|
175
|
+
export async function downloadVttFile(
|
|
176
|
+
client: SanityClient,
|
|
177
|
+
asset: VideoAssetDocument,
|
|
178
|
+
track: MuxTextTrack
|
|
179
|
+
): Promise<void> {
|
|
180
|
+
if (!track.id) {
|
|
181
|
+
throw new Error('Track ID is missing')
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (track.status !== 'ready') {
|
|
185
|
+
throw new Error(`Track is not ready yet. Status: ${track.status}`)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!asset.assetId) {
|
|
189
|
+
throw new Error('Asset ID is required')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const playbackId = getPlaybackId(asset)
|
|
193
|
+
if (!playbackId) {
|
|
194
|
+
throw new Error('Playback ID is required')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const playbackPolicy = getPlaybackPolicy(asset)?.policy
|
|
198
|
+
|
|
199
|
+
let downloadUrl = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`
|
|
200
|
+
|
|
201
|
+
if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {
|
|
202
|
+
const token = generateJwt(client, playbackId, 'v')
|
|
203
|
+
downloadUrl += `?token=${token}`
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const response = await fetch(downloadUrl)
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
throw new Error(`Failed to download file: ${response.statusText}`)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const blob = await response.blob()
|
|
212
|
+
const blobUrl = URL.createObjectURL(blob)
|
|
213
|
+
|
|
214
|
+
const link = document.createElement('a')
|
|
215
|
+
link.href = blobUrl
|
|
216
|
+
link.download = `${asset.filename || 'captions'}-${track.language_code || 'en'}.vtt`
|
|
217
|
+
document.body.appendChild(link)
|
|
218
|
+
link.click()
|
|
219
|
+
document.body.removeChild(link)
|
|
220
|
+
|
|
221
|
+
URL.revokeObjectURL(blobUrl)
|
|
222
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When running `suspend()` from react-suspend a function may throw a Promise
|
|
3
|
+
* causing unexpected behavior when catching.
|
|
4
|
+
* @param block Your block of code that uses suspend
|
|
5
|
+
* @param onError (optional) How to handle a regular Error
|
|
6
|
+
* @returns Whatever is returned by the block if it succeeds, otherwise whatever is resolved by onError if defined
|
|
7
|
+
* @throws rethrows the caught Promise to comply with Suspense logic
|
|
8
|
+
*/
|
|
9
|
+
export function tryWithSuspend<T, E>(
|
|
10
|
+
block: () => T,
|
|
11
|
+
onError?: (error: Error) => E
|
|
12
|
+
): T | E | undefined {
|
|
13
|
+
try {
|
|
14
|
+
return block()
|
|
15
|
+
} catch (errorOrPromise) {
|
|
16
|
+
if (errorOrPromise instanceof Promise) {
|
|
17
|
+
// react-suspend will throw a Promise
|
|
18
|
+
throw errorOrPromise
|
|
19
|
+
}
|
|
20
|
+
return onError ? onError(errorOrPromise as Error) : undefined
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/util/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type MuxPlayerElement from '@mux/mux-player'
|
|
1
2
|
import type {ObjectInputProps, PreviewLayoutKey, PreviewProps, SchemaType} from 'sanity'
|
|
2
3
|
import type {PartialDeep} from 'type-fest'
|
|
3
|
-
import type MuxPlayerElement from '@mux/mux-player'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Standard static rendition options available for plugin configuration defaults
|
|
@@ -89,6 +89,13 @@ export interface MuxInputConfig {
|
|
|
89
89
|
*/
|
|
90
90
|
defaultPublic?: boolean
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Enables DRM Protection by default, if you configured your DRM Configuration Id.
|
|
94
|
+
* @see {@link https://www.mux.com/docs/guides/protect-videos-with-drm}
|
|
95
|
+
* @defaultValue true
|
|
96
|
+
*/
|
|
97
|
+
defaultDrm?: boolean
|
|
98
|
+
|
|
92
99
|
/**
|
|
93
100
|
* Auto-generate captions for these languages by default.
|
|
94
101
|
* Requires `"video_quality": "plus"`
|
|
@@ -124,6 +131,13 @@ export interface MuxInputConfig {
|
|
|
124
131
|
*/
|
|
125
132
|
disableTextTrackConfig?: boolean
|
|
126
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Whether or not to show the playback warning when trying to watch DRM content for the first time.
|
|
136
|
+
*
|
|
137
|
+
* @defaultValue false
|
|
138
|
+
*/
|
|
139
|
+
disableDrmPlaybackWarning?: boolean
|
|
140
|
+
|
|
127
141
|
/**
|
|
128
142
|
* The mime types that are accepted by the input.
|
|
129
143
|
*
|
|
@@ -266,6 +280,7 @@ export interface UploadConfig
|
|
|
266
280
|
text_tracks: UploadTextTrack[]
|
|
267
281
|
signed_policy: boolean
|
|
268
282
|
public_policy: boolean
|
|
283
|
+
drm_policy: boolean
|
|
269
284
|
}
|
|
270
285
|
|
|
271
286
|
/**
|
|
@@ -303,24 +318,33 @@ export interface MuxNewAssetSettings
|
|
|
303
318
|
name?: string
|
|
304
319
|
/** Indicates the track provides Subtitles for the Deaf or Hard-of-hearing (SDH). */
|
|
305
320
|
closed_captions?: boolean
|
|
306
|
-
/// @TODO Huhh?>?? Below
|
|
307
321
|
/** This optional parameter should be used tracks with type of text and text_type set to subtitles. */
|
|
308
322
|
passthrough?: string
|
|
309
323
|
}[]
|
|
310
324
|
|
|
311
325
|
/** An array of playback policy names that you want applied to this asset and available through playback_ids. */
|
|
312
|
-
playback_policy
|
|
326
|
+
playback_policy?: PlaybackPolicy[]
|
|
327
|
+
|
|
328
|
+
/** An array of playback policy objects that you want applied to this asset and available through playback_ids. advanced_playback_policies must be used instead of playback_policies when creating a DRM playback ID. */
|
|
329
|
+
advanced_playback_policies: AdvancedPlaybackPolicy[]
|
|
313
330
|
|
|
314
331
|
/** Arbitrary user-supplied metadata that will be included in the asset details and related webhooks. */
|
|
315
332
|
passthrough?: string
|
|
316
333
|
}
|
|
317
334
|
|
|
335
|
+
/** Used by advanced_playback_policies, allows to define DRM config. */
|
|
336
|
+
export type AdvancedPlaybackPolicy = {
|
|
337
|
+
policy: PlaybackPolicy
|
|
338
|
+
drm_configuration_id?: string
|
|
339
|
+
}
|
|
340
|
+
|
|
318
341
|
export interface Secrets {
|
|
319
342
|
token: string | null
|
|
320
343
|
secretKey: string | null
|
|
321
344
|
enableSignedUrls: boolean
|
|
322
345
|
signingKeyId: string | null
|
|
323
346
|
signingKeyPrivate: string | null
|
|
347
|
+
drmConfigId: string | null
|
|
324
348
|
}
|
|
325
349
|
|
|
326
350
|
// This narrowed type indicates that there may be assets that are signed, and we have the secrets to access them
|
|
@@ -367,7 +391,7 @@ export interface AssetThumbnailOptions {
|
|
|
367
391
|
asset: Pick<VideoAssetDocument, 'playbackId' | 'data' | 'thumbTime' | 'filename' | 'assetId'>
|
|
368
392
|
}
|
|
369
393
|
|
|
370
|
-
export type PlaybackPolicy = 'signed' | 'public'
|
|
394
|
+
export type PlaybackPolicy = 'signed' | 'public' | 'drm'
|
|
371
395
|
|
|
372
396
|
export interface MuxErrors {
|
|
373
397
|
type: string
|
|
@@ -401,7 +425,12 @@ export interface MuxTextTrack {
|
|
|
401
425
|
id: string
|
|
402
426
|
text_type?: 'subtitles'
|
|
403
427
|
// https://docs.mux.com/api-reference/video#operation/list-assets:~:text=text%20type%20tracks.-,tracks%5B%5D.,text_source,-string
|
|
404
|
-
text_source?:
|
|
428
|
+
text_source?:
|
|
429
|
+
| 'uploaded'
|
|
430
|
+
| 'embedded'
|
|
431
|
+
| 'generated_live'
|
|
432
|
+
| 'generated_live_final'
|
|
433
|
+
| 'generated_vod'
|
|
405
434
|
// BCP 47 language code
|
|
406
435
|
language_code?: 'en' | 'en-US' | string
|
|
407
436
|
// The name of the track containing a human-readable description. The hls manifest will associate a subtitle text track with this value
|
|
@@ -410,8 +439,12 @@ export interface MuxTextTrack {
|
|
|
410
439
|
// Max 255 characters
|
|
411
440
|
passthrough?: string
|
|
412
441
|
status: 'preparing' | 'ready' | 'errored'
|
|
442
|
+
error?: {
|
|
443
|
+
type: string
|
|
444
|
+
messages?: string[]
|
|
445
|
+
}
|
|
413
446
|
}
|
|
414
|
-
export type MuxTrack = MuxVideoTrack | MuxAudioTrack
|
|
447
|
+
export type MuxTrack = MuxVideoTrack | MuxAudioTrack | MuxTextTrack
|
|
415
448
|
// Typings lifted from https://docs.mux.com/api-reference/video#tag/assets
|
|
416
449
|
export interface MuxAsset {
|
|
417
450
|
id: string
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type {VideoAssetDocument} from './types'
|
|
2
|
-
|
|
3
|
-
export function getPlaybackId(asset: Pick<VideoAssetDocument, 'playbackId'>): string {
|
|
4
|
-
if (!asset?.playbackId) {
|
|
5
|
-
console.error('Asset is missing a playbackId', {asset})
|
|
6
|
-
throw new TypeError(`Missing playbackId`)
|
|
7
|
-
}
|
|
8
|
-
return asset.playbackId
|
|
9
|
-
}
|