@meframe/core 0.0.3 → 0.0.4
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/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +5 -4
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +2 -2
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +4 -3
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/VideoL1Cache.d.ts +2 -2
- package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -1
- package/dist/cache/l1/VideoL1Cache.js +13 -8
- package/dist/cache/l1/VideoL1Cache.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/types.d.ts +3 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.d.ts +7 -8
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +56 -76
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/controllers/types.d.ts +2 -3
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/event/events.d.ts +1 -4
- package/dist/event/events.d.ts.map +1 -1
- package/dist/event/events.js.map +1 -1
- package/dist/model/CompositionModel.d.ts +1 -0
- package/dist/model/CompositionModel.d.ts.map +1 -1
- package/dist/model/CompositionModel.js +2 -0
- package/dist/model/CompositionModel.js.map +1 -1
- package/dist/model/patch.d.ts +6 -2
- package/dist/model/patch.d.ts.map +1 -1
- package/dist/model/patch.js +76 -2
- package/dist/model/patch.js.map +1 -1
- package/dist/model/types.d.ts +1 -0
- package/dist/model/types.d.ts.map +1 -1
- package/dist/orchestrator/CompositionPlanner.d.ts +8 -7
- package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -1
- package/dist/orchestrator/CompositionPlanner.js +33 -56
- package/dist/orchestrator/CompositionPlanner.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +0 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +39 -19
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +3 -5
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoClipSession.js +66 -69
- package/dist/orchestrator/VideoClipSession.js.map +1 -1
- package/dist/orchestrator/types.d.ts +1 -0
- package/dist/orchestrator/types.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts +6 -0
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.js +17 -1
- package/dist/stages/compose/GlobalAudioSession.js.map +1 -1
- package/dist/stages/load/ResourceLoader.d.ts +22 -1
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
- package/dist/stages/load/ResourceLoader.js +71 -25
- package/dist/stages/load/ResourceLoader.js.map +1 -1
- package/dist/stages/load/TaskManager.d.ts +1 -1
- package/dist/stages/load/TaskManager.d.ts.map +1 -1
- package/dist/stages/load/TaskManager.js +3 -2
- package/dist/stages/load/TaskManager.js.map +1 -1
- package/dist/stages/load/types.d.ts +2 -0
- package/dist/stages/load/types.d.ts.map +1 -1
- package/dist/worker/WorkerPool.d.ts +2 -0
- package/dist/worker/WorkerPool.d.ts.map +1 -1
- package/dist/worker/WorkerPool.js +4 -1
- package/dist/worker/WorkerPool.js.map +1 -1
- package/dist/workers/stages/compose/video-compose.worker.js +113 -81
- package/dist/workers/stages/compose/video-compose.worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/controllers/PreviewHandle.d.ts +0 -25
- package/dist/controllers/PreviewHandle.d.ts.map +0 -1
- package/dist/controllers/PreviewHandle.js +0 -45
- package/dist/controllers/PreviewHandle.js.map +0 -1
- package/dist/model/dirty-range.js +0 -220
- package/dist/model/dirty-range.js.map +0 -1
|
@@ -832,8 +832,11 @@ class VideoComposer {
|
|
|
832
832
|
this.filterProcessor.clearCache();
|
|
833
833
|
}
|
|
834
834
|
}
|
|
835
|
-
function resolveActiveLayers(layers, timestamp
|
|
835
|
+
function resolveActiveLayers(layers, timestamp) {
|
|
836
836
|
return layers.filter((layer) => {
|
|
837
|
+
if (layer.layerId.includes("base-video")) {
|
|
838
|
+
return true;
|
|
839
|
+
}
|
|
837
840
|
if (layer.status !== "ready") {
|
|
838
841
|
return false;
|
|
839
842
|
}
|
|
@@ -892,11 +895,12 @@ class VideoComposeWorker {
|
|
|
892
895
|
channel;
|
|
893
896
|
composer = null;
|
|
894
897
|
composeStream = null;
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
streamState =
|
|
898
|
+
clipId = null;
|
|
899
|
+
downstreamPort = null;
|
|
900
|
+
upstreamPort = null;
|
|
901
|
+
instructions = null;
|
|
902
|
+
streamState = null;
|
|
903
|
+
imageBitmap = null;
|
|
900
904
|
constructor() {
|
|
901
905
|
this.channel = new WorkerChannel(self, {
|
|
902
906
|
name: "VideoComposeWorker",
|
|
@@ -910,7 +914,7 @@ class VideoComposeWorker {
|
|
|
910
914
|
this.channel.registerHandler("flush", this.handleFlush.bind(this));
|
|
911
915
|
this.channel.registerHandler("get_stats", this.handleGetStats.bind(this));
|
|
912
916
|
this.channel.registerHandler("install_instructions", this.handleInstallInstructions.bind(this));
|
|
913
|
-
this.channel.registerHandler("
|
|
917
|
+
this.channel.registerHandler("receive_image", this.handleReceiveImage.bind(this));
|
|
914
918
|
this.channel.registerHandler("dispose_clip", this.handleDisposeClip.bind(this));
|
|
915
919
|
this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));
|
|
916
920
|
}
|
|
@@ -918,9 +922,12 @@ class VideoComposeWorker {
|
|
|
918
922
|
* Unified connect handler used by stream pipeline
|
|
919
923
|
*/
|
|
920
924
|
async handleConnect(payload) {
|
|
921
|
-
const { port, direction, clipId
|
|
925
|
+
const { port, direction, clipId } = payload;
|
|
926
|
+
if (clipId && !this.clipId) {
|
|
927
|
+
this.clipId = clipId;
|
|
928
|
+
}
|
|
922
929
|
if (direction === "upstream") {
|
|
923
|
-
this.
|
|
930
|
+
this.upstreamPort = port;
|
|
924
931
|
const channel = new WorkerChannel(port, {
|
|
925
932
|
name: "VideoCompose-Decode",
|
|
926
933
|
timeout: 3e4
|
|
@@ -928,7 +935,7 @@ class VideoComposeWorker {
|
|
|
928
935
|
channel.receiveStream(this.handleReceiveStream.bind(this));
|
|
929
936
|
}
|
|
930
937
|
if (direction === "downstream") {
|
|
931
|
-
this.
|
|
938
|
+
this.downstreamPort = port;
|
|
932
939
|
}
|
|
933
940
|
return { success: true };
|
|
934
941
|
}
|
|
@@ -967,14 +974,12 @@ class VideoComposeWorker {
|
|
|
967
974
|
};
|
|
968
975
|
}
|
|
969
976
|
async handleReceiveStream(stream, metadata) {
|
|
970
|
-
const { clipId = "default" } = metadata || {};
|
|
971
977
|
if (!this.composer) {
|
|
972
978
|
console.error("[VideoComposeWorker] Composer not configured");
|
|
973
979
|
return;
|
|
974
980
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
console.warn("[VideoComposeWorker] No instructions for clip", clipId);
|
|
981
|
+
if (!this.instructions) {
|
|
982
|
+
console.warn("[VideoComposeWorker] No instructions installed");
|
|
978
983
|
return;
|
|
979
984
|
}
|
|
980
985
|
const filteredStream = stream.pipeThrough(
|
|
@@ -984,12 +989,7 @@ class VideoComposeWorker {
|
|
|
984
989
|
const frame = wrappedFrame.frame || wrappedFrame;
|
|
985
990
|
const gopSerial = wrappedFrame.gopSerial;
|
|
986
991
|
const isKeyframe = wrappedFrame.isKeyframe;
|
|
987
|
-
const
|
|
988
|
-
if (this.shouldSkipFrame(clipId, timestamp)) {
|
|
989
|
-
frame.close();
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
const request = this.buildComposeRequest(clipId, instruction, frame, timestamp);
|
|
992
|
+
const request = this.buildComposeRequest(this.instructions, frame);
|
|
993
993
|
if (!request) {
|
|
994
994
|
frame.close();
|
|
995
995
|
return;
|
|
@@ -1008,7 +1008,7 @@ class VideoComposeWorker {
|
|
|
1008
1008
|
const { composeStream, cacheStream } = this.composer.createStreams();
|
|
1009
1009
|
this.channel.sendStream(cacheStream, metadata);
|
|
1010
1010
|
filteredStream.pipeTo(composeStream).catch((error) => {
|
|
1011
|
-
console.error("[VideoComposeWorker] compose stream error", clipId, error);
|
|
1011
|
+
console.error("[VideoComposeWorker] compose stream error", this.clipId, error);
|
|
1012
1012
|
});
|
|
1013
1013
|
}
|
|
1014
1014
|
// private handleGetStream(): ReadableStream<VideoFrame> | undefined {
|
|
@@ -1047,61 +1047,96 @@ class VideoComposeWorker {
|
|
|
1047
1047
|
this.composer = null;
|
|
1048
1048
|
}
|
|
1049
1049
|
this.composeStream = null;
|
|
1050
|
-
this.
|
|
1051
|
-
this.
|
|
1052
|
-
this.
|
|
1053
|
-
this.
|
|
1050
|
+
this.downstreamPort?.close();
|
|
1051
|
+
this.upstreamPort?.close();
|
|
1052
|
+
this.downstreamPort = null;
|
|
1053
|
+
this.upstreamPort = null;
|
|
1054
|
+
this.imageBitmap?.close();
|
|
1055
|
+
this.imageBitmap = null;
|
|
1056
|
+
this.instructions = null;
|
|
1057
|
+
this.streamState = null;
|
|
1054
1058
|
this.channel.state = WorkerState.Disposed;
|
|
1055
1059
|
return { success: true };
|
|
1056
1060
|
}
|
|
1057
|
-
async handleInstallInstructions(
|
|
1058
|
-
const { clipId, revision } =
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
+
async handleInstallInstructions(payload) {
|
|
1062
|
+
const { clipId, revision } = payload;
|
|
1063
|
+
if (!this.clipId) {
|
|
1064
|
+
this.clipId = clipId;
|
|
1065
|
+
}
|
|
1066
|
+
if (this.instructions && this.instructions.revision > revision) {
|
|
1061
1067
|
return { success: false };
|
|
1062
1068
|
}
|
|
1063
|
-
this.
|
|
1069
|
+
this.instructions = payload;
|
|
1064
1070
|
return { success: true };
|
|
1065
1071
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1072
|
+
/**
|
|
1073
|
+
* Receive image data from ResourceLoader
|
|
1074
|
+
* Note: ImageBitmap is required because VideoFrame constructor in Worker context
|
|
1075
|
+
* only accepts ImageBitmap/OffscreenCanvas, not HTMLImageElement or Blob
|
|
1076
|
+
*/
|
|
1077
|
+
async handleReceiveImage(payload) {
|
|
1078
|
+
const { clipId, imageBitmap } = payload;
|
|
1079
|
+
if (!this.clipId) {
|
|
1080
|
+
this.clipId = clipId;
|
|
1081
|
+
}
|
|
1082
|
+
if (this.imageBitmap) {
|
|
1083
|
+
this.imageBitmap.close();
|
|
1084
|
+
}
|
|
1085
|
+
this.imageBitmap = imageBitmap;
|
|
1086
|
+
if (this.instructions) {
|
|
1087
|
+
await this.startImageFrameStream();
|
|
1071
1088
|
}
|
|
1072
|
-
this.pendingReplay.set(clipId, { ...range, revision });
|
|
1073
|
-
this.channel.notify("sync_ack", { clipId, revision });
|
|
1074
1089
|
return { success: true };
|
|
1075
1090
|
}
|
|
1076
|
-
async handleDisposeClip(
|
|
1077
|
-
|
|
1078
|
-
this.
|
|
1079
|
-
this.
|
|
1080
|
-
this.
|
|
1081
|
-
this.
|
|
1082
|
-
this.
|
|
1083
|
-
this.
|
|
1091
|
+
async handleDisposeClip() {
|
|
1092
|
+
this.instructions = null;
|
|
1093
|
+
this.streamState = null;
|
|
1094
|
+
this.downstreamPort?.close();
|
|
1095
|
+
this.upstreamPort?.close();
|
|
1096
|
+
this.downstreamPort = null;
|
|
1097
|
+
this.upstreamPort = null;
|
|
1098
|
+
this.imageBitmap?.close();
|
|
1099
|
+
this.imageBitmap = null;
|
|
1084
1100
|
return { success: true };
|
|
1085
1101
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
*/
|
|
1090
|
-
shouldSkipFrame(clipId, timestamp) {
|
|
1091
|
-
const dirtyRange = this.pendingReplay.get(clipId);
|
|
1092
|
-
if (!dirtyRange) {
|
|
1093
|
-
return false;
|
|
1094
|
-
}
|
|
1095
|
-
if (timestamp >= dirtyRange.startUs && timestamp <= dirtyRange.endUs) {
|
|
1096
|
-
return false;
|
|
1102
|
+
async startImageFrameStream() {
|
|
1103
|
+
if (!this.instructions || !this.composer) {
|
|
1104
|
+
return;
|
|
1097
1105
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1106
|
+
const timeline = this.instructions.baseConfig.timeline;
|
|
1107
|
+
if (!timeline) {
|
|
1108
|
+
return;
|
|
1100
1109
|
}
|
|
1101
|
-
|
|
1110
|
+
const { composeStream, cacheStream } = this.composer.createStreams();
|
|
1111
|
+
const { clipDurationUs, compositionFps } = timeline;
|
|
1112
|
+
let currentTimeUs = 0;
|
|
1113
|
+
const readableStream = new ReadableStream({
|
|
1114
|
+
pull: (controller) => {
|
|
1115
|
+
if (currentTimeUs >= clipDurationUs) {
|
|
1116
|
+
controller.close();
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
const videoFrame = new VideoFrame(this.imageBitmap, {
|
|
1120
|
+
timestamp: currentTimeUs,
|
|
1121
|
+
duration: frameDurationFromFps(compositionFps)
|
|
1122
|
+
});
|
|
1123
|
+
const request = this.buildComposeRequest(this.instructions, videoFrame);
|
|
1124
|
+
if (request) {
|
|
1125
|
+
controller.enqueue(request);
|
|
1126
|
+
}
|
|
1127
|
+
currentTimeUs += frameDurationFromFps(compositionFps);
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1130
|
+
this.channel.sendStream(cacheStream, {
|
|
1131
|
+
streamType: "video",
|
|
1132
|
+
clipId: this.clipId
|
|
1133
|
+
});
|
|
1134
|
+
readableStream.pipeTo(composeStream).catch((error) => {
|
|
1135
|
+
console.error("[VideoComposeWorker] image frame stream error", this.clipId, error);
|
|
1136
|
+
});
|
|
1102
1137
|
}
|
|
1103
|
-
buildComposeRequest(
|
|
1104
|
-
const normalizedTime = this.computeTimelineTimestamp(
|
|
1138
|
+
buildComposeRequest(instruction, frame) {
|
|
1139
|
+
const normalizedTime = this.computeTimelineTimestamp(frame, instruction.baseConfig);
|
|
1105
1140
|
const clipStartUs = instruction.baseConfig.timeline?.clipStartUs ?? 0;
|
|
1106
1141
|
const clipDurationUs = instruction.baseConfig.timeline?.clipDurationUs ?? Infinity;
|
|
1107
1142
|
const clipEndUs = clipStartUs + clipDurationUs;
|
|
@@ -1142,43 +1177,40 @@ class VideoComposeWorker {
|
|
|
1142
1177
|
direction: entry.params.payload?.direction
|
|
1143
1178
|
};
|
|
1144
1179
|
}
|
|
1145
|
-
computeTimelineTimestamp(
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
if (!state) {
|
|
1149
|
-
state = {
|
|
1180
|
+
computeTimelineTimestamp(frame, config) {
|
|
1181
|
+
if (!this.streamState) {
|
|
1182
|
+
this.streamState = {
|
|
1150
1183
|
baseTimestamp: null,
|
|
1151
1184
|
lastSourceTimestamp: null,
|
|
1152
1185
|
nextFrameIndex: 0
|
|
1153
1186
|
};
|
|
1154
|
-
this.streamState.set(key, state);
|
|
1155
1187
|
}
|
|
1156
1188
|
const timeline = config.timeline;
|
|
1157
1189
|
if (!timeline) {
|
|
1158
1190
|
const ts = frame.timestamp ?? 0;
|
|
1159
|
-
|
|
1191
|
+
this.streamState.lastSourceTimestamp = frame.timestamp ?? null;
|
|
1160
1192
|
return ts;
|
|
1161
1193
|
}
|
|
1162
1194
|
const { clipStartUs, compositionFps } = timeline;
|
|
1163
1195
|
const sourceTimestamp = frame.timestamp ?? null;
|
|
1164
|
-
if (sourceTimestamp !== null &&
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
}
|
|
1168
|
-
if (
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if (
|
|
1196
|
+
if (sourceTimestamp !== null && this.streamState.lastSourceTimestamp !== null && sourceTimestamp < this.streamState.lastSourceTimestamp) {
|
|
1197
|
+
this.streamState.baseTimestamp = null;
|
|
1198
|
+
this.streamState.nextFrameIndex = 0;
|
|
1199
|
+
}
|
|
1200
|
+
if (this.streamState.baseTimestamp === null) {
|
|
1201
|
+
this.streamState.baseTimestamp = sourceTimestamp ?? 0;
|
|
1202
|
+
this.streamState.nextFrameIndex = 0;
|
|
1203
|
+
if (this.streamState.baseTimestamp > 1e3) {
|
|
1172
1204
|
console.warn(
|
|
1173
|
-
`[VideoComposeWorker] First frame timestamp is ${
|
|
1205
|
+
`[VideoComposeWorker] First frame timestamp is ${this.streamState.baseTimestamp}us, expected ~0. Check MP4Demuxer normalization.`
|
|
1174
1206
|
);
|
|
1175
1207
|
}
|
|
1176
1208
|
}
|
|
1177
1209
|
const frameDuration = frameDurationFromFps(compositionFps);
|
|
1178
|
-
let frameIndex =
|
|
1210
|
+
let frameIndex = this.streamState.nextFrameIndex;
|
|
1179
1211
|
if (sourceTimestamp !== null) {
|
|
1180
1212
|
const approxIndex = frameIndexFromTimestamp(
|
|
1181
|
-
|
|
1213
|
+
this.streamState.baseTimestamp,
|
|
1182
1214
|
sourceTimestamp,
|
|
1183
1215
|
compositionFps,
|
|
1184
1216
|
"nearest"
|
|
@@ -1192,8 +1224,8 @@ class VideoComposeWorker {
|
|
|
1192
1224
|
compositionFps,
|
|
1193
1225
|
"nearest"
|
|
1194
1226
|
);
|
|
1195
|
-
|
|
1196
|
-
|
|
1227
|
+
this.streamState.nextFrameIndex = frameIndex + 1;
|
|
1228
|
+
this.streamState.lastSourceTimestamp = sourceTimestamp;
|
|
1197
1229
|
return timelineTime;
|
|
1198
1230
|
}
|
|
1199
1231
|
}
|