@meframe/core 0.0.27 → 0.0.29
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 +2 -2
- package/dist/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +8 -2
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +2 -0
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +9 -2
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/AudioL1Cache.d.ts +1 -1
- package/dist/cache/l1/AudioL1Cache.js +2 -2
- package/dist/cache/l1/AudioL1Cache.js.map +1 -1
- package/dist/controllers/PlaybackController.d.ts +1 -1
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +9 -9
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/model/types.d.ts +5 -0
- package/dist/model/types.d.ts.map +1 -1
- package/dist/model/types.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +2 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +11 -5
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/stages/compose/FrameRateConverter.d.ts +68 -0
- package/dist/stages/compose/FrameRateConverter.d.ts.map +1 -0
- package/dist/stages/compose/VideoComposer.d.ts +2 -2
- package/dist/stages/compose/VideoComposer.d.ts.map +1 -1
- package/dist/stages/encode/index.d.ts +0 -1
- package/dist/stages/encode/index.d.ts.map +1 -1
- package/dist/workers/{MP4Demuxer.CFHDkPYc.js → MP4Demuxer.lMOUMWFh.js} +2 -2
- package/dist/workers/{MP4Demuxer.CFHDkPYc.js.map → MP4Demuxer.lMOUMWFh.js.map} +1 -1
- package/dist/workers/stages/compose/{video-compose.worker.M5uomNVr.js → video-compose.worker.CIeEIJO7.js} +208 -59
- package/dist/workers/stages/compose/video-compose.worker.CIeEIJO7.js.map +1 -0
- package/dist/workers/stages/demux/{audio-demux.worker.BTFPcY7P.js → audio-demux.worker.DcurGC8i.js} +2 -2
- package/dist/workers/stages/demux/{audio-demux.worker.BTFPcY7P.js.map → audio-demux.worker.DcurGC8i.js.map} +1 -1
- package/dist/workers/stages/demux/{video-demux.worker.D_WeHPkt.js → video-demux.worker.B1_wntU4.js} +2 -2
- package/dist/workers/stages/demux/{video-demux.worker.D_WeHPkt.js.map → video-demux.worker.B1_wntU4.js.map} +1 -1
- package/dist/workers/worker-manifest.json +3 -3
- package/package.json +1 -1
- package/dist/stages/encode/ClipEncoderManager.d.ts +0 -64
- package/dist/stages/encode/ClipEncoderManager.d.ts.map +0 -1
- package/dist/utils/time-utils.js +0 -45
- package/dist/utils/time-utils.js.map +0 -1
- package/dist/workers/stages/compose/video-compose.worker.M5uomNVr.js.map +0 -1
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
import { W as WorkerChannel, a as WorkerMessageType, b as WorkerState } from "../../WorkerChannel.CE5euh3R.js";
|
|
2
|
-
const MICROSECONDS_PER_SECOND = 1e6;
|
|
3
|
-
const DEFAULT_FPS = 30;
|
|
4
|
-
function normalizeFps(value) {
|
|
5
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
6
|
-
return DEFAULT_FPS;
|
|
7
|
-
}
|
|
8
|
-
return value;
|
|
9
|
-
}
|
|
10
|
-
function frameDurationFromFps(fps) {
|
|
11
|
-
const normalized = normalizeFps(fps);
|
|
12
|
-
const duration = MICROSECONDS_PER_SECOND / normalized;
|
|
13
|
-
return Math.max(Math.round(duration), 1);
|
|
14
|
-
}
|
|
15
2
|
function measureTextWidth(ctx, text, fontSize, fontFamily, fontWeight = 400) {
|
|
16
3
|
ctx.save();
|
|
17
4
|
ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
@@ -1466,9 +1453,11 @@ class VideoComposer {
|
|
|
1466
1453
|
layerRenderer;
|
|
1467
1454
|
transitionProcessor;
|
|
1468
1455
|
filterProcessor;
|
|
1469
|
-
|
|
1456
|
+
frameDurationUs;
|
|
1457
|
+
// Cached frame duration
|
|
1470
1458
|
constructor(config) {
|
|
1471
1459
|
this.config = this.applyDefaults(config);
|
|
1460
|
+
this.frameDurationUs = Math.round(1e6 / this.config.fps);
|
|
1472
1461
|
this.canvas = new OffscreenCanvas(this.config.width, this.config.height);
|
|
1473
1462
|
const ctx = this.canvas.getContext("2d", {
|
|
1474
1463
|
alpha: true,
|
|
@@ -1491,7 +1480,6 @@ class VideoComposer {
|
|
|
1491
1480
|
);
|
|
1492
1481
|
this.transitionProcessor = new TransitionProcessor(this.config.width, this.config.height);
|
|
1493
1482
|
this.filterProcessor = new FilterProcessor();
|
|
1494
|
-
this.timelineContext = this.config.timeline;
|
|
1495
1483
|
}
|
|
1496
1484
|
applyDefaults(config) {
|
|
1497
1485
|
return {
|
|
@@ -1516,10 +1504,7 @@ class VideoComposer {
|
|
|
1516
1504
|
fonts: config.fonts ?? []
|
|
1517
1505
|
};
|
|
1518
1506
|
}
|
|
1519
|
-
createStreams(
|
|
1520
|
-
if (instruction?.baseConfig.timeline) {
|
|
1521
|
-
this.timelineContext = instruction.baseConfig.timeline;
|
|
1522
|
-
}
|
|
1507
|
+
createStreams(_instruction) {
|
|
1523
1508
|
const stream = new TransformStream(
|
|
1524
1509
|
{
|
|
1525
1510
|
transform: async (request, controller) => {
|
|
@@ -1602,10 +1587,10 @@ class VideoComposer {
|
|
|
1602
1587
|
// return [...layers].sort((a, b) => a.zIndex - b.zIndex);
|
|
1603
1588
|
// }
|
|
1604
1589
|
async createOutputFrame(timeUs) {
|
|
1605
|
-
const duration = frameDurationFromFps(this.timelineContext.compositionFps);
|
|
1606
1590
|
const frame = new VideoFrame(this.canvas, {
|
|
1607
1591
|
timestamp: timeUs,
|
|
1608
|
-
duration,
|
|
1592
|
+
duration: this.frameDurationUs,
|
|
1593
|
+
// Use cached duration
|
|
1609
1594
|
alpha: "discard",
|
|
1610
1595
|
visibleRect: { x: 0, y: 0, width: this.canvas.width, height: this.canvas.height }
|
|
1611
1596
|
});
|
|
@@ -1629,6 +1614,9 @@ class VideoComposer {
|
|
|
1629
1614
|
}
|
|
1630
1615
|
updateConfig(config) {
|
|
1631
1616
|
Object.assign(this.config, this.applyDefaults({ ...this.config, ...config }));
|
|
1617
|
+
if (config.fps !== void 0) {
|
|
1618
|
+
this.frameDurationUs = Math.round(1e6 / this.config.fps);
|
|
1619
|
+
}
|
|
1632
1620
|
if (config.width || config.height) {
|
|
1633
1621
|
this.canvas.width = this.config.width;
|
|
1634
1622
|
this.canvas.height = this.config.height;
|
|
@@ -1638,9 +1626,6 @@ class VideoComposer {
|
|
|
1638
1626
|
if (config.enableSmoothing !== void 0) {
|
|
1639
1627
|
this.ctx.imageSmoothingEnabled = this.config.enableSmoothing;
|
|
1640
1628
|
}
|
|
1641
|
-
if (config.timeline) {
|
|
1642
|
-
this.timelineContext = config.timeline;
|
|
1643
|
-
}
|
|
1644
1629
|
if (config.fonts) {
|
|
1645
1630
|
this.loadFonts();
|
|
1646
1631
|
}
|
|
@@ -1649,6 +1634,19 @@ class VideoComposer {
|
|
|
1649
1634
|
this.filterProcessor.clearCache();
|
|
1650
1635
|
}
|
|
1651
1636
|
}
|
|
1637
|
+
const MICROSECONDS_PER_SECOND = 1e6;
|
|
1638
|
+
const DEFAULT_FPS = 30;
|
|
1639
|
+
function normalizeFps(value) {
|
|
1640
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
1641
|
+
return DEFAULT_FPS;
|
|
1642
|
+
}
|
|
1643
|
+
return value;
|
|
1644
|
+
}
|
|
1645
|
+
function frameDurationFromFps(fps) {
|
|
1646
|
+
const normalized = normalizeFps(fps);
|
|
1647
|
+
const duration = MICROSECONDS_PER_SECOND / normalized;
|
|
1648
|
+
return Math.max(Math.round(duration), 1);
|
|
1649
|
+
}
|
|
1652
1650
|
function interpolateKeyframes(keyframes, timeUs) {
|
|
1653
1651
|
const defaultTransform = {
|
|
1654
1652
|
x: 0,
|
|
@@ -1727,6 +1725,183 @@ function applyEasing(t, easing) {
|
|
|
1727
1725
|
return t;
|
|
1728
1726
|
}
|
|
1729
1727
|
}
|
|
1728
|
+
class FrameRateConverter {
|
|
1729
|
+
clipDurationUs;
|
|
1730
|
+
frameDurationUs;
|
|
1731
|
+
// State for frame processing
|
|
1732
|
+
targetFrameIndex = 0;
|
|
1733
|
+
targetFrameTimeUs = 0;
|
|
1734
|
+
sourceFrameBuffer = [];
|
|
1735
|
+
constructor(targetFps, clipDurationUs) {
|
|
1736
|
+
if (targetFps <= 0) {
|
|
1737
|
+
throw new Error(`Invalid target fps: ${targetFps}`);
|
|
1738
|
+
}
|
|
1739
|
+
if (clipDurationUs <= 0) {
|
|
1740
|
+
throw new Error(`Invalid clip duration: ${clipDurationUs}`);
|
|
1741
|
+
}
|
|
1742
|
+
this.clipDurationUs = clipDurationUs;
|
|
1743
|
+
this.frameDurationUs = Math.round(1e6 / targetFps);
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Create a TransformStream that converts VFR frames to CFR frames
|
|
1747
|
+
*/
|
|
1748
|
+
createStream() {
|
|
1749
|
+
return new TransformStream({
|
|
1750
|
+
start: () => {
|
|
1751
|
+
this.targetFrameIndex = 0;
|
|
1752
|
+
this.targetFrameTimeUs = 0;
|
|
1753
|
+
this.sourceFrameBuffer = [];
|
|
1754
|
+
this.sourceFrameCount = 0;
|
|
1755
|
+
this.outputFrameCount = 0;
|
|
1756
|
+
},
|
|
1757
|
+
transform: (sourceFrame, controller) => {
|
|
1758
|
+
this.processSourceFrame(sourceFrame, controller);
|
|
1759
|
+
},
|
|
1760
|
+
flush: (controller) => {
|
|
1761
|
+
this.flushRemainingFrames(controller);
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
sourceFrameCount = 0;
|
|
1766
|
+
outputFrameCount = 0;
|
|
1767
|
+
/**
|
|
1768
|
+
* Process incoming source frame and output target frames
|
|
1769
|
+
*/
|
|
1770
|
+
processSourceFrame(sourceFrame, controller) {
|
|
1771
|
+
this.sourceFrameBuffer.push(sourceFrame);
|
|
1772
|
+
this.sourceFrameCount++;
|
|
1773
|
+
while (this.targetFrameTimeUs < this.clipDurationUs) {
|
|
1774
|
+
const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
|
|
1775
|
+
if (!closestFrame) {
|
|
1776
|
+
break;
|
|
1777
|
+
}
|
|
1778
|
+
if (this.shouldWaitForNextFrame(closestFrame)) {
|
|
1779
|
+
break;
|
|
1780
|
+
}
|
|
1781
|
+
try {
|
|
1782
|
+
const targetFrame = new VideoFrame(closestFrame, {
|
|
1783
|
+
timestamp: this.targetFrameTimeUs,
|
|
1784
|
+
duration: this.frameDurationUs
|
|
1785
|
+
});
|
|
1786
|
+
controller.enqueue(targetFrame);
|
|
1787
|
+
this.outputFrameCount++;
|
|
1788
|
+
this.cleanupOldFrames(this.targetFrameTimeUs);
|
|
1789
|
+
this.targetFrameIndex++;
|
|
1790
|
+
this.targetFrameTimeUs = this.targetFrameIndex * this.frameDurationUs;
|
|
1791
|
+
} catch (error) {
|
|
1792
|
+
console.error("[FrameRateConverter] Failed to create target frame:", error);
|
|
1793
|
+
this.targetFrameIndex++;
|
|
1794
|
+
this.targetFrameTimeUs = this.targetFrameIndex * this.frameDurationUs;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Flush remaining target frames at end of stream
|
|
1800
|
+
*/
|
|
1801
|
+
flushRemainingFrames(controller) {
|
|
1802
|
+
while (this.sourceFrameBuffer.length > 0) {
|
|
1803
|
+
const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
|
|
1804
|
+
if (!closestFrame) {
|
|
1805
|
+
break;
|
|
1806
|
+
}
|
|
1807
|
+
if (this.targetFrameTimeUs >= this.clipDurationUs) {
|
|
1808
|
+
break;
|
|
1809
|
+
}
|
|
1810
|
+
try {
|
|
1811
|
+
const targetFrame = new VideoFrame(closestFrame, {
|
|
1812
|
+
timestamp: this.targetFrameTimeUs,
|
|
1813
|
+
duration: this.frameDurationUs
|
|
1814
|
+
});
|
|
1815
|
+
controller.enqueue(targetFrame);
|
|
1816
|
+
this.cleanupOldFrames(this.targetFrameTimeUs);
|
|
1817
|
+
this.targetFrameIndex++;
|
|
1818
|
+
this.targetFrameTimeUs = this.targetFrameIndex * this.frameDurationUs;
|
|
1819
|
+
} catch (error) {
|
|
1820
|
+
console.error("[FrameRateConverter] Failed to create target frame in flush:", error);
|
|
1821
|
+
break;
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
for (const frame of this.sourceFrameBuffer) {
|
|
1825
|
+
try {
|
|
1826
|
+
frame.close();
|
|
1827
|
+
} catch (error) {
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
this.sourceFrameBuffer = [];
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* Find the source frame closest to target time
|
|
1834
|
+
*/
|
|
1835
|
+
findClosestFrame(targetTimeUs) {
|
|
1836
|
+
if (this.sourceFrameBuffer.length === 0) {
|
|
1837
|
+
return null;
|
|
1838
|
+
}
|
|
1839
|
+
let closestFrame = this.sourceFrameBuffer[0];
|
|
1840
|
+
let minError = Math.abs((closestFrame?.timestamp ?? 0) - targetTimeUs);
|
|
1841
|
+
for (const frame of this.sourceFrameBuffer) {
|
|
1842
|
+
const error = Math.abs((frame.timestamp ?? 0) - targetTimeUs);
|
|
1843
|
+
if (error < minError) {
|
|
1844
|
+
minError = error;
|
|
1845
|
+
closestFrame = frame;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return closestFrame ?? null;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Check if we should wait for next source frame before outputting
|
|
1852
|
+
* Returns true if:
|
|
1853
|
+
* - We only have 1 frame in buffer
|
|
1854
|
+
* - The closest frame is before target time
|
|
1855
|
+
* - We might get a better match from next frame
|
|
1856
|
+
*/
|
|
1857
|
+
shouldWaitForNextFrame(closestFrame) {
|
|
1858
|
+
if (this.sourceFrameBuffer.length <= 1) {
|
|
1859
|
+
const frameTimestamp = closestFrame.timestamp ?? 0;
|
|
1860
|
+
if (frameTimestamp < this.targetFrameTimeUs) {
|
|
1861
|
+
return true;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
return false;
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Clean up source frames that are no longer needed
|
|
1868
|
+
* Keep frames that might be needed for future target frames
|
|
1869
|
+
*/
|
|
1870
|
+
cleanupOldFrames(currentTargetTimeUs) {
|
|
1871
|
+
const nextTargetTimeUs = currentTargetTimeUs + this.frameDurationUs;
|
|
1872
|
+
const previousTargetTimeUs = currentTargetTimeUs - this.frameDurationUs;
|
|
1873
|
+
let removeCount = 0;
|
|
1874
|
+
for (let i = 0; i < this.sourceFrameBuffer.length; i++) {
|
|
1875
|
+
const frame = this.sourceFrameBuffer[i];
|
|
1876
|
+
if (!frame) continue;
|
|
1877
|
+
const frameTimestamp = frame.timestamp ?? 0;
|
|
1878
|
+
const isNeededForNext = Math.abs(frameTimestamp - nextTargetTimeUs) < Math.abs(frameTimestamp - previousTargetTimeUs);
|
|
1879
|
+
if (frameTimestamp < previousTargetTimeUs && !isNeededForNext) {
|
|
1880
|
+
try {
|
|
1881
|
+
frame.close();
|
|
1882
|
+
} catch (error) {
|
|
1883
|
+
}
|
|
1884
|
+
removeCount++;
|
|
1885
|
+
} else {
|
|
1886
|
+
break;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
if (removeCount > 0) {
|
|
1890
|
+
this.sourceFrameBuffer.splice(0, removeCount);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* Get current conversion state (for debugging)
|
|
1895
|
+
*/
|
|
1896
|
+
getState() {
|
|
1897
|
+
return {
|
|
1898
|
+
targetFrameIndex: this.targetFrameIndex,
|
|
1899
|
+
targetFrameTimeUs: this.targetFrameTimeUs,
|
|
1900
|
+
bufferSize: this.sourceFrameBuffer.length,
|
|
1901
|
+
frameDurationUs: this.frameDurationUs
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1730
1905
|
function resolveActiveLayers(layers, timestamp) {
|
|
1731
1906
|
return layers.filter((layer) => {
|
|
1732
1907
|
if (!layer.payload.attachmentId) {
|
|
@@ -1842,7 +2017,6 @@ class VideoComposeWorker {
|
|
|
1842
2017
|
downstreamPort = null;
|
|
1843
2018
|
upstreamPort = null;
|
|
1844
2019
|
instructions = null;
|
|
1845
|
-
streamState = null;
|
|
1846
2020
|
imageMap = /* @__PURE__ */ new Map();
|
|
1847
2021
|
constructor() {
|
|
1848
2022
|
this.channel = new WorkerChannel(self, {
|
|
@@ -1925,7 +2099,13 @@ class VideoComposeWorker {
|
|
|
1925
2099
|
console.warn("[VideoComposeWorker] No instructions installed");
|
|
1926
2100
|
return;
|
|
1927
2101
|
}
|
|
1928
|
-
const
|
|
2102
|
+
const timeline = this.instructions.baseConfig.timeline;
|
|
2103
|
+
const fpsConverter = new FrameRateConverter(
|
|
2104
|
+
timeline?.compositionFps ?? 30,
|
|
2105
|
+
timeline?.clipDurationUs ?? Infinity
|
|
2106
|
+
);
|
|
2107
|
+
const cfrStream = stream.pipeThrough(fpsConverter.createStream());
|
|
2108
|
+
const filteredStream = cfrStream.pipeThrough(
|
|
1929
2109
|
new TransformStream({
|
|
1930
2110
|
transform: (frame, controller) => {
|
|
1931
2111
|
try {
|
|
@@ -2004,7 +2184,6 @@ class VideoComposeWorker {
|
|
|
2004
2184
|
this.imageMap.forEach((bitmap) => bitmap.close());
|
|
2005
2185
|
this.imageMap.clear();
|
|
2006
2186
|
this.instructions = null;
|
|
2007
|
-
this.streamState = null;
|
|
2008
2187
|
this.channel.state = WorkerState.Disposed;
|
|
2009
2188
|
return { success: true };
|
|
2010
2189
|
}
|
|
@@ -2045,7 +2224,6 @@ class VideoComposeWorker {
|
|
|
2045
2224
|
}
|
|
2046
2225
|
async handleDisposeClip() {
|
|
2047
2226
|
this.instructions = null;
|
|
2048
|
-
this.streamState = null;
|
|
2049
2227
|
this.downstreamPort?.close();
|
|
2050
2228
|
this.upstreamPort?.close();
|
|
2051
2229
|
this.downstreamPort = null;
|
|
@@ -2115,7 +2293,7 @@ class VideoComposeWorker {
|
|
|
2115
2293
|
}
|
|
2116
2294
|
}
|
|
2117
2295
|
buildComposeRequest(instruction, frame) {
|
|
2118
|
-
const clipRelativeTime =
|
|
2296
|
+
const clipRelativeTime = frame.timestamp ?? 0;
|
|
2119
2297
|
const clipDurationUs = instruction.baseConfig.timeline?.clipDurationUs ?? Infinity;
|
|
2120
2298
|
if (clipRelativeTime < 0 || clipRelativeTime >= clipDurationUs) {
|
|
2121
2299
|
return null;
|
|
@@ -2159,35 +2337,6 @@ class VideoComposeWorker {
|
|
|
2159
2337
|
direction: entry.params.payload?.direction
|
|
2160
2338
|
};
|
|
2161
2339
|
}
|
|
2162
|
-
computeTimelineTimestamp(frame, config) {
|
|
2163
|
-
if (!this.streamState) {
|
|
2164
|
-
this.streamState = {
|
|
2165
|
-
lastSourceTimestamp: null,
|
|
2166
|
-
nextFrameIndex: 0
|
|
2167
|
-
};
|
|
2168
|
-
}
|
|
2169
|
-
const timeline = config.timeline;
|
|
2170
|
-
if (!timeline) {
|
|
2171
|
-
const ts = frame.timestamp ?? 0;
|
|
2172
|
-
this.streamState.lastSourceTimestamp = frame.timestamp ?? null;
|
|
2173
|
-
return ts;
|
|
2174
|
-
}
|
|
2175
|
-
const { compositionFps } = timeline;
|
|
2176
|
-
const sourceTimestamp = frame.timestamp ?? null;
|
|
2177
|
-
if (sourceTimestamp !== null && this.streamState.lastSourceTimestamp !== null && sourceTimestamp < this.streamState.lastSourceTimestamp) {
|
|
2178
|
-
this.streamState.nextFrameIndex = 0;
|
|
2179
|
-
}
|
|
2180
|
-
const frameDuration = frameDurationFromFps(compositionFps);
|
|
2181
|
-
let frameIndex = this.streamState.nextFrameIndex;
|
|
2182
|
-
if (sourceTimestamp !== null) {
|
|
2183
|
-
const approxIndex = Math.round(sourceTimestamp / frameDuration);
|
|
2184
|
-
frameIndex = Math.max(frameIndex, approxIndex);
|
|
2185
|
-
}
|
|
2186
|
-
const relativeTimeUs = frameIndex * frameDuration;
|
|
2187
|
-
this.streamState.nextFrameIndex = frameIndex + 1;
|
|
2188
|
-
this.streamState.lastSourceTimestamp = sourceTimestamp;
|
|
2189
|
-
return relativeTimeUs;
|
|
2190
|
-
}
|
|
2191
2340
|
}
|
|
2192
2341
|
const worker = new VideoComposeWorker();
|
|
2193
2342
|
self.addEventListener("beforeunload", () => {
|
|
@@ -2198,4 +2347,4 @@ export {
|
|
|
2198
2347
|
VideoComposeWorker,
|
|
2199
2348
|
videoCompose_worker as default
|
|
2200
2349
|
};
|
|
2201
|
-
//# sourceMappingURL=video-compose.worker.
|
|
2350
|
+
//# sourceMappingURL=video-compose.worker.CIeEIJO7.js.map
|