@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 +1 -1
- package/dist/remote-export.d.ts +33 -0
- package/dist/remote-export.d.ts.map +1 -1
- package/dist/remote-export.js +66 -8
- package/dist/session.d.ts +26 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +107 -0
- package/dist/webm-export.d.ts +8 -0
- package/dist/webm-export.d.ts.map +1 -1
- package/dist/webm-export.js +14 -0
- package/package.json +4 -4
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
|
|
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.
|
package/dist/remote-export.d.ts
CHANGED
|
@@ -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":"AAAA,OAAO,EAA+B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;CAC/
|
|
1
|
+
{"version":3,"file":"remote-export.d.ts","sourceRoot":"","sources":["../src/remote-export.ts"],"names":[],"mappings":"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"}
|
package/dist/remote-export.js
CHANGED
|
@@ -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
|
|
26
|
+
if (!validAuthorization(authorization)) {
|
|
12
27
|
throw new AelionError([
|
|
13
28
|
{
|
|
14
|
-
code:
|
|
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
|
-
|
|
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: '
|
|
52
|
+
code: 'REMOTE_EXPORT_INCOMPATIBLE',
|
|
25
53
|
severity: 'error',
|
|
26
|
-
message: 'Remote export
|
|
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>;
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACjD,QAAQ,CAAC,oBAAoB,CAAC,EAAE;QAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;KACpC,CAAC;CACH;AAED,MAAM,WAAW,uBACf,SAAQ,IAAI,CACV,iBAAiB,EACjB,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,CAChF;IACD,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAClC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,KAC5C,OAAO,CAAC;IACb;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACzC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CACnC;AAED,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,wBAAwB,CAAC,EAAE,uBAAuB,CAAC,0BAA0B,CAAC,CAAC;CACzF;
|
|
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 }),
|
package/dist/webm-export.d.ts
CHANGED
|
@@ -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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"}
|
package/dist/webm-export.js
CHANGED
|
@@ -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": "
|
|
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": "
|
|
38
|
-
"@aelionsdk/media": "
|
|
39
|
-
"@aelionsdk/render-ir": "
|
|
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": {
|