@aelionsdk/export 0.1.0-beta.1 → 1.0.0-rc.1

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 CHANGED
@@ -4,4 +4,4 @@ Streaming WebCodecs and WebM export pipeline for AelionSDK
4
4
 
5
5
  Install with `npm install @aelionsdk/export@next`.
6
6
 
7
- Version 0.1.0-beta.1 is a prerelease and its API may change before the first stable release. This package is part of [AelionSDK](https://github.com/FoyonaCZY/AelionSDK); see the repository README for supported browsers, examples and deployment requirements.
7
+ Version 1.0.0-rc.1 is a prerelease and its API may change before the first stable release. This package is part of [AelionSDK](https://github.com/FoyonaCZY/AelionSDK); see the repository README for supported browsers, examples and deployment requirements.
@@ -1,5 +1,6 @@
1
1
  import { type JsonObject } from '@aelionsdk/core';
2
2
  import type { ExportProfileId } from './profiles.js';
3
+ export declare const REMOTE_EXPORT_PROTOCOL_VERSION: "1.0.0";
3
4
  export interface RemoteExportAuthorization {
4
5
  readonly scheme: string;
5
6
  readonly token: string;
@@ -8,7 +9,22 @@ export interface RemoteExportAuthorization {
8
9
  export interface RemoteExportAuthorizer {
9
10
  authorize(signal?: AbortSignal): Promise<RemoteExportAuthorization>;
10
11
  }
12
+ export interface RemoteExportAsset {
13
+ readonly assetId: string;
14
+ readonly contentId: string;
15
+ readonly byteLength: number;
16
+ readonly sha256: string;
17
+ readonly mediaType?: string;
18
+ readonly locator?: JsonObject;
19
+ }
20
+ export interface RemoteExportAssetAuthorization extends RemoteExportAuthorization {
21
+ readonly assetId: string;
22
+ }
23
+ export interface RemoteExportAssetAuthorizer {
24
+ authorizeAsset(asset: RemoteExportAsset, signal?: AbortSignal): Promise<RemoteExportAssetAuthorization>;
25
+ }
11
26
  export interface RemoteExportRequest {
27
+ readonly protocolVersion: typeof REMOTE_EXPORT_PROTOCOL_VERSION;
12
28
  readonly contentId: string;
13
29
  readonly idempotencyKey: string;
14
30
  readonly profileId: ExportProfileId;
@@ -16,6 +32,20 @@ export interface RemoteExportRequest {
16
32
  readonly sequenceId: string;
17
33
  readonly revision: string;
18
34
  readonly manifest: JsonObject;
35
+ readonly assets: readonly RemoteExportAsset[];
36
+ /** Ephemeral credentials; providers must not persist them in manifests or logs. */
37
+ readonly assetAuthorizations: readonly RemoteExportAssetAuthorization[];
38
+ }
39
+ export interface RemoteExportNegotiationRequest {
40
+ readonly supportedProtocolVersions: readonly [typeof REMOTE_EXPORT_PROTOCOL_VERSION];
41
+ readonly profileId: ExportProfileId;
42
+ readonly assets: readonly RemoteExportAsset[];
43
+ }
44
+ export interface RemoteExportNegotiation {
45
+ /** Untrusted provider response; callers validate it against the supported version. */
46
+ readonly protocolVersion: string;
47
+ readonly acceptedProfileIds: readonly ExportProfileId[];
48
+ readonly maxAssetBytes: number;
19
49
  }
20
50
  export type RemoteExportEvent = {
21
51
  readonly type: 'progress';
@@ -31,6 +61,7 @@ export interface RemoteExportResult {
31
61
  readonly profileId: ExportProfileId;
32
62
  readonly mimeType: string;
33
63
  readonly byteLength: number;
64
+ readonly sha256: string;
34
65
  readonly outputUrl?: string;
35
66
  readonly outputToken?: string;
36
67
  }
@@ -42,12 +73,14 @@ export interface RemoteExportSession {
42
73
  }
43
74
  export interface RemoteExportProvider {
44
75
  readonly id: string;
76
+ negotiate(request: RemoteExportNegotiationRequest, authorization: RemoteExportAuthorization, signal?: AbortSignal): Promise<RemoteExportNegotiation>;
45
77
  start(request: RemoteExportRequest, authorization: RemoteExportAuthorization, signal?: AbortSignal): Promise<RemoteExportSession>;
46
78
  }
47
79
  export interface RunRemoteExportOptions {
48
80
  readonly provider: RemoteExportProvider;
49
81
  readonly authorizer: RemoteExportAuthorizer;
50
82
  readonly request: RemoteExportRequest;
83
+ readonly assetAuthorizer?: RemoteExportAssetAuthorizer;
51
84
  readonly signal?: AbortSignal;
52
85
  readonly onProgress?: (progress: number, stage?: string) => void;
53
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remote-export.d.ts","sourceRoot":"","sources":["../src/remote-export.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-export.d.ts","sourceRoot":"","sources":["../src/remote-export.ts"],"names":[],"mappings":"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"}
@@ -1,37 +1,92 @@
1
1
  import { AelionError, throwIfAborted } from '@aelionsdk/core';
2
+ export const REMOTE_EXPORT_PROTOCOL_VERSION = '1.0.0';
2
3
  function boundedProgress(value) {
3
4
  if (!Number.isFinite(value))
4
5
  return 0;
5
6
  return Math.max(0, Math.min(1, value));
6
7
  }
8
+ function validAuthorization(value) {
9
+ return (value.scheme.length > 0 &&
10
+ value.token.length > 0 &&
11
+ (value.expiresAtMs === undefined || value.expiresAtMs > Date.now()));
12
+ }
13
+ function validateAsset(asset) {
14
+ if (asset.assetId.length === 0 ||
15
+ asset.contentId.length === 0 ||
16
+ !Number.isSafeInteger(asset.byteLength) ||
17
+ asset.byteLength < 0 ||
18
+ !/^[0-9a-f]{64}$/u.test(asset.sha256)) {
19
+ throw new TypeError(`Invalid remote export asset ${asset.assetId || '<empty>'}`);
20
+ }
21
+ }
7
22
  export async function runRemoteExport(options) {
8
23
  throwIfAborted(options.signal, 'Remote export');
9
24
  const authorization = await options.authorizer.authorize(options.signal);
10
25
  throwIfAborted(options.signal, 'Remote export');
11
- if (authorization.scheme.length === 0 || authorization.token.length === 0) {
26
+ if (!validAuthorization(authorization)) {
12
27
  throw new AelionError([
13
28
  {
14
- code: 'REMOTE_EXPORT_AUTH_INVALID',
29
+ code: authorization.expiresAtMs !== undefined && authorization.expiresAtMs <= Date.now()
30
+ ? 'REMOTE_EXPORT_AUTH_EXPIRED'
31
+ : 'REMOTE_EXPORT_AUTH_INVALID',
15
32
  severity: 'error',
16
- message: 'Remote export authorization is empty',
33
+ message: 'Remote export authorization is empty or expired',
17
34
  recoverable: true,
18
35
  },
19
36
  ]);
20
37
  }
21
- if (authorization.expiresAtMs !== undefined && authorization.expiresAtMs <= Date.now()) {
38
+ for (const asset of options.request.assets)
39
+ validateAsset(asset);
40
+ const negotiation = await options.provider.negotiate({
41
+ supportedProtocolVersions: [REMOTE_EXPORT_PROTOCOL_VERSION],
42
+ profileId: options.request.profileId,
43
+ assets: options.request.assets,
44
+ }, authorization, options.signal);
45
+ if (negotiation.protocolVersion !== REMOTE_EXPORT_PROTOCOL_VERSION ||
46
+ !negotiation.acceptedProfileIds.includes(options.request.profileId) ||
47
+ !Number.isSafeInteger(negotiation.maxAssetBytes) ||
48
+ negotiation.maxAssetBytes < 0 ||
49
+ options.request.assets.some(asset => asset.byteLength > negotiation.maxAssetBytes)) {
22
50
  throw new AelionError([
23
51
  {
24
- code: 'REMOTE_EXPORT_AUTH_EXPIRED',
52
+ code: 'REMOTE_EXPORT_INCOMPATIBLE',
25
53
  severity: 'error',
26
- message: 'Remote export authorization has expired',
54
+ message: 'Remote export protocol, profile, or asset budget is incompatible',
55
+ recoverable: false,
56
+ },
57
+ ]);
58
+ }
59
+ if (options.request.assets.length > 0 && options.assetAuthorizer === undefined) {
60
+ throw new AelionError([
61
+ {
62
+ code: 'REMOTE_EXPORT_ASSET_AUTH_REQUIRED',
63
+ severity: 'error',
64
+ message: 'Remote export assets require an explicit authorizer',
27
65
  recoverable: true,
28
66
  },
29
67
  ]);
30
68
  }
69
+ const assetAuthorizations = [];
70
+ for (const asset of options.request.assets) {
71
+ const assetAuthorization = await options.assetAuthorizer?.authorizeAsset(asset, options.signal);
72
+ if (assetAuthorization === undefined ||
73
+ assetAuthorization.assetId !== asset.assetId ||
74
+ !validAuthorization(assetAuthorization)) {
75
+ throw new AelionError([
76
+ {
77
+ code: 'REMOTE_EXPORT_ASSET_AUTH_INVALID',
78
+ severity: 'error',
79
+ message: `Remote export asset authorization is invalid for ${asset.assetId}`,
80
+ recoverable: true,
81
+ },
82
+ ]);
83
+ }
84
+ assetAuthorizations.push(assetAuthorization);
85
+ }
31
86
  let session;
32
87
  let lastProgress = 0;
33
88
  try {
34
- session = await options.provider.start(options.request, authorization, options.signal);
89
+ session = await options.provider.start({ ...options.request, assetAuthorizations }, authorization, options.signal);
35
90
  for await (const event of session.events) {
36
91
  throwIfAborted(options.signal, 'Remote export');
37
92
  if (event.type === 'progress') {
@@ -45,7 +100,10 @@ export async function runRemoteExport(options) {
45
100
  }
46
101
  if (event.result.providerJobId !== session.providerJobId ||
47
102
  event.result.contentId !== options.request.contentId ||
48
- event.result.profileId !== options.request.profileId) {
103
+ event.result.profileId !== options.request.profileId ||
104
+ !Number.isSafeInteger(event.result.byteLength) ||
105
+ event.result.byteLength < 0 ||
106
+ !/^[0-9a-f]{64}$/u.test(event.result.sha256)) {
49
107
  throw new Error('Remote export result identity does not match the request');
50
108
  }
51
109
  options.onProgress?.(1, 'completed');
package/dist/session.d.ts CHANGED
@@ -34,6 +34,32 @@ export interface FrozenProfilePreflightOptions {
34
34
  readonly audioBitrate?: number;
35
35
  readonly materialBackendAvailable?: FrozenWebMExportOptions['materialBackendAvailable'];
36
36
  }
37
+ export type AudioExportCodec = 'opus' | 'aac';
38
+ export interface AudioExportCapabilityEntry {
39
+ readonly codec: AudioExportCodec;
40
+ readonly codecString: 'opus' | 'mp4a.40.2';
41
+ readonly sampleRate: number;
42
+ readonly channelCount: number;
43
+ readonly bitrate: number;
44
+ readonly declaredSupported: boolean;
45
+ readonly runtimeSupported: boolean;
46
+ readonly supported: boolean;
47
+ readonly reason?: 'EXPORT_AUDIO_ENCODER_UNAVAILABLE' | 'EXPORT_AUDIO_CONFIG_UNSUPPORTED' | 'EXPORT_AUDIO_RUNTIME_CANARY_FAILED' | 'EXPORT_AUDIO_CONFIG_PROBE_FAILED';
48
+ }
49
+ export interface ProbeAudioExportMatrixOptions {
50
+ readonly codecs?: readonly AudioExportCodec[];
51
+ readonly sampleRates?: readonly number[];
52
+ readonly channelCounts?: readonly number[];
53
+ readonly bitratePerChannel?: number;
54
+ }
55
+ /**
56
+ * Probes the exact multichannel/sample-rate matrix advertised to a host.
57
+ *
58
+ * `isConfigSupported()` is not accepted as sufficient evidence: every declared
59
+ * configuration also encodes and flushes four real AudioData blocks. This
60
+ * catches runtimes that advertise AAC/Opus but fail when the encoder is used.
61
+ */
62
+ export declare function probeAudioExportMatrix(options?: ProbeAudioExportMatrixOptions): Promise<readonly AudioExportCapabilityEntry[]>;
37
63
  export declare function preflightWebMExport(options: FrozenWebMExportOptions): Promise<ExportPreflightReport>;
38
64
  export declare function preflightMp4Export(options: FrozenMp4ExportOptions): Promise<ExportPreflightReport>;
39
65
  export declare function preflightAv1Mp4Export(options: FrozenMp4ExportOptions): Promise<ExportPreflightReport>;
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/session.js CHANGED
@@ -60,6 +60,96 @@ function verifyAudioEncoderRuntime(config) {
60
60
  audioRuntimeSupport.set(key, probe);
61
61
  return probe;
62
62
  }
63
+ /**
64
+ * Probes the exact multichannel/sample-rate matrix advertised to a host.
65
+ *
66
+ * `isConfigSupported()` is not accepted as sufficient evidence: every declared
67
+ * configuration also encodes and flushes four real AudioData blocks. This
68
+ * catches runtimes that advertise AAC/Opus but fail when the encoder is used.
69
+ */
70
+ export async function probeAudioExportMatrix(options = {}) {
71
+ const codecs = options.codecs ?? ['opus', 'aac'];
72
+ const sampleRates = options.sampleRates ?? [44_100, 48_000, 96_000];
73
+ const channelCounts = options.channelCounts ?? [1, 2, 6];
74
+ const bitratePerChannel = options.bitratePerChannel ?? 64_000;
75
+ for (const [values, name] of [
76
+ [sampleRates, 'sampleRates'],
77
+ [channelCounts, 'channelCounts'],
78
+ ]) {
79
+ if (values.length === 0 || values.some(value => !Number.isSafeInteger(value) || value <= 0)) {
80
+ throw new RangeError(`${name} must contain positive safe integers`);
81
+ }
82
+ }
83
+ if (!Number.isSafeInteger(bitratePerChannel) || bitratePerChannel <= 0) {
84
+ throw new RangeError('bitratePerChannel must be a positive safe integer');
85
+ }
86
+ const entries = [];
87
+ for (const codec of codecs) {
88
+ const codecString = codec === 'aac' ? 'mp4a.40.2' : 'opus';
89
+ for (const sampleRate of sampleRates) {
90
+ for (const channelCount of channelCounts) {
91
+ const bitrate = bitratePerChannel * channelCount;
92
+ if (typeof AudioEncoder !== 'function') {
93
+ entries.push({
94
+ codec,
95
+ codecString,
96
+ sampleRate,
97
+ channelCount,
98
+ bitrate,
99
+ declaredSupported: false,
100
+ runtimeSupported: false,
101
+ supported: false,
102
+ reason: 'EXPORT_AUDIO_ENCODER_UNAVAILABLE',
103
+ });
104
+ continue;
105
+ }
106
+ const config = {
107
+ codec: codecString,
108
+ sampleRate,
109
+ numberOfChannels: channelCount,
110
+ bitrate,
111
+ bitrateMode: 'variable',
112
+ ...(codec === 'aac'
113
+ ? { aac: { format: 'aac' } }
114
+ : { opus: { format: 'opus' } }),
115
+ };
116
+ try {
117
+ const declaredSupported = (await AudioEncoder.isConfigSupported(config)).supported === true;
118
+ const runtimeSupported = declaredSupported && (await verifyAudioEncoderRuntime(config));
119
+ entries.push({
120
+ codec,
121
+ codecString,
122
+ sampleRate,
123
+ channelCount,
124
+ bitrate,
125
+ declaredSupported,
126
+ runtimeSupported,
127
+ supported: runtimeSupported,
128
+ ...(!declaredSupported
129
+ ? { reason: 'EXPORT_AUDIO_CONFIG_UNSUPPORTED' }
130
+ : !runtimeSupported
131
+ ? { reason: 'EXPORT_AUDIO_RUNTIME_CANARY_FAILED' }
132
+ : {}),
133
+ });
134
+ }
135
+ catch {
136
+ entries.push({
137
+ codec,
138
+ codecString,
139
+ sampleRate,
140
+ channelCount,
141
+ bitrate,
142
+ declaredSupported: false,
143
+ runtimeSupported: false,
144
+ supported: false,
145
+ reason: 'EXPORT_AUDIO_CONFIG_PROBE_FAILED',
146
+ });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return entries;
152
+ }
63
153
  function channelCount(layout) {
64
154
  if (layout === 'mono')
65
155
  return 1;
@@ -69,6 +159,20 @@ function channelCount(layout) {
69
159
  return 6;
70
160
  return undefined;
71
161
  }
162
+ function sourceColorSpace(ir) {
163
+ if (ir.colorPrimaries !== 'bt709' ||
164
+ ir.transferFunction !== 'srgb' ||
165
+ ir.matrixCoefficients !== 'rgb' ||
166
+ ir.colorRange !== 'full') {
167
+ throw new TypeError('COLOR_EXPORT_RGBA_CONVERSION_UNSUPPORTED');
168
+ }
169
+ return {
170
+ primaries: 'bt709',
171
+ transfer: 'iec61966-2-1',
172
+ matrix: 'rgb',
173
+ fullRange: true,
174
+ };
175
+ }
72
176
  async function preflightMuxedExport(options, profile) {
73
177
  const issues = [];
74
178
  try {
@@ -383,6 +487,7 @@ export async function exportFrozenRenderIrWebM(options) {
383
487
  channelCount: channelCount(options.ir.channelLayout) ?? 0,
384
488
  videoBitrate: options.videoBitrate,
385
489
  audioBitrate: options.audioBitrate,
490
+ sourceColorSpace: sourceColorSpace(options.ir),
386
491
  ...(report.encoderConfiguration?.videoCodecString === undefined
387
492
  ? {}
388
493
  : { videoCodecString: report.encoderConfiguration.videoCodecString }),
@@ -417,6 +522,7 @@ export async function exportFrozenRenderIrMp4(options) {
417
522
  channelCount: channelCount(options.ir.channelLayout) ?? 0,
418
523
  videoBitrate: options.videoBitrate,
419
524
  audioBitrate: options.audioBitrate,
525
+ sourceColorSpace: sourceColorSpace(options.ir),
420
526
  ...(report.encoderConfiguration?.videoCodecString === undefined
421
527
  ? {}
422
528
  : { videoCodecString: report.encoderConfiguration.videoCodecString }),
@@ -453,6 +559,7 @@ async function exportFrozenRenderIrAlternativeMp4(options, profile) {
453
559
  channelCount: channelCount(options.ir.channelLayout) ?? 0,
454
560
  videoBitrate: options.videoBitrate,
455
561
  audioBitrate: options.audioBitrate,
562
+ sourceColorSpace: sourceColorSpace(options.ir),
456
563
  ...(report.encoderConfiguration?.videoCodecString === undefined
457
564
  ? {}
458
565
  : { videoCodecString: report.encoderConfiguration.videoCodecString }),
@@ -26,6 +26,8 @@ export interface WebMExportOptions {
26
26
  readonly videoCodecString?: string;
27
27
  /** Exact audio codec string selected by preflight. */
28
28
  readonly audioCodecString?: string;
29
+ /** Color interpretation of the RGBA frames passed to the encoder. */
30
+ readonly sourceColorSpace?: VideoColorSpaceInit;
29
31
  readonly sink: WritableStream<{
30
32
  readonly type: 'write';
31
33
  readonly data: Uint8Array<ArrayBuffer>;
@@ -59,6 +61,12 @@ export interface MuxedEncoderConfiguration {
59
61
  readonly frameRate: number;
60
62
  readonly bitrateMode: 'variable';
61
63
  readonly targetBitrate: number;
64
+ readonly sourceColorSpace: {
65
+ readonly primaries: VideoColorPrimaries | null;
66
+ readonly transfer: VideoTransferCharacteristics | null;
67
+ readonly matrix: VideoMatrixCoefficients | null;
68
+ readonly fullRange: boolean | null;
69
+ };
62
70
  };
63
71
  readonly audio: {
64
72
  readonly codec: string;
@@ -1 +1 @@
1
- {"version":3,"file":"webm-export.d.ts","sourceRoot":"","sources":["../src/webm-export.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webm-export.d.ts","sourceRoot":"","sources":["../src/webm-export.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,12 @@ import { av1CodecString, hevcCodecString, negotiateAvcCodecString, preferredAvcC
4
4
  import { createSinkCompletionBarrier } from './sink-completion.js';
5
5
  const MAIN_THREAD_YIELD_INTERVAL_MS = 16;
6
6
  const audioEncoderRuntimeSupport = new Map();
7
+ const DEFAULT_SOURCE_COLOR_SPACE = Object.freeze({
8
+ primaries: 'bt709',
9
+ transfer: 'iec61966-2-1',
10
+ matrix: 'rgb',
11
+ fullRange: true,
12
+ });
7
13
  function nextMainThreadTask() {
8
14
  return new Promise(resolve => globalThis.setTimeout(resolve, 0));
9
15
  }
@@ -130,6 +136,12 @@ export async function exportMuxed(options, profile, range) {
130
136
  throw new RangeError('Muxed export range must be a non-empty subset of the timeline');
131
137
  }
132
138
  throwIfAborted(options.signal, profile.operationName);
139
+ const sourceColorSpace = {
140
+ primaries: options.sourceColorSpace?.primaries ?? DEFAULT_SOURCE_COLOR_SPACE.primaries,
141
+ transfer: options.sourceColorSpace?.transfer ?? DEFAULT_SOURCE_COLOR_SPACE.transfer,
142
+ matrix: options.sourceColorSpace?.matrix ?? DEFAULT_SOURCE_COLOR_SPACE.matrix,
143
+ fullRange: options.sourceColorSpace?.fullRange ?? DEFAULT_SOURCE_COLOR_SPACE.fullRange,
144
+ };
133
145
  if (profile.audioCodec === 'aac') {
134
146
  const runtimeConfig = {
135
147
  codec: options.audioCodecString ?? 'mp4a.40.2',
@@ -230,6 +242,7 @@ export async function exportMuxed(options, profile, range) {
230
242
  const sample = new VideoSample(frame, {
231
243
  timestamp: (timestampUs - rangeTimestampBaseUs) / 1_000_000,
232
244
  duration: durationUs / 1_000_000,
245
+ colorSpace: sourceColorSpace,
233
246
  });
234
247
  try {
235
248
  await videoSource.add(sample);
@@ -299,6 +312,7 @@ export async function exportMuxed(options, profile, range) {
299
312
  frameRate: options.frameRate.numerator / options.frameRate.denominator,
300
313
  bitrateMode: 'variable',
301
314
  targetBitrate: options.videoBitrate,
315
+ sourceColorSpace,
302
316
  },
303
317
  audio: {
304
318
  codec: profile.audioCodec,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aelionsdk/export",
3
- "version": "0.1.0-beta.1",
3
+ "version": "1.0.0-rc.1",
4
4
  "description": "Streaming WebCodecs and WebM export pipeline for AelionSDK",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,9 +34,9 @@
34
34
  "provenance": true
35
35
  },
36
36
  "dependencies": {
37
- "@aelionsdk/core": "0.1.0-beta.1",
38
- "@aelionsdk/media": "0.1.0-beta.1",
39
- "@aelionsdk/render-ir": "0.1.0-beta.1",
37
+ "@aelionsdk/core": "1.0.0-rc.1",
38
+ "@aelionsdk/media": "1.0.0-rc.1",
39
+ "@aelionsdk/render-ir": "1.0.0-rc.1",
40
40
  "mediabunny": "1.50.8"
41
41
  },
42
42
  "scripts": {