@eluvio/elv-client-js 3.1.94 → 3.1.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ElvClient-min.js +5 -5
- package/dist/ElvClient-node-min.js +8 -8
- package/dist/ElvFrameClient-min.js +5 -5
- package/dist/ElvPermissionsClient-min.js +5 -5
- package/dist/src/AuthorizationClient.js +1 -1
- package/dist/src/ElvClient.js +289 -176
- package/dist/src/RemoteSigner.js +13 -5
- package/dist/src/Utils.js +20 -0
- package/dist/src/client/ABRPublishing.js +6 -4
- package/dist/src/client/ContentAccess.js +46 -37
- package/package-lock.json +18191 -23169
- package/package.json +2 -2
- package/src/AuthorizationClient.js +1 -1
- package/src/ElvClient.js +62 -1
- package/src/RemoteSigner.js +22 -18
- package/src/Utils.js +22 -0
- package/src/client/ContentAccess.js +4 -0
- package/testScripts/Test.js +0 -19
- package/utilities/ObjectSetPermission.js +4 -4
- package/utilities/SimpleIngest.js +41 -0
- package/utilities/example_files/simple_ingest_library_metadata.json +180 -0
- package/utilities/example_files/simple_ingest_library_metadata_animation_NFTs.json +133 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eluvio/elv-client-js",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.97",
|
|
4
4
|
"description": "Javascript client for the Eluvio Content Fabric",
|
|
5
5
|
"main": "src/ElvClient.js",
|
|
6
6
|
"author": "Kevin Talmadge",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@babel/runtime": "^7.8.4",
|
|
59
59
|
"@eluvio/crypto": ">=1.0.8",
|
|
60
|
-
"@eluvio/elv-abr-profile": "^0.
|
|
60
|
+
"@eluvio/elv-abr-profile": "^1.0.0",
|
|
61
61
|
"@sindresorhus/slugify": "^1.1.0",
|
|
62
62
|
"babel-loader": "^8.0.6",
|
|
63
63
|
"bignumber.js": "^8.0.2",
|
|
@@ -204,7 +204,7 @@ class AuthorizationClient {
|
|
|
204
204
|
addr: Utils.FormatAddress(((this.client.signer && this.client.signer.address) || ""))
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
-
if(!(this.noAuth || noAuth)
|
|
207
|
+
if(!(this.noAuth || noAuth)) {
|
|
208
208
|
const { transactionHash } = await this.MakeAccessRequest({
|
|
209
209
|
libraryId,
|
|
210
210
|
objectId,
|
package/src/ElvClient.js
CHANGED
|
@@ -694,6 +694,67 @@ class ElvClient {
|
|
|
694
694
|
return this.utils.FormatAddress(this.signer.address);
|
|
695
695
|
}
|
|
696
696
|
|
|
697
|
+
/*
|
|
698
|
+
TOKEN 211b PREFIX + BODY | aplsjcJf1HYcDDUuCdXcSZtU86nYK162YmYJeuqwMczEBJVkD5D5EvsBvVwYDRsf4hzDvBWMoe9piBpqx...
|
|
699
|
+
PREFIX 6b aplsjc | apl=plain s=ES256K jc=json-compressed
|
|
700
|
+
BODY 205b base58(SIGNATURE + PAYLOAD)
|
|
701
|
+
SIGNATURE + PAYLOAD 151b 151b * 138 / 100 + 1 = 209b (>= 205b)
|
|
702
|
+
SIGNATURE 66b ES256K_Di9Lu83mz4wMoehCEeQhKpJJ7ApmDZLumAa2Cge48F6EHYnbn8msATGGpjucScwimei1TWGd7aeyQY45AdXd5tT1Z
|
|
703
|
+
PAYLOAD 85b json-compressed
|
|
704
|
+
json 79b {"adr":"VVf4DQU357tDnZGYQeDrntRJ5rs=","spc":"ispc3ANoVSzNA3P6t7abLR69ho5YPPZU"}
|
|
705
|
+
*/
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Create a signed authorization token that can be used to authorize against the fabric
|
|
709
|
+
*
|
|
710
|
+
* @methodGroup Authorization
|
|
711
|
+
* @namedParams
|
|
712
|
+
* @param {number} duration=86400000 - Time until the token expires, in milliseconds (1 hour = 60 * 60 * 1000 = 3600000). Default is 24 hours.
|
|
713
|
+
* @param {Object=} spec - Additional attributes for this token
|
|
714
|
+
* @param {string=} address - Address of the signing account - if not specified, the current signer address will be used.
|
|
715
|
+
* @param {function=} Sign - If specified, this function will be used to produce the signature instead of the client's current signer
|
|
716
|
+
* @param {boolean=} addEthereumPrefix=true - If specified, the 'Ethereum Signed Message' prefixed hash format will be performed. Disable this if the provided Sign method already does this (e.g. Metamask)
|
|
717
|
+
*/
|
|
718
|
+
async CreateFabricToken({
|
|
719
|
+
duration=24 * 60 * 60 * 1000,
|
|
720
|
+
spec={},
|
|
721
|
+
address,
|
|
722
|
+
Sign,
|
|
723
|
+
addEthereumPrefix=true,
|
|
724
|
+
}={}) {
|
|
725
|
+
address = address || this.CurrentAccountAddress();
|
|
726
|
+
|
|
727
|
+
let token = {
|
|
728
|
+
...spec,
|
|
729
|
+
sub:`iusr${Utils.AddressToHash(address)}`,
|
|
730
|
+
adr: Buffer.from(address.replace(/^0x/, ""), "hex").toString("base64"),
|
|
731
|
+
spc: await this.ContentSpaceId(),
|
|
732
|
+
iat: Date.now(),
|
|
733
|
+
exp: Date.now() + duration,
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
if(!Sign) {
|
|
737
|
+
Sign = async message => this.authClient.Sign(message);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
let message = `Eluvio Content Fabric Access Token 1.0\n${JSON.stringify(token)}`;
|
|
741
|
+
|
|
742
|
+
if(addEthereumPrefix) {
|
|
743
|
+
message = Ethers.utils.keccak256(Buffer.from(`\x19Ethereum Signed Message:\n${message.length}${message}`, "utf-8"));
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const signature = await Sign(message);
|
|
747
|
+
|
|
748
|
+
const compressedToken = Pako.deflateRaw(Buffer.from(JSON.stringify(token), "utf-8"));
|
|
749
|
+
return `acspjc${this.utils.B58(
|
|
750
|
+
Buffer.concat([
|
|
751
|
+
Buffer.from(signature.replace(/^0x/, ""), "hex"),
|
|
752
|
+
Buffer.from(compressedToken)
|
|
753
|
+
])
|
|
754
|
+
)}`;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
|
|
697
758
|
/**
|
|
698
759
|
* Issue a self-signed authorization token
|
|
699
760
|
*
|
|
@@ -705,7 +766,7 @@ class ElvClient {
|
|
|
705
766
|
* @param {string=} policyId - The object ID of the policy for this token
|
|
706
767
|
* @param {string=} subject - The subject of the token
|
|
707
768
|
* @param {string} grantType=read - Permissions to grant for this token. Options: "access", "read", "create", "update", "read-crypt"
|
|
708
|
-
* @param {number} duration - Time until the token expires, in milliseconds (1 hour = 60 * 60 * 1000)
|
|
769
|
+
* @param {number} duration - Time until the token expires, in milliseconds (1 hour = 60 * 60 * 1000 = 3600000)
|
|
709
770
|
* @param {boolean} allowDecryption=false - If specified, the re-encryption key will be included in the token,
|
|
710
771
|
* enabling the user of this token to download encrypted content from the specified object
|
|
711
772
|
* @param {Object=} context - Additional JSON context
|
package/src/RemoteSigner.js
CHANGED
|
@@ -85,24 +85,28 @@ class RemoteSigner extends Ethers.Signer {
|
|
|
85
85
|
*/
|
|
86
86
|
async signDigest(digest) {
|
|
87
87
|
if(!this.signatureCache[digest]) {
|
|
88
|
-
this.signatureCache[digest] = new Promise(async resolve => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
88
|
+
this.signatureCache[digest] = new Promise(async (resolve, reject) => {
|
|
89
|
+
try {
|
|
90
|
+
let signature = await Utils.ResponseToJson(
|
|
91
|
+
this.HttpClient.Request({
|
|
92
|
+
method: "POST",
|
|
93
|
+
path: UrlJoin("as", "wlt", "sign", "eth", this.id),
|
|
94
|
+
headers: {
|
|
95
|
+
Authorization: `Bearer ${this.authToken}`
|
|
96
|
+
},
|
|
97
|
+
body: {
|
|
98
|
+
hash: digest
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
signature.v = parseInt(signature.v, 16);
|
|
104
|
+
signature.recoveryParam = signature.v - 27;
|
|
105
|
+
|
|
106
|
+
resolve(signature);
|
|
107
|
+
} catch(error) {
|
|
108
|
+
reject(error);
|
|
109
|
+
}
|
|
106
110
|
});
|
|
107
111
|
}
|
|
108
112
|
|
package/src/Utils.js
CHANGED
|
@@ -4,6 +4,7 @@ const bs58 = require("bs58");
|
|
|
4
4
|
const BigNumber = require("bignumber.js").default;
|
|
5
5
|
const VarInt = require("varint");
|
|
6
6
|
const URI = require("urijs");
|
|
7
|
+
const Pako = require("pako");
|
|
7
8
|
|
|
8
9
|
const {
|
|
9
10
|
keccak256,
|
|
@@ -150,6 +151,27 @@ const Utils = {
|
|
|
150
151
|
};
|
|
151
152
|
},
|
|
152
153
|
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Decode the specified signed token into its component parts
|
|
157
|
+
*
|
|
158
|
+
* @param {string} token - The token to decode
|
|
159
|
+
*
|
|
160
|
+
* @return {Object} - Components of the signed token
|
|
161
|
+
*/
|
|
162
|
+
DecodeSignedToken: (token) => {
|
|
163
|
+
const decodedToken = Utils.FromB58(token.slice(6));
|
|
164
|
+
const signature = `0x${decodedToken.slice(0, 65).toString("hex")}`;
|
|
165
|
+
|
|
166
|
+
let payload = JSON.parse(Buffer.from(Pako.inflateRaw(decodedToken.slice(65))).toString("utf-8"));
|
|
167
|
+
payload.adr = Utils.FormatAddress(`0x${Buffer.from(payload.adr, "base64").toString("hex")}`);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
payload,
|
|
171
|
+
signature
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
|
|
153
175
|
/**
|
|
154
176
|
* Decode the specified write token into its component parts
|
|
155
177
|
*
|
|
@@ -2332,6 +2332,10 @@ exports.LinkData = async function({libraryId, objectId, versionHash, writeToken,
|
|
|
2332
2332
|
/* Encryption */
|
|
2333
2333
|
|
|
2334
2334
|
exports.CreateEncryptionConk = async function({libraryId, objectId, versionHash, writeToken, createKMSConk=true}) {
|
|
2335
|
+
if(this.signer.remoteSigner) {
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2335
2339
|
ValidateParameters({libraryId, objectId, versionHash});
|
|
2336
2340
|
ValidateWriteToken(writeToken);
|
|
2337
2341
|
|
package/testScripts/Test.js
CHANGED
|
@@ -13,25 +13,6 @@ const Test = async () => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
client.SetSigner({signer});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const ethUrl = "https://host-216-66-40-19.contentfabric.io/eth";
|
|
19
|
-
const asUrl = "https://host-66-220-3-86.contentfabric.io";
|
|
20
|
-
|
|
21
|
-
client.SetNodes({
|
|
22
|
-
ethereumURIs: [
|
|
23
|
-
ethUrl
|
|
24
|
-
],
|
|
25
|
-
authServiceURIs: [
|
|
26
|
-
asUrl
|
|
27
|
-
]
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
console.log(
|
|
31
|
-
await client.ContentObjectTenantId({
|
|
32
|
-
objectId: "iq__3PXRZX5NCzPQsfTEquCctB2K3KJh"
|
|
33
|
-
})
|
|
34
|
-
)
|
|
35
16
|
} catch(error) {
|
|
36
17
|
console.error(error);
|
|
37
18
|
console.error(JSON.stringify(error, null, 2));
|
|
@@ -9,7 +9,7 @@ const Logger = require("./lib/concerns/Logger");
|
|
|
9
9
|
|
|
10
10
|
const permissionTypes = ["owner", "editable", "viewable", "listable", "public"];
|
|
11
11
|
|
|
12
|
-
class
|
|
12
|
+
class ObjectSetPermission extends Utility {
|
|
13
13
|
blueprint() {
|
|
14
14
|
return {
|
|
15
15
|
concerns: [Logger, ArgObjectId, Client],
|
|
@@ -55,7 +55,7 @@ class ObjectAddGroupPerms extends Utility {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if(require.main === module) {
|
|
58
|
-
Utility.cmdLineInvoke(
|
|
58
|
+
Utility.cmdLineInvoke(ObjectSetPermission);
|
|
59
59
|
} else {
|
|
60
|
-
module.exports =
|
|
61
|
-
}
|
|
60
|
+
module.exports = ObjectSetPermission;
|
|
61
|
+
}
|
|
@@ -53,6 +53,10 @@ class SimpleIngest extends Utility {
|
|
|
53
53
|
const libABRProfile = R.path(["metadata", "abr", "default_profile"], libInfo);
|
|
54
54
|
if(R.isNil(libABRProfile)) throw Error("Library does not specify ABR profile for simple ingests");
|
|
55
55
|
|
|
56
|
+
const libMezManageGroups = R.path(["metadata", "abr", "mez_manage_groups"], libInfo);
|
|
57
|
+
|
|
58
|
+
const libMezPermission = R.path(["metadata", "abr", "mez_permission_level"], libInfo);
|
|
59
|
+
|
|
56
60
|
const {drm, libraryId, title} = this.args;
|
|
57
61
|
const encrypt = true;
|
|
58
62
|
|
|
@@ -91,6 +95,7 @@ class SimpleIngest extends Utility {
|
|
|
91
95
|
|
|
92
96
|
if(!R.isNil(createMasterResponse.errors) && !R.isEmpty(createMasterResponse.errors)) throw Error(`Error(s) encountered while inspecting uploaded files: ${createMasterResponse.errors.join("\n")}`);
|
|
93
97
|
|
|
98
|
+
// TODO: replace with a 'waitForNewObject' call (Finalize.waitForPublish throws exception for brand new object not yet visible)
|
|
94
99
|
await seconds(2);
|
|
95
100
|
|
|
96
101
|
await this.concerns.Finalize.waitForPublish({
|
|
@@ -218,6 +223,42 @@ class SimpleIngest extends Utility {
|
|
|
218
223
|
const finalizeErrors = finalizeAbrResponse.errors;
|
|
219
224
|
if(!R.isNil(finalizeErrors) && !R.isEmpty(finalizeErrors)) throw Error(`Error(s) encountered while finalizing object: ${finalizeErrors.join("\n")}`);
|
|
220
225
|
|
|
226
|
+
if(libMezManageGroups && libMezManageGroups.length > 0){
|
|
227
|
+
for(const groupAddress of libMezManageGroups){
|
|
228
|
+
logger.log("Setting access permissions for managers");
|
|
229
|
+
await client.AddContentObjectGroupPermission({
|
|
230
|
+
objectId: id,
|
|
231
|
+
groupAddress,
|
|
232
|
+
permission: "manage"
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if(libMezPermission) {
|
|
239
|
+
if(!["owner", "editable", "viewable", "listable", "public"].includes(libMezPermission)) {
|
|
240
|
+
logger.warn(`Bad value for mez_permission_level: '${libMezPermission}', skipping permission setting`);
|
|
241
|
+
} else {
|
|
242
|
+
logger.log(`Setting object permission to '${libMezPermission}'`);
|
|
243
|
+
const prevHash = await client.LatestVersionHash({objectId: id});
|
|
244
|
+
|
|
245
|
+
await client.SetPermission({
|
|
246
|
+
objectId: id,
|
|
247
|
+
permission: libMezPermission
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const newHash = await client.LatestVersionHash({objectId: id});
|
|
251
|
+
|
|
252
|
+
if(prevHash === newHash) {
|
|
253
|
+
logger.log("Version hash unchanged: " + newHash );
|
|
254
|
+
} else {
|
|
255
|
+
logger.log("Previous version hash: " + prevHash );
|
|
256
|
+
logger.log("New version hash: " + newHash );
|
|
257
|
+
}
|
|
258
|
+
logger.data("version_hash", newHash);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
221
262
|
logger.logList(
|
|
222
263
|
"",
|
|
223
264
|
"Playable media object created:",
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"abr": {
|
|
3
|
+
"comments": [
|
|
4
|
+
"For movies/TV - snapAR is set to true, this profile will attempt to conform aspect ratio to nearby standard",
|
|
5
|
+
"also specifies 'store encrypted', offers both clear and drm playout formats"
|
|
6
|
+
],
|
|
7
|
+
"mez_content_type": "YOUR_TITLE_(MEZ)_CONTENT_TYPE_ID",
|
|
8
|
+
"mez_manage_groups": [
|
|
9
|
+
"ADDRESS_FOR_YOUR_CONTENT_ADMINS_GROUP"
|
|
10
|
+
],
|
|
11
|
+
"mez_permission_level": "ONE_OF_THE_FOLLOWING: owner, editable, viewable, listable, public",
|
|
12
|
+
"default_profile": {
|
|
13
|
+
"drm_optional": true,
|
|
14
|
+
"store_clear": false,
|
|
15
|
+
"video_parametric_ladder": {
|
|
16
|
+
"baseAspectRatio": "16/9",
|
|
17
|
+
"baseFrameRate": "30",
|
|
18
|
+
"rungSpecs": [
|
|
19
|
+
{
|
|
20
|
+
"dim": 2160,
|
|
21
|
+
"bitrate": 14000000
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"dim": 1440,
|
|
25
|
+
"bitrate": 11500000
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"dim": 1080,
|
|
29
|
+
"bitrate": 9500000
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"dim": 720,
|
|
33
|
+
"bitrate": 4500000
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"dim": 480,
|
|
37
|
+
"bitrate": 1750000
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"dim": 360,
|
|
41
|
+
"bitrate": 810000
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"dim": 240,
|
|
45
|
+
"bitrate": 500000
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"options": {
|
|
49
|
+
"upscale": false,
|
|
50
|
+
"snapAR": true,
|
|
51
|
+
"maxARSnap": 0.06,
|
|
52
|
+
"minDimStepdown": 0.12,
|
|
53
|
+
"frameRateScaleFactor": 0.5
|
|
54
|
+
},
|
|
55
|
+
"limits": {
|
|
56
|
+
"aspectRatioMax": "3",
|
|
57
|
+
"aspectRatioMin": "1/3",
|
|
58
|
+
"avgBitrateMax": 100000000,
|
|
59
|
+
"avgBitrateMin": 100000,
|
|
60
|
+
"fileSizeMax": 100000000,
|
|
61
|
+
"fileSizeMin": 10000,
|
|
62
|
+
"durationMax": 14400,
|
|
63
|
+
"durationMin": 1,
|
|
64
|
+
"finalBitrateMax": 30000000,
|
|
65
|
+
"frameRateMax": "60",
|
|
66
|
+
"frameRateMin": "15",
|
|
67
|
+
"heightMax": 5000,
|
|
68
|
+
"heightMin": 100,
|
|
69
|
+
"sampleAspectRatioMax": "3/2",
|
|
70
|
+
"sampleAspectRatioMin": "2/3",
|
|
71
|
+
"widthMax": 5000,
|
|
72
|
+
"widthMin": 100
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"ladder_specs": {
|
|
76
|
+
"{\"media_type\":\"audio\",\"channels\":1}": {
|
|
77
|
+
"rung_specs": [
|
|
78
|
+
{
|
|
79
|
+
"bit_rate": 128000,
|
|
80
|
+
"media_type": "audio",
|
|
81
|
+
"pregenerate": true
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"{\"media_type\":\"audio\",\"channels\":2}": {
|
|
86
|
+
"rung_specs": [
|
|
87
|
+
{
|
|
88
|
+
"bit_rate": 192000,
|
|
89
|
+
"media_type": "audio",
|
|
90
|
+
"pregenerate": true
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"{\"media_type\":\"audio\",\"channels\":6}": {
|
|
95
|
+
"rung_specs": [
|
|
96
|
+
{
|
|
97
|
+
"bit_rate": 384000,
|
|
98
|
+
"media_type": "audio",
|
|
99
|
+
"pregenerate": true
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"playout_formats": {
|
|
105
|
+
"dash-widevine": {
|
|
106
|
+
"drm": {
|
|
107
|
+
"content_id": "",
|
|
108
|
+
"enc_scheme_name": "cenc",
|
|
109
|
+
"license_servers": [],
|
|
110
|
+
"type": "DrmWidevine"
|
|
111
|
+
},
|
|
112
|
+
"protocol": {
|
|
113
|
+
"min_buffer_length": 2,
|
|
114
|
+
"type": "ProtoDash"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"hls-aes128": {
|
|
118
|
+
"drm": {
|
|
119
|
+
"enc_scheme_name": "aes-128",
|
|
120
|
+
"type": "DrmAes128"
|
|
121
|
+
},
|
|
122
|
+
"protocol": {
|
|
123
|
+
"type": "ProtoHls"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"hls-fairplay": {
|
|
127
|
+
"drm": {
|
|
128
|
+
"enc_scheme_name": "cbcs",
|
|
129
|
+
"license_servers": [],
|
|
130
|
+
"type": "DrmFairplay"
|
|
131
|
+
},
|
|
132
|
+
"protocol": {
|
|
133
|
+
"type": "ProtoHls"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"hls-sample-aes": {
|
|
137
|
+
"drm": {
|
|
138
|
+
"enc_scheme_name": "cbcs",
|
|
139
|
+
"type": "DrmSampleAes"
|
|
140
|
+
},
|
|
141
|
+
"protocol": {
|
|
142
|
+
"type": "ProtoHls"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"dash-clear": {
|
|
146
|
+
"drm": null,
|
|
147
|
+
"protocol": {
|
|
148
|
+
"min_buffer_length": 2,
|
|
149
|
+
"type": "ProtoDash"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"hls-clear": {
|
|
153
|
+
"drm": null,
|
|
154
|
+
"protocol": {
|
|
155
|
+
"type": "ProtoHls"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"segment_specs": {
|
|
160
|
+
"audio": {
|
|
161
|
+
"segs_per_chunk": 15,
|
|
162
|
+
"target_dur": 2
|
|
163
|
+
},
|
|
164
|
+
"video": {
|
|
165
|
+
"segs_per_chunk": 15,
|
|
166
|
+
"target_dur": 2
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
"elv": {
|
|
172
|
+
"media": {
|
|
173
|
+
"drm": {
|
|
174
|
+
"fps": {
|
|
175
|
+
"cert": "MIIExzCCA6+gAwIBAgIIHyfkXhxLHC4wDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYDVQQDDCpBcHBsZSBLZXkgU2VydmljZXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMjAwOTEyMDMzMjI0WhcNMjIwOTEzMDMzMjI0WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECgwKRWx1dmlvIEluYzETMBEGA1UECwwKMktIOEtDM01NWDEnMCUGA1UEAwweRmFpclBsYXkgU3RyZWFtaW5nOiBFbHV2aW8gSW5jMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDslbBURB6gj07g7VrS7Ojixe7FNZOupomcZt+mtMvyavjg7X7/T4RccmKUQxOoMLKCJcQ6WrdHhIpN8+bciq7lr0mNzaN467zREiUNYOpkVPi13sJLieY2m2MEPOQTbIl52Cu1YyH+4/g1dKPmeguSnzZRo36jsCGHlJBjHq0jkQIDAQABo4IB6DCCAeQwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRj5EdUy4VxWUYsg6zMRDFkZwMsvjCB4gYDVR0gBIHaMIHXMIHUBgkqhkiG92NkBQEwgcYwgcMGCCsGAQUFBwICMIG2DIGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5hcHBsZS5jb20va2V5c2VydmljZXMuY3JsMB0GA1UdDgQWBBR4jerseBHEUDC7mU+NQuIzZqHRFDAOBgNVHQ8BAf8EBAMCBSAwOAYLKoZIhvdjZAYNAQMBAf8EJgFuNnNkbHQ2OXFuc3l6eXp5bWFzdmdudGthbWd2bGE1Y212YzdpMC4GCyqGSIb3Y2QGDQEEAQH/BBwBd252bHhlbGV1Y3Vpb2JyZW4yeHZlZmV6N2Y5MA0GCSqGSIb3DQEBBQUAA4IBAQBM17YYquw0soDPAadr1aIM6iC6BQ/kOGYu3y/6AlrwYgAQNFy8DjsQUoqlQWFuA0sigp57bTUymkXEBf9yhUmXXiPafGjbxzsPF5SPFLIciolWbxRCB153L1a/Vh2wg3rhf4IvAZuJpnml6SSg5SjD19bN+gD7zrtp3yWKBKuarLSjDvVIB1SoxEToBs3glAEqoBiA2eZjikBA0aBlbvjUF2gqOmZjZJ7dmG1Tos2Zd4SdGL6ltSpKUeSGSxyv41aqF83vNpymNJmey2t2kPPtC7mt0LM32Ift3AkAl8Za9JbV/pOnc95oAfPhVTOGOI+u2BuB2qaKWjqHwkfqCz4A"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
{
|
|
2
|
+
"abr": {
|
|
3
|
+
"comments": [
|
|
4
|
+
"For animation NFTs that are not movie/TV clips - snapAR is set to false",
|
|
5
|
+
"also specifies 'store clear', only offers clear playout formats (no drm)",
|
|
6
|
+
"and object permission 'listable'.",
|
|
7
|
+
"does not include DRM cert @ /elv/media/drm/fps/cert"
|
|
8
|
+
],
|
|
9
|
+
"mez_content_type": "YOUR_TITLE_(NFT)_CONTENT_TYPE_ID",
|
|
10
|
+
"mez_manage_groups": [
|
|
11
|
+
"ADDRESS_FOR_YOUR_CONTENT_ADMINS_GROUP"
|
|
12
|
+
],
|
|
13
|
+
"mez_permission_level": "listable",
|
|
14
|
+
"default_profile": {
|
|
15
|
+
"drm_optional": true,
|
|
16
|
+
"store_clear": true,
|
|
17
|
+
"video_parametric_ladder": {
|
|
18
|
+
"baseAspectRatio": "16/9",
|
|
19
|
+
"baseFrameRate": "30",
|
|
20
|
+
"rungSpecs": [
|
|
21
|
+
{
|
|
22
|
+
"dim": 2160,
|
|
23
|
+
"bitrate": 14000000
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"dim": 1440,
|
|
27
|
+
"bitrate": 11500000
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"dim": 1080,
|
|
31
|
+
"bitrate": 9500000
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"dim": 720,
|
|
35
|
+
"bitrate": 4500000
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"dim": 480,
|
|
39
|
+
"bitrate": 1750000
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"dim": 360,
|
|
43
|
+
"bitrate": 810000
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"dim": 240,
|
|
47
|
+
"bitrate": 500000
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"options": {
|
|
51
|
+
"upscale": false,
|
|
52
|
+
"snapAR": false,
|
|
53
|
+
"maxARSnap": 0.06,
|
|
54
|
+
"minDimStepdown": 0.12,
|
|
55
|
+
"frameRateScaleFactor": 0.5
|
|
56
|
+
},
|
|
57
|
+
"limits": {
|
|
58
|
+
"aspectRatioMax": "3",
|
|
59
|
+
"aspectRatioMin": "1/3",
|
|
60
|
+
"avgBitrateMax": 100000000,
|
|
61
|
+
"avgBitrateMin": 100000,
|
|
62
|
+
"fileSizeMax": 100000000,
|
|
63
|
+
"fileSizeMin": 10000,
|
|
64
|
+
"durationMax": 14400,
|
|
65
|
+
"durationMin": 1,
|
|
66
|
+
"finalBitrateMax": 30000000,
|
|
67
|
+
"frameRateMax": "60",
|
|
68
|
+
"frameRateMin": "15",
|
|
69
|
+
"heightMax": 5000,
|
|
70
|
+
"heightMin": 100,
|
|
71
|
+
"sampleAspectRatioMax": "3/2",
|
|
72
|
+
"sampleAspectRatioMin": "2/3",
|
|
73
|
+
"widthMax": 5000,
|
|
74
|
+
"widthMin": 100
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"ladder_specs": {
|
|
78
|
+
"{\"media_type\":\"audio\",\"channels\":1}": {
|
|
79
|
+
"rung_specs": [
|
|
80
|
+
{
|
|
81
|
+
"bit_rate": 128000,
|
|
82
|
+
"media_type": "audio",
|
|
83
|
+
"pregenerate": true
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"{\"media_type\":\"audio\",\"channels\":2}": {
|
|
88
|
+
"rung_specs": [
|
|
89
|
+
{
|
|
90
|
+
"bit_rate": 192000,
|
|
91
|
+
"media_type": "audio",
|
|
92
|
+
"pregenerate": true
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
"{\"media_type\":\"audio\",\"channels\":6}": {
|
|
97
|
+
"rung_specs": [
|
|
98
|
+
{
|
|
99
|
+
"bit_rate": 384000,
|
|
100
|
+
"media_type": "audio",
|
|
101
|
+
"pregenerate": true
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"playout_formats": {
|
|
107
|
+
"dash-clear": {
|
|
108
|
+
"drm": null,
|
|
109
|
+
"protocol": {
|
|
110
|
+
"min_buffer_length": 2,
|
|
111
|
+
"type": "ProtoDash"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"hls-clear": {
|
|
115
|
+
"drm": null,
|
|
116
|
+
"protocol": {
|
|
117
|
+
"type": "ProtoHls"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"segment_specs": {
|
|
122
|
+
"audio": {
|
|
123
|
+
"segs_per_chunk": 15,
|
|
124
|
+
"target_dur": 2
|
|
125
|
+
},
|
|
126
|
+
"video": {
|
|
127
|
+
"segs_per_chunk": 15,
|
|
128
|
+
"target_dur": 2
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|