@remotion/studio 4.0.452 → 4.0.454
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/audio-waveform-worker.d.ts +1 -0
- package/dist/audio-waveform-worker.js +102 -0
- package/dist/components/AudioWaveform.d.ts +2 -0
- package/dist/components/AudioWaveform.js +168 -18
- package/dist/components/CurrentAsset.js +13 -5
- package/dist/components/Timeline/LoopedIndicator.js +5 -19
- package/dist/components/Timeline/TimelineSequence.js +18 -10
- package/dist/components/Timeline/TimelineVideoInfo.d.ts +2 -0
- package/dist/components/Timeline/TimelineVideoInfo.js +51 -12
- package/dist/components/audio-waveform-worker-types.d.ts +28 -0
- package/dist/components/audio-waveform-worker-types.js +2 -0
- package/dist/components/draw-peaks.d.ts +1 -1
- package/dist/components/load-waveform-peaks.d.ts +11 -1
- package/dist/components/load-waveform-peaks.js +33 -36
- package/dist/components/looped-media-timeline.d.ts +6 -0
- package/dist/components/looped-media-timeline.js +14 -0
- package/dist/components/slice-waveform-peaks.d.ts +7 -0
- package/dist/components/slice-waveform-peaks.js +15 -0
- package/dist/components/waveform-peak-processor.d.ts +23 -0
- package/dist/components/waveform-peak-processor.js +77 -0
- package/dist/esm/audio-waveform-worker.mjs +351 -0
- package/dist/esm/{chunk-hxr6txpe.js → chunk-g39hwn0a.js} +434 -108
- package/dist/esm/internals.mjs +434 -108
- package/dist/esm/previewEntry.mjs +434 -108
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/helpers/calculate-timeline.js +16 -0
- package/dist/helpers/extract-frames.js +12 -3
- package/dist/helpers/get-duration-or-compute.d.ts +2 -0
- package/dist/helpers/get-duration-or-compute.js +10 -0
- package/dist/helpers/get-timeline-nestedness.js +2 -1
- package/dist/helpers/use-max-media-duration.js +2 -2
- package/dist/make-audio-waveform-worker.d.ts +1 -0
- package/dist/make-audio-waveform-worker.js +10 -0
- package/package.json +19 -10
|
@@ -6615,6 +6615,13 @@ import { ALL_FORMATS, Input, UrlSource } from "mediabunny";
|
|
|
6615
6615
|
import { useContext as useContext12, useEffect as useEffect22, useMemo as useMemo29, useState as useState24 } from "react";
|
|
6616
6616
|
import { Internals as Internals11, staticFile } from "remotion";
|
|
6617
6617
|
|
|
6618
|
+
// src/helpers/get-duration-or-compute.ts
|
|
6619
|
+
var getDurationOrCompute = async (input) => {
|
|
6620
|
+
return await input.getDurationFromMetadata(undefined, {
|
|
6621
|
+
skipLiveWait: true
|
|
6622
|
+
}) ?? input.computeDuration(undefined, { skipLiveWait: true });
|
|
6623
|
+
};
|
|
6624
|
+
|
|
6618
6625
|
// src/components/use-static-files.ts
|
|
6619
6626
|
import React40, { createContext as createContext10, useContext as useContext11, useEffect as useEffect21, useState as useState23 } from "react";
|
|
6620
6627
|
import { useRemotionEnvironment } from "remotion";
|
|
@@ -6758,15 +6765,21 @@ var CurrentAsset = () => {
|
|
|
6758
6765
|
source: new UrlSource(url)
|
|
6759
6766
|
});
|
|
6760
6767
|
Promise.all([
|
|
6761
|
-
input
|
|
6768
|
+
getDurationOrCompute(input),
|
|
6762
6769
|
input.getFormat(),
|
|
6763
6770
|
input.getPrimaryVideoTrack()
|
|
6764
|
-
]).then(([duration, format, videoTrack]) => {
|
|
6771
|
+
]).then(async ([duration, format, videoTrack]) => {
|
|
6772
|
+
if (videoTrack && await videoTrack.isLive()) {
|
|
6773
|
+
throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + url);
|
|
6774
|
+
}
|
|
6775
|
+
if (videoTrack && await videoTrack.isRelativeToUnixEpoch()) {
|
|
6776
|
+
throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + url);
|
|
6777
|
+
}
|
|
6765
6778
|
setMediaMetadata({
|
|
6766
6779
|
duration,
|
|
6767
6780
|
format: format.name,
|
|
6768
|
-
width: videoTrack
|
|
6769
|
-
height: videoTrack
|
|
6781
|
+
width: videoTrack ? await videoTrack.getDisplayWidth() : null,
|
|
6782
|
+
height: videoTrack ? await videoTrack.getDisplayHeight() : null
|
|
6770
6783
|
});
|
|
6771
6784
|
}).catch(() => {});
|
|
6772
6785
|
return () => {
|
|
@@ -21050,7 +21063,8 @@ var getTimelineNestedLevel = (sequence, allSequences, depth) => {
|
|
|
21050
21063
|
if (!parentSequence) {
|
|
21051
21064
|
throw new Error("has parentId but no parent");
|
|
21052
21065
|
}
|
|
21053
|
-
|
|
21066
|
+
const parentContributes = parentSequence.showInTimeline;
|
|
21067
|
+
return getTimelineNestedLevel(parentSequence, allSequences, parentContributes ? depth + 1 : depth);
|
|
21054
21068
|
};
|
|
21055
21069
|
|
|
21056
21070
|
// src/helpers/get-timeline-sequence-hash.ts
|
|
@@ -21099,6 +21113,19 @@ var getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}, nonceR
|
|
|
21099
21113
|
};
|
|
21100
21114
|
|
|
21101
21115
|
// src/helpers/calculate-timeline.ts
|
|
21116
|
+
var getInheritedLoopDisplay = (sequence, sequences) => {
|
|
21117
|
+
if (sequence.loopDisplay) {
|
|
21118
|
+
return sequence.loopDisplay;
|
|
21119
|
+
}
|
|
21120
|
+
if (!sequence.parent) {
|
|
21121
|
+
return;
|
|
21122
|
+
}
|
|
21123
|
+
const parent = sequences.find((s) => s.id === sequence.parent);
|
|
21124
|
+
if (!parent) {
|
|
21125
|
+
return;
|
|
21126
|
+
}
|
|
21127
|
+
return getInheritedLoopDisplay(parent, sequences);
|
|
21128
|
+
};
|
|
21102
21129
|
var calculateTimeline = ({
|
|
21103
21130
|
sequences
|
|
21104
21131
|
}) => {
|
|
@@ -21127,7 +21154,8 @@ var calculateTimeline = ({
|
|
|
21127
21154
|
sequence: {
|
|
21128
21155
|
...sequence,
|
|
21129
21156
|
from: visibleStart,
|
|
21130
|
-
duration: visibleDuration
|
|
21157
|
+
duration: visibleDuration,
|
|
21158
|
+
loopDisplay: sequence.type === "audio" || sequence.type === "video" ? getInheritedLoopDisplay(sequence, sortedSequences) : sequence.loopDisplay
|
|
21131
21159
|
},
|
|
21132
21160
|
depth: getTimelineNestedLevel(sequence, sortedSequences, 0),
|
|
21133
21161
|
hash: actualHash,
|
|
@@ -23736,7 +23764,7 @@ var useMaxMediaDuration = (s, fps) => {
|
|
|
23736
23764
|
formats: ALL_FORMATS2,
|
|
23737
23765
|
source: new UrlSource2(src)
|
|
23738
23766
|
});
|
|
23739
|
-
input2
|
|
23767
|
+
getDurationOrCompute(input2).then((duration) => {
|
|
23740
23768
|
cache.set(src, Math.floor(duration * fps));
|
|
23741
23769
|
setMaxMediaDuration(Math.floor(duration * fps));
|
|
23742
23770
|
}).catch((e) => {
|
|
@@ -23763,6 +23791,13 @@ var useMaxMediaDuration = (s, fps) => {
|
|
|
23763
23791
|
import { useEffect as useEffect73, useMemo as useMemo119, useRef as useRef43, useState as useState79 } from "react";
|
|
23764
23792
|
import { Internals as Internals55 } from "remotion";
|
|
23765
23793
|
|
|
23794
|
+
// src/make-audio-waveform-worker.ts
|
|
23795
|
+
var makeAudioWaveformWorker = () => {
|
|
23796
|
+
return new Worker(new URL("./audio-waveform-worker.mjs", import.meta.url), {
|
|
23797
|
+
type: "module"
|
|
23798
|
+
});
|
|
23799
|
+
};
|
|
23800
|
+
|
|
23766
23801
|
// src/components/parse-color.ts
|
|
23767
23802
|
var colorCache = new Map;
|
|
23768
23803
|
var parseColor = (color) => {
|
|
@@ -23838,12 +23873,107 @@ var drawBars = (canvas, peaks, color, volume, width) => {
|
|
|
23838
23873
|
|
|
23839
23874
|
// src/components/load-waveform-peaks.ts
|
|
23840
23875
|
import { ALL_FORMATS as ALL_FORMATS3, AudioSampleSink, Input as Input3, UrlSource as UrlSource3 } from "mediabunny";
|
|
23876
|
+
|
|
23877
|
+
// src/components/waveform-peak-processor.ts
|
|
23878
|
+
var emitWaveformProgress = ({
|
|
23879
|
+
completedPeaks,
|
|
23880
|
+
final,
|
|
23881
|
+
onProgress,
|
|
23882
|
+
peaks,
|
|
23883
|
+
totalPeaks
|
|
23884
|
+
}) => {
|
|
23885
|
+
onProgress?.({
|
|
23886
|
+
peaks,
|
|
23887
|
+
completedPeaks,
|
|
23888
|
+
totalPeaks,
|
|
23889
|
+
final
|
|
23890
|
+
});
|
|
23891
|
+
};
|
|
23892
|
+
var createWaveformPeakProcessor = ({
|
|
23893
|
+
totalPeaks,
|
|
23894
|
+
samplesPerPeak,
|
|
23895
|
+
onProgress,
|
|
23896
|
+
progressIntervalInMs,
|
|
23897
|
+
now
|
|
23898
|
+
}) => {
|
|
23899
|
+
const peaks = new Float32Array(totalPeaks);
|
|
23900
|
+
let peakIndex = 0;
|
|
23901
|
+
let peakMax = 0;
|
|
23902
|
+
let sampleInPeak = 0;
|
|
23903
|
+
let lastProgressAt = 0;
|
|
23904
|
+
let lastProgressPeak = 0;
|
|
23905
|
+
const emitProgress = (force) => {
|
|
23906
|
+
const timestamp = now();
|
|
23907
|
+
if (!force && peakIndex === lastProgressPeak && sampleInPeak === 0) {
|
|
23908
|
+
return;
|
|
23909
|
+
}
|
|
23910
|
+
if (!force && timestamp - lastProgressAt < progressIntervalInMs) {
|
|
23911
|
+
return;
|
|
23912
|
+
}
|
|
23913
|
+
lastProgressAt = timestamp;
|
|
23914
|
+
lastProgressPeak = peakIndex;
|
|
23915
|
+
emitWaveformProgress({
|
|
23916
|
+
peaks,
|
|
23917
|
+
completedPeaks: peakIndex,
|
|
23918
|
+
totalPeaks,
|
|
23919
|
+
final: force,
|
|
23920
|
+
onProgress
|
|
23921
|
+
});
|
|
23922
|
+
};
|
|
23923
|
+
return {
|
|
23924
|
+
peaks,
|
|
23925
|
+
processSampleChunk: (floats, channels) => {
|
|
23926
|
+
const frameCount = Math.floor(floats.length / Math.max(1, channels));
|
|
23927
|
+
for (let frame2 = 0;frame2 < frameCount; frame2++) {
|
|
23928
|
+
let framePeak = 0;
|
|
23929
|
+
for (let channel = 0;channel < channels; channel++) {
|
|
23930
|
+
const sampleIndex = frame2 * channels + channel;
|
|
23931
|
+
const abs = Math.abs(floats[sampleIndex] ?? 0);
|
|
23932
|
+
if (abs > framePeak) {
|
|
23933
|
+
framePeak = abs;
|
|
23934
|
+
}
|
|
23935
|
+
}
|
|
23936
|
+
if (framePeak > peakMax) {
|
|
23937
|
+
peakMax = framePeak;
|
|
23938
|
+
}
|
|
23939
|
+
sampleInPeak++;
|
|
23940
|
+
if (sampleInPeak >= samplesPerPeak) {
|
|
23941
|
+
if (peakIndex < totalPeaks) {
|
|
23942
|
+
peaks[peakIndex] = peakMax;
|
|
23943
|
+
}
|
|
23944
|
+
peakIndex++;
|
|
23945
|
+
peakMax = 0;
|
|
23946
|
+
sampleInPeak = 0;
|
|
23947
|
+
}
|
|
23948
|
+
}
|
|
23949
|
+
emitProgress(false);
|
|
23950
|
+
},
|
|
23951
|
+
finalize: () => {
|
|
23952
|
+
if (sampleInPeak > 0 && peakIndex < totalPeaks) {
|
|
23953
|
+
peaks[peakIndex] = peakMax;
|
|
23954
|
+
peakIndex++;
|
|
23955
|
+
}
|
|
23956
|
+
emitProgress(true);
|
|
23957
|
+
}
|
|
23958
|
+
};
|
|
23959
|
+
};
|
|
23960
|
+
|
|
23961
|
+
// src/components/load-waveform-peaks.ts
|
|
23841
23962
|
var TARGET_SAMPLE_RATE = 100;
|
|
23963
|
+
var DEFAULT_PROGRESS_INTERVAL_IN_MS = 50;
|
|
23842
23964
|
var peaksCache = new Map;
|
|
23843
|
-
async function loadWaveformPeaks(url, signal) {
|
|
23965
|
+
async function loadWaveformPeaks(url, signal, options) {
|
|
23844
23966
|
const cached = peaksCache.get(url);
|
|
23845
|
-
if (cached)
|
|
23967
|
+
if (cached) {
|
|
23968
|
+
emitWaveformProgress({
|
|
23969
|
+
peaks: cached,
|
|
23970
|
+
completedPeaks: cached.length,
|
|
23971
|
+
totalPeaks: cached.length,
|
|
23972
|
+
final: true,
|
|
23973
|
+
onProgress: options?.onProgress
|
|
23974
|
+
});
|
|
23846
23975
|
return cached;
|
|
23976
|
+
}
|
|
23847
23977
|
const input2 = new Input3({
|
|
23848
23978
|
formats: ALL_FORMATS3,
|
|
23849
23979
|
source: new UrlSource3(url)
|
|
@@ -23853,15 +23983,24 @@ async function loadWaveformPeaks(url, signal) {
|
|
|
23853
23983
|
if (!audioTrack) {
|
|
23854
23984
|
return new Float32Array(0);
|
|
23855
23985
|
}
|
|
23856
|
-
|
|
23857
|
-
|
|
23986
|
+
if (await audioTrack.isLive()) {
|
|
23987
|
+
throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + url);
|
|
23988
|
+
}
|
|
23989
|
+
if (await audioTrack.isRelativeToUnixEpoch()) {
|
|
23990
|
+
throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + url);
|
|
23991
|
+
}
|
|
23992
|
+
const sampleRate = await audioTrack.getSampleRate();
|
|
23993
|
+
const durationInSeconds = await audioTrack.getDurationFromMetadata({ skipLiveWait: true }) ?? await audioTrack.computeDuration({ skipLiveWait: true });
|
|
23858
23994
|
const totalPeaks = Math.ceil(durationInSeconds * TARGET_SAMPLE_RATE);
|
|
23859
23995
|
const samplesPerPeak = Math.max(1, Math.floor(sampleRate / TARGET_SAMPLE_RATE));
|
|
23860
|
-
const peaks = new Float32Array(totalPeaks);
|
|
23861
|
-
let peakIndex = 0;
|
|
23862
|
-
let peakMax = 0;
|
|
23863
|
-
let sampleInPeak = 0;
|
|
23864
23996
|
const sink = new AudioSampleSink(audioTrack);
|
|
23997
|
+
const processor = createWaveformPeakProcessor({
|
|
23998
|
+
totalPeaks,
|
|
23999
|
+
samplesPerPeak,
|
|
24000
|
+
onProgress: options?.onProgress,
|
|
24001
|
+
progressIntervalInMs: options?.progressIntervalInMs ?? DEFAULT_PROGRESS_INTERVAL_IN_MS,
|
|
24002
|
+
now: () => Date.now()
|
|
24003
|
+
});
|
|
23865
24004
|
for await (const sample of sink.samples()) {
|
|
23866
24005
|
if (signal.aborted) {
|
|
23867
24006
|
sample.close();
|
|
@@ -23874,34 +24013,11 @@ async function loadWaveformPeaks(url, signal) {
|
|
|
23874
24013
|
const floats = new Float32Array(bytesNeeded / 4);
|
|
23875
24014
|
sample.copyTo(floats, { format: "f32", planeIndex: 0 });
|
|
23876
24015
|
const channels = Math.max(1, sample.numberOfChannels);
|
|
23877
|
-
const frames = sample.numberOfFrames;
|
|
23878
24016
|
sample.close();
|
|
23879
|
-
|
|
23880
|
-
let framePeak = 0;
|
|
23881
|
-
for (let channel = 0;channel < channels; channel++) {
|
|
23882
|
-
const sampleIndex = frame2 * channels + channel;
|
|
23883
|
-
const abs = Math.abs(floats[sampleIndex] ?? 0);
|
|
23884
|
-
if (abs > framePeak) {
|
|
23885
|
-
framePeak = abs;
|
|
23886
|
-
}
|
|
23887
|
-
}
|
|
23888
|
-
if (framePeak > peakMax) {
|
|
23889
|
-
peakMax = framePeak;
|
|
23890
|
-
}
|
|
23891
|
-
sampleInPeak++;
|
|
23892
|
-
if (sampleInPeak >= samplesPerPeak) {
|
|
23893
|
-
if (peakIndex < totalPeaks) {
|
|
23894
|
-
peaks[peakIndex] = peakMax;
|
|
23895
|
-
}
|
|
23896
|
-
peakIndex++;
|
|
23897
|
-
peakMax = 0;
|
|
23898
|
-
sampleInPeak = 0;
|
|
23899
|
-
}
|
|
23900
|
-
}
|
|
23901
|
-
}
|
|
23902
|
-
if (sampleInPeak > 0 && peakIndex < totalPeaks) {
|
|
23903
|
-
peaks[peakIndex] = peakMax;
|
|
24017
|
+
processor.processSampleChunk(floats, channels);
|
|
23904
24018
|
}
|
|
24019
|
+
processor.finalize();
|
|
24020
|
+
const { peaks } = processor;
|
|
23905
24021
|
peaksCache.set(url, peaks);
|
|
23906
24022
|
return peaks;
|
|
23907
24023
|
} finally {
|
|
@@ -23909,8 +24025,50 @@ async function loadWaveformPeaks(url, signal) {
|
|
|
23909
24025
|
}
|
|
23910
24026
|
}
|
|
23911
24027
|
|
|
24028
|
+
// src/components/looped-media-timeline.ts
|
|
24029
|
+
var shouldTileLoopDisplay = (loopDisplay) => {
|
|
24030
|
+
return loopDisplay !== undefined && loopDisplay.numberOfTimes > 1;
|
|
24031
|
+
};
|
|
24032
|
+
var getLoopDisplayWidth = ({
|
|
24033
|
+
visualizationWidth,
|
|
24034
|
+
loopDisplay
|
|
24035
|
+
}) => {
|
|
24036
|
+
if (!shouldTileLoopDisplay(loopDisplay)) {
|
|
24037
|
+
return visualizationWidth;
|
|
24038
|
+
}
|
|
24039
|
+
return visualizationWidth / loopDisplay.numberOfTimes;
|
|
24040
|
+
};
|
|
24041
|
+
|
|
24042
|
+
// src/components/slice-waveform-peaks.ts
|
|
24043
|
+
var sliceWaveformPeaks = ({
|
|
24044
|
+
durationInFrames,
|
|
24045
|
+
fps,
|
|
24046
|
+
peaks,
|
|
24047
|
+
playbackRate,
|
|
24048
|
+
startFrom
|
|
24049
|
+
}) => {
|
|
24050
|
+
if (peaks.length === 0) {
|
|
24051
|
+
return peaks;
|
|
24052
|
+
}
|
|
24053
|
+
const startTimeInSeconds = startFrom / fps;
|
|
24054
|
+
const durationInSeconds = durationInFrames / fps * playbackRate;
|
|
24055
|
+
const startPeakIndex = Math.floor(startTimeInSeconds * TARGET_SAMPLE_RATE);
|
|
24056
|
+
const endPeakIndex = Math.ceil((startTimeInSeconds + durationInSeconds) * TARGET_SAMPLE_RATE);
|
|
24057
|
+
return peaks.subarray(Math.max(0, startPeakIndex), Math.min(peaks.length, endPeakIndex));
|
|
24058
|
+
};
|
|
24059
|
+
|
|
23912
24060
|
// src/components/AudioWaveform.tsx
|
|
23913
24061
|
import { jsx as jsx212, jsxs as jsxs102 } from "react/jsx-runtime";
|
|
24062
|
+
var EMPTY_PEAKS = new Float32Array(0);
|
|
24063
|
+
var canRetryCanvasTransfer = (err) => {
|
|
24064
|
+
return err instanceof DOMException && err.name === "InvalidStateError";
|
|
24065
|
+
};
|
|
24066
|
+
var canUseAudioWaveformWorker = () => {
|
|
24067
|
+
if (typeof Worker === "undefined" || typeof OffscreenCanvas === "undefined" || typeof HTMLCanvasElement === "undefined") {
|
|
24068
|
+
return false;
|
|
24069
|
+
}
|
|
24070
|
+
return "transferControlToOffscreen" in HTMLCanvasElement.prototype;
|
|
24071
|
+
};
|
|
23914
24072
|
var container43 = {
|
|
23915
24073
|
display: "flex",
|
|
23916
24074
|
flexDirection: "row",
|
|
@@ -23929,11 +24087,41 @@ var errorMessage = {
|
|
|
23929
24087
|
opacity: 0.75
|
|
23930
24088
|
};
|
|
23931
24089
|
var waveformCanvasStyle = {
|
|
23932
|
-
pointerEvents: "none"
|
|
24090
|
+
pointerEvents: "none",
|
|
24091
|
+
width: "100%",
|
|
24092
|
+
height: "100%"
|
|
23933
24093
|
};
|
|
23934
24094
|
var volumeCanvasStyle = {
|
|
23935
24095
|
position: "absolute"
|
|
23936
24096
|
};
|
|
24097
|
+
var drawLoopedWaveform = ({
|
|
24098
|
+
canvas,
|
|
24099
|
+
peaks,
|
|
24100
|
+
volume,
|
|
24101
|
+
visualizationWidth,
|
|
24102
|
+
loopWidth
|
|
24103
|
+
}) => {
|
|
24104
|
+
const h = canvas.height;
|
|
24105
|
+
const w = Math.ceil(visualizationWidth);
|
|
24106
|
+
const targetCanvas = document.createElement("canvas");
|
|
24107
|
+
targetCanvas.width = Math.max(1, Math.ceil(loopWidth));
|
|
24108
|
+
targetCanvas.height = h;
|
|
24109
|
+
drawBars(targetCanvas, peaks, "rgba(255, 255, 255, 0.6)", volume, targetCanvas.width);
|
|
24110
|
+
canvas.width = w;
|
|
24111
|
+
canvas.height = h;
|
|
24112
|
+
const ctx = canvas.getContext("2d");
|
|
24113
|
+
if (!ctx) {
|
|
24114
|
+
throw new Error("Failed to get canvas context");
|
|
24115
|
+
}
|
|
24116
|
+
const pattern = ctx.createPattern(targetCanvas, "repeat-x");
|
|
24117
|
+
if (!pattern) {
|
|
24118
|
+
return;
|
|
24119
|
+
}
|
|
24120
|
+
pattern.setTransform(new DOMMatrix().scaleSelf(loopWidth / targetCanvas.width, 1));
|
|
24121
|
+
ctx.clearRect(0, 0, w, h);
|
|
24122
|
+
ctx.fillStyle = pattern;
|
|
24123
|
+
ctx.fillRect(0, 0, w, h);
|
|
24124
|
+
};
|
|
23937
24125
|
var AudioWaveform = ({
|
|
23938
24126
|
src,
|
|
23939
24127
|
startFrom,
|
|
@@ -23941,10 +24129,13 @@ var AudioWaveform = ({
|
|
|
23941
24129
|
visualizationWidth,
|
|
23942
24130
|
volume,
|
|
23943
24131
|
doesVolumeChange,
|
|
23944
|
-
playbackRate
|
|
24132
|
+
playbackRate,
|
|
24133
|
+
loopDisplay
|
|
23945
24134
|
}) => {
|
|
23946
24135
|
const [peaks, setPeaks] = useState79(null);
|
|
23947
24136
|
const [error, setError] = useState79(null);
|
|
24137
|
+
const [waveformCanvasKey, setWaveformCanvasKey] = useState79(0);
|
|
24138
|
+
const canUseWorkerPath = useMemo119(() => canUseAudioWaveformWorker(), []);
|
|
23948
24139
|
const vidConf = Internals55.useUnsafeVideoConfig();
|
|
23949
24140
|
if (vidConf === null) {
|
|
23950
24141
|
throw new Error("Expected video config");
|
|
@@ -23952,8 +24143,15 @@ var AudioWaveform = ({
|
|
|
23952
24143
|
const containerRef = useRef43(null);
|
|
23953
24144
|
const waveformCanvas = useRef43(null);
|
|
23954
24145
|
const volumeCanvas = useRef43(null);
|
|
24146
|
+
const waveformWorker = useRef43(null);
|
|
24147
|
+
const hasTransferredCanvas = useRef43(false);
|
|
24148
|
+
const latestRequestId = useRef43(0);
|
|
23955
24149
|
useEffect73(() => {
|
|
24150
|
+
if (canUseWorkerPath) {
|
|
24151
|
+
return;
|
|
24152
|
+
}
|
|
23956
24153
|
const controller = new AbortController;
|
|
24154
|
+
setPeaks(null);
|
|
23957
24155
|
setError(null);
|
|
23958
24156
|
loadWaveformPeaks(src, controller.signal).then((p) => {
|
|
23959
24157
|
if (!controller.signal.aborted) {
|
|
@@ -23965,30 +24163,127 @@ var AudioWaveform = ({
|
|
|
23965
24163
|
}
|
|
23966
24164
|
});
|
|
23967
24165
|
return () => controller.abort();
|
|
23968
|
-
}, [src]);
|
|
24166
|
+
}, [canUseWorkerPath, src]);
|
|
24167
|
+
useEffect73(() => {
|
|
24168
|
+
if (!canUseWorkerPath) {
|
|
24169
|
+
return;
|
|
24170
|
+
}
|
|
24171
|
+
const canvasElement = waveformCanvas.current;
|
|
24172
|
+
if (!canvasElement || hasTransferredCanvas.current) {
|
|
24173
|
+
return;
|
|
24174
|
+
}
|
|
24175
|
+
const worker = makeAudioWaveformWorker();
|
|
24176
|
+
waveformWorker.current = worker;
|
|
24177
|
+
worker.addEventListener("message", (event) => {
|
|
24178
|
+
if (event.data.type === "error") {
|
|
24179
|
+
if (event.data.requestId !== latestRequestId.current) {
|
|
24180
|
+
return;
|
|
24181
|
+
}
|
|
24182
|
+
setError(new Error(event.data.message));
|
|
24183
|
+
}
|
|
24184
|
+
});
|
|
24185
|
+
let offscreen;
|
|
24186
|
+
try {
|
|
24187
|
+
offscreen = canvasElement.transferControlToOffscreen();
|
|
24188
|
+
} catch (err) {
|
|
24189
|
+
worker.terminate();
|
|
24190
|
+
waveformWorker.current = null;
|
|
24191
|
+
if (canRetryCanvasTransfer(err)) {
|
|
24192
|
+
setWaveformCanvasKey((key4) => key4 + 1);
|
|
24193
|
+
return;
|
|
24194
|
+
}
|
|
24195
|
+
throw err;
|
|
24196
|
+
}
|
|
24197
|
+
hasTransferredCanvas.current = true;
|
|
24198
|
+
worker.postMessage({ type: "init", canvas: offscreen }, [offscreen]);
|
|
24199
|
+
return () => {
|
|
24200
|
+
worker.postMessage({ type: "dispose" });
|
|
24201
|
+
worker.terminate();
|
|
24202
|
+
waveformWorker.current = null;
|
|
24203
|
+
hasTransferredCanvas.current = false;
|
|
24204
|
+
};
|
|
24205
|
+
}, [canUseWorkerPath, waveformCanvasKey]);
|
|
23969
24206
|
const portionPeaks = useMemo119(() => {
|
|
23970
|
-
if (
|
|
24207
|
+
if (canUseWorkerPath || !peaks) {
|
|
23971
24208
|
return null;
|
|
23972
24209
|
}
|
|
23973
|
-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
24210
|
+
return sliceWaveformPeaks({
|
|
24211
|
+
durationInFrames: shouldTileLoopDisplay(loopDisplay) ? loopDisplay.durationInFrames : durationInFrames,
|
|
24212
|
+
fps: vidConf.fps,
|
|
24213
|
+
peaks,
|
|
24214
|
+
playbackRate,
|
|
24215
|
+
startFrom
|
|
24216
|
+
});
|
|
24217
|
+
}, [
|
|
24218
|
+
canUseWorkerPath,
|
|
24219
|
+
durationInFrames,
|
|
24220
|
+
loopDisplay,
|
|
24221
|
+
peaks,
|
|
24222
|
+
playbackRate,
|
|
24223
|
+
startFrom,
|
|
24224
|
+
vidConf.fps
|
|
24225
|
+
]);
|
|
23979
24226
|
useEffect73(() => {
|
|
23980
24227
|
const { current: canvasElement } = waveformCanvas;
|
|
23981
24228
|
const { current: containerElement } = containerRef;
|
|
23982
|
-
if (!canvasElement || !containerElement
|
|
24229
|
+
if (!canvasElement || !containerElement) {
|
|
23983
24230
|
return;
|
|
23984
24231
|
}
|
|
23985
24232
|
const h = containerElement.clientHeight;
|
|
23986
24233
|
const w = Math.ceil(visualizationWidth);
|
|
24234
|
+
const vol = typeof volume === "number" ? volume : 1;
|
|
24235
|
+
if (canUseWorkerPath) {
|
|
24236
|
+
const worker = waveformWorker.current;
|
|
24237
|
+
if (!worker || !hasTransferredCanvas.current) {
|
|
24238
|
+
return;
|
|
24239
|
+
}
|
|
24240
|
+
latestRequestId.current += 1;
|
|
24241
|
+
setError(null);
|
|
24242
|
+
const message = {
|
|
24243
|
+
type: "render",
|
|
24244
|
+
requestId: latestRequestId.current,
|
|
24245
|
+
src,
|
|
24246
|
+
width: w,
|
|
24247
|
+
height: h,
|
|
24248
|
+
volume: vol,
|
|
24249
|
+
startFrom,
|
|
24250
|
+
durationInFrames,
|
|
24251
|
+
fps: vidConf.fps,
|
|
24252
|
+
playbackRate,
|
|
24253
|
+
loopDisplay
|
|
24254
|
+
};
|
|
24255
|
+
worker.postMessage(message);
|
|
24256
|
+
return;
|
|
24257
|
+
}
|
|
23987
24258
|
canvasElement.width = w;
|
|
23988
24259
|
canvasElement.height = h;
|
|
23989
|
-
|
|
23990
|
-
|
|
23991
|
-
|
|
24260
|
+
if (shouldTileLoopDisplay(loopDisplay)) {
|
|
24261
|
+
drawLoopedWaveform({
|
|
24262
|
+
canvas: canvasElement,
|
|
24263
|
+
peaks: portionPeaks ?? EMPTY_PEAKS,
|
|
24264
|
+
volume: vol,
|
|
24265
|
+
visualizationWidth,
|
|
24266
|
+
loopWidth: getLoopDisplayWidth({
|
|
24267
|
+
visualizationWidth,
|
|
24268
|
+
loopDisplay
|
|
24269
|
+
})
|
|
24270
|
+
});
|
|
24271
|
+
} else {
|
|
24272
|
+
drawBars(canvasElement, portionPeaks ?? EMPTY_PEAKS, "rgba(255, 255, 255, 0.6)", vol, w);
|
|
24273
|
+
}
|
|
24274
|
+
}, [
|
|
24275
|
+
canUseWorkerPath,
|
|
24276
|
+
durationInFrames,
|
|
24277
|
+
loopDisplay,
|
|
24278
|
+
playbackRate,
|
|
24279
|
+
portionPeaks,
|
|
24280
|
+
src,
|
|
24281
|
+
startFrom,
|
|
24282
|
+
vidConf.fps,
|
|
24283
|
+
visualizationWidth,
|
|
24284
|
+
volume,
|
|
24285
|
+
waveformCanvasKey
|
|
24286
|
+
]);
|
|
23992
24287
|
useEffect73(() => {
|
|
23993
24288
|
const { current: volumeCanvasElement } = volumeCanvas;
|
|
23994
24289
|
const { current: containerElement } = containerRef;
|
|
@@ -24022,6 +24317,7 @@ var AudioWaveform = ({
|
|
|
24022
24317
|
context.stroke();
|
|
24023
24318
|
}, [visualizationWidth, volume, doesVolumeChange]);
|
|
24024
24319
|
if (error) {
|
|
24320
|
+
console.error(error);
|
|
24025
24321
|
return /* @__PURE__ */ jsx212("div", {
|
|
24026
24322
|
style: container43,
|
|
24027
24323
|
children: /* @__PURE__ */ jsx212("div", {
|
|
@@ -24030,7 +24326,7 @@ var AudioWaveform = ({
|
|
|
24030
24326
|
})
|
|
24031
24327
|
});
|
|
24032
24328
|
}
|
|
24033
|
-
if (!peaks) {
|
|
24329
|
+
if (!canUseWorkerPath && !peaks) {
|
|
24034
24330
|
return null;
|
|
24035
24331
|
}
|
|
24036
24332
|
return /* @__PURE__ */ jsxs102("div", {
|
|
@@ -24040,7 +24336,7 @@ var AudioWaveform = ({
|
|
|
24040
24336
|
/* @__PURE__ */ jsx212("canvas", {
|
|
24041
24337
|
ref: waveformCanvas,
|
|
24042
24338
|
style: waveformCanvasStyle
|
|
24043
|
-
}),
|
|
24339
|
+
}, waveformCanvasKey),
|
|
24044
24340
|
/* @__PURE__ */ jsx212("canvas", {
|
|
24045
24341
|
ref: volumeCanvas,
|
|
24046
24342
|
style: volumeCanvasStyle
|
|
@@ -24063,7 +24359,8 @@ var width = {
|
|
|
24063
24359
|
position: "relative"
|
|
24064
24360
|
};
|
|
24065
24361
|
var icon4 = {
|
|
24066
|
-
height: 12
|
|
24362
|
+
height: 12,
|
|
24363
|
+
filter: "drop-shadow(0 0 2px rgba(0, 0, 0, 0.9)) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.8))"
|
|
24067
24364
|
};
|
|
24068
24365
|
var Icon = () => /* @__PURE__ */ jsx213("svg", {
|
|
24069
24366
|
viewBox: "0 0 512 512",
|
|
@@ -24073,44 +24370,23 @@ var Icon = () => /* @__PURE__ */ jsx213("svg", {
|
|
|
24073
24370
|
d: "M512 256c0 88.224-71.775 160-160 160H170.067l34.512 32.419c9.875 9.276 10.119 24.883.539 34.464l-10.775 10.775c-9.373 9.372-24.568 9.372-33.941 0l-92.686-92.686c-9.373-9.373-9.373-24.568 0-33.941l92.686-92.686c9.373-9.373 24.568-9.373 33.941 0l10.775 10.775c9.581 9.581 9.337 25.187-.539 34.464L170.067 352H352c52.935 0 96-43.065 96-96 0-13.958-2.996-27.228-8.376-39.204-4.061-9.039-2.284-19.626 4.723-26.633l12.183-12.183c11.499-11.499 30.965-8.526 38.312 5.982C505.814 205.624 512 230.103 512 256zM72.376 295.204C66.996 283.228 64 269.958 64 256c0-52.935 43.065-96 96-96h181.933l-34.512 32.419c-9.875 9.276-10.119 24.883-.539 34.464l10.775 10.775c9.373 9.372 24.568 9.372 33.941 0l92.686-92.686c9.373-9.373 9.373-24.568 0-33.941l-92.686-92.686c-9.373-9.373-24.568-9.373-33.941 0L306.882 29.12c-9.581 9.581-9.337 25.187.539 34.464L341.933 96H160C71.775 96 0 167.776 0 256c0 25.897 6.186 50.376 17.157 72.039 7.347 14.508 26.813 17.481 38.312 5.982l12.183-12.183c7.008-7.008 8.786-17.595 4.724-26.634z"
|
|
24074
24371
|
})
|
|
24075
24372
|
});
|
|
24076
|
-
var
|
|
24077
|
-
|
|
24078
|
-
height: 2,
|
|
24079
|
-
width: 1,
|
|
24080
|
-
background: LIGHT_COLOR
|
|
24081
|
-
};
|
|
24082
|
-
var bottomLine = {
|
|
24083
|
-
top: 0,
|
|
24084
|
-
height: 2,
|
|
24373
|
+
var verticalLine = {
|
|
24374
|
+
height: "100%",
|
|
24085
24375
|
width: 1,
|
|
24086
|
-
background:
|
|
24087
|
-
};
|
|
24088
|
-
var topContainer = {
|
|
24089
|
-
justifyContent: "flex-start",
|
|
24090
|
-
alignItems: "center"
|
|
24376
|
+
background: "rgb(255,255,255, 0.5)"
|
|
24091
24377
|
};
|
|
24092
24378
|
var centerContainer = {
|
|
24093
24379
|
justifyContent: "center",
|
|
24094
24380
|
alignItems: "center"
|
|
24095
24381
|
};
|
|
24096
|
-
var bottomContainer = {
|
|
24097
|
-
justifyContent: "flex-end",
|
|
24098
|
-
alignItems: "center"
|
|
24099
|
-
};
|
|
24100
24382
|
var LoopedIndicator = () => {
|
|
24101
24383
|
return /* @__PURE__ */ jsxs103("div", {
|
|
24102
24384
|
style: width,
|
|
24103
24385
|
children: [
|
|
24104
24386
|
/* @__PURE__ */ jsx213(AbsoluteFill5, {
|
|
24105
|
-
style:
|
|
24106
|
-
children: /* @__PURE__ */ jsx213("div", {
|
|
24107
|
-
style: topLine
|
|
24108
|
-
})
|
|
24109
|
-
}),
|
|
24110
|
-
/* @__PURE__ */ jsx213(AbsoluteFill5, {
|
|
24111
|
-
style: bottomContainer,
|
|
24387
|
+
style: centerContainer,
|
|
24112
24388
|
children: /* @__PURE__ */ jsx213("div", {
|
|
24113
|
-
style:
|
|
24389
|
+
style: verticalLine
|
|
24114
24390
|
})
|
|
24115
24391
|
}),
|
|
24116
24392
|
/* @__PURE__ */ jsx213(AbsoluteFill5, {
|
|
@@ -24253,17 +24529,23 @@ async function extractFrames({
|
|
|
24253
24529
|
}
|
|
24254
24530
|
try {
|
|
24255
24531
|
const [durationInSeconds, format, videoTrack] = await Promise.all([
|
|
24256
|
-
input2
|
|
24532
|
+
getDurationOrCompute(input2),
|
|
24257
24533
|
input2.getFormat(),
|
|
24258
24534
|
input2.getPrimaryVideoTrack()
|
|
24259
24535
|
]);
|
|
24260
24536
|
if (!videoTrack) {
|
|
24261
24537
|
throw new Error("No video track found in the input");
|
|
24262
24538
|
}
|
|
24539
|
+
if (await videoTrack.isLive()) {
|
|
24540
|
+
throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + src);
|
|
24541
|
+
}
|
|
24542
|
+
if (await videoTrack.isRelativeToUnixEpoch()) {
|
|
24543
|
+
throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + src);
|
|
24544
|
+
}
|
|
24263
24545
|
const timestamps = typeof timestampsInSeconds === "function" ? await timestampsInSeconds({
|
|
24264
24546
|
track: {
|
|
24265
|
-
width: videoTrack.
|
|
24266
|
-
height: videoTrack.
|
|
24547
|
+
width: await videoTrack.getDisplayWidth(),
|
|
24548
|
+
height: await videoTrack.getDisplayHeight()
|
|
24267
24549
|
},
|
|
24268
24550
|
container: format.name,
|
|
24269
24551
|
durationInSeconds
|
|
@@ -24582,7 +24864,8 @@ var TimelineVideoInfo = ({
|
|
|
24582
24864
|
volume,
|
|
24583
24865
|
doesVolumeChange,
|
|
24584
24866
|
premountWidth,
|
|
24585
|
-
postmountWidth
|
|
24867
|
+
postmountWidth,
|
|
24868
|
+
loopDisplay
|
|
24586
24869
|
}) => {
|
|
24587
24870
|
const { fps } = useVideoConfig5();
|
|
24588
24871
|
const ref2 = useRef45(null);
|
|
@@ -24605,25 +24888,54 @@ var TimelineVideoInfo = ({
|
|
|
24605
24888
|
return;
|
|
24606
24889
|
}
|
|
24607
24890
|
current.appendChild(canvas);
|
|
24891
|
+
const loopWidth = getLoopDisplayWidth({
|
|
24892
|
+
visualizationWidth: naturalWidth,
|
|
24893
|
+
loopDisplay
|
|
24894
|
+
});
|
|
24895
|
+
const shouldRepeatVideo = shouldTileLoopDisplay(loopDisplay);
|
|
24896
|
+
const targetCanvas = shouldRepeatVideo ? document.createElement("canvas") : canvas;
|
|
24897
|
+
targetCanvas.width = shouldRepeatVideo ? Math.max(1, Math.ceil(loopWidth)) : canvas.width;
|
|
24898
|
+
targetCanvas.height = canvas.height;
|
|
24899
|
+
const targetCtx = shouldRepeatVideo ? targetCanvas.getContext("2d") : ctx;
|
|
24900
|
+
if (!targetCtx) {
|
|
24901
|
+
current.removeChild(canvas);
|
|
24902
|
+
return;
|
|
24903
|
+
}
|
|
24904
|
+
const repeatTarget = () => {
|
|
24905
|
+
if (!shouldRepeatVideo) {
|
|
24906
|
+
return;
|
|
24907
|
+
}
|
|
24908
|
+
const pattern = ctx.createPattern(targetCanvas, "repeat-x");
|
|
24909
|
+
if (!pattern) {
|
|
24910
|
+
return;
|
|
24911
|
+
}
|
|
24912
|
+
pattern.setTransform(new DOMMatrix().scaleSelf(loopWidth / targetCanvas.width, 1));
|
|
24913
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
24914
|
+
ctx.fillStyle = pattern;
|
|
24915
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
24916
|
+
};
|
|
24608
24917
|
const filledSlots = new Map;
|
|
24609
24918
|
const fromSeconds = trimBefore / fps;
|
|
24610
|
-
const
|
|
24919
|
+
const visibleDurationInFrames = shouldRepeatVideo && loopDisplay ? loopDisplay.durationInFrames : durationInFrames;
|
|
24920
|
+
const toSeconds = fromSeconds + visibleDurationInFrames * playbackRate / fps;
|
|
24921
|
+
const targetWidth = shouldRepeatVideo ? targetCanvas.width : naturalWidth;
|
|
24611
24922
|
if (aspectRatio.current !== null) {
|
|
24612
24923
|
ensureSlots({
|
|
24613
24924
|
filledSlots,
|
|
24614
|
-
naturalWidth,
|
|
24925
|
+
naturalWidth: targetWidth,
|
|
24615
24926
|
fromSeconds,
|
|
24616
24927
|
toSeconds,
|
|
24617
24928
|
aspectRatio: aspectRatio.current
|
|
24618
24929
|
});
|
|
24619
24930
|
fillWithCachedFrames({
|
|
24620
|
-
ctx,
|
|
24621
|
-
naturalWidth,
|
|
24931
|
+
ctx: targetCtx,
|
|
24932
|
+
naturalWidth: targetWidth,
|
|
24622
24933
|
filledSlots,
|
|
24623
24934
|
src,
|
|
24624
24935
|
segmentDuration: toSeconds - fromSeconds,
|
|
24625
24936
|
fromSeconds
|
|
24626
24937
|
});
|
|
24938
|
+
repeatTarget();
|
|
24627
24939
|
const unfilled = Array.from(filledSlots.keys()).filter((timestamp) => !filledSlots.get(timestamp));
|
|
24628
24940
|
if (unfilled.length === 0) {
|
|
24629
24941
|
return () => {
|
|
@@ -24641,7 +24953,7 @@ var TimelineVideoInfo = ({
|
|
|
24641
24953
|
filledSlots,
|
|
24642
24954
|
fromSeconds,
|
|
24643
24955
|
toSeconds,
|
|
24644
|
-
naturalWidth,
|
|
24956
|
+
naturalWidth: targetWidth,
|
|
24645
24957
|
aspectRatio: aspectRatio.current
|
|
24646
24958
|
});
|
|
24647
24959
|
return Array.from(filledSlots.keys()).map((timestamp) => timestamp / WEBCODECS_TIMESCALE);
|
|
@@ -24669,17 +24981,18 @@ var TimelineVideoInfo = ({
|
|
|
24669
24981
|
filledSlots,
|
|
24670
24982
|
fromSeconds,
|
|
24671
24983
|
toSeconds,
|
|
24672
|
-
naturalWidth,
|
|
24984
|
+
naturalWidth: targetWidth,
|
|
24673
24985
|
aspectRatio: aspectRatio.current
|
|
24674
24986
|
});
|
|
24675
24987
|
fillFrameWhereItFits({
|
|
24676
|
-
ctx,
|
|
24988
|
+
ctx: targetCtx,
|
|
24677
24989
|
filledSlots,
|
|
24678
|
-
visualizationWidth:
|
|
24990
|
+
visualizationWidth: targetWidth,
|
|
24679
24991
|
frame: transformed,
|
|
24680
24992
|
segmentDuration: toSeconds - fromSeconds,
|
|
24681
24993
|
fromSeconds
|
|
24682
24994
|
});
|
|
24995
|
+
repeatTarget();
|
|
24683
24996
|
} catch (e) {
|
|
24684
24997
|
if (frame2) {
|
|
24685
24998
|
frame2.close();
|
|
@@ -24695,13 +25008,14 @@ var TimelineVideoInfo = ({
|
|
|
24695
25008
|
return;
|
|
24696
25009
|
}
|
|
24697
25010
|
fillWithCachedFrames({
|
|
24698
|
-
ctx,
|
|
24699
|
-
naturalWidth,
|
|
25011
|
+
ctx: targetCtx,
|
|
25012
|
+
naturalWidth: targetWidth,
|
|
24700
25013
|
filledSlots,
|
|
24701
25014
|
src,
|
|
24702
25015
|
segmentDuration: toSeconds - fromSeconds,
|
|
24703
25016
|
fromSeconds
|
|
24704
25017
|
});
|
|
25018
|
+
repeatTarget();
|
|
24705
25019
|
}).catch((e) => {
|
|
24706
25020
|
setError(e);
|
|
24707
25021
|
});
|
|
@@ -24713,6 +25027,7 @@ var TimelineVideoInfo = ({
|
|
|
24713
25027
|
durationInFrames,
|
|
24714
25028
|
error,
|
|
24715
25029
|
fps,
|
|
25030
|
+
loopDisplay,
|
|
24716
25031
|
naturalWidth,
|
|
24717
25032
|
playbackRate,
|
|
24718
25033
|
src,
|
|
@@ -24744,7 +25059,8 @@ var TimelineVideoInfo = ({
|
|
|
24744
25059
|
durationInFrames,
|
|
24745
25060
|
volume,
|
|
24746
25061
|
doesVolumeChange,
|
|
24747
|
-
playbackRate
|
|
25062
|
+
playbackRate,
|
|
25063
|
+
loopDisplay
|
|
24748
25064
|
})
|
|
24749
25065
|
})
|
|
24750
25066
|
]
|
|
@@ -24769,29 +25085,37 @@ var TimelineSequence = ({ s }) => {
|
|
|
24769
25085
|
var Inner4 = ({ s, windowWidth }) => {
|
|
24770
25086
|
const video = Internals56.useVideo();
|
|
24771
25087
|
const maxMediaDuration = useMaxMediaDuration(s, video?.fps ?? 30);
|
|
25088
|
+
const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
|
|
24772
25089
|
if (!video) {
|
|
24773
25090
|
throw new TypeError("Expected video config");
|
|
24774
25091
|
}
|
|
24775
25092
|
const frame2 = useCurrentFrame2();
|
|
24776
25093
|
const relativeFrame = frame2 - s.from;
|
|
25094
|
+
const displayDurationInFrames = s.loopDisplay ? s.loopDisplay.durationInFrames * s.loopDisplay.numberOfTimes : s.duration;
|
|
24777
25095
|
const relativeFrameWithPremount = relativeFrame + (s.premountDisplay ?? 0);
|
|
24778
|
-
const relativeFrameWithPostmount = relativeFrame -
|
|
25096
|
+
const relativeFrameWithPostmount = relativeFrame - displayDurationInFrames;
|
|
24779
25097
|
const roundedFrame = Math.round(relativeFrame * 100) / 100;
|
|
24780
|
-
const isInRange = relativeFrame >= 0 && relativeFrame <
|
|
24781
|
-
const isPremounting = relativeFrameWithPremount >= 0 && relativeFrameWithPremount <
|
|
25098
|
+
const isInRange = relativeFrame >= 0 && relativeFrame < displayDurationInFrames;
|
|
25099
|
+
const isPremounting = relativeFrameWithPremount >= 0 && relativeFrameWithPremount < displayDurationInFrames && !isInRange;
|
|
24782
25100
|
const isPostmounting = relativeFrameWithPostmount >= 0 && relativeFrameWithPostmount < (s.postmountDisplay ?? 0) && !isInRange;
|
|
24783
25101
|
const { marginLeft, width: width2, naturalWidth, premountWidth, postmountWidth } = useMemo121(() => {
|
|
24784
25102
|
return getTimelineSequenceLayout({
|
|
24785
|
-
durationInFrames:
|
|
25103
|
+
durationInFrames: displayDurationInFrames,
|
|
24786
25104
|
startFrom: s.loopDisplay ? s.from + s.loopDisplay.startOffset : s.from,
|
|
24787
25105
|
startFromMedia: s.type === "sequence" || s.type === "image" ? 0 : s.startMediaFrom,
|
|
24788
|
-
maxMediaDuration,
|
|
25106
|
+
maxMediaDuration: effectiveMaxMediaDuration,
|
|
24789
25107
|
video,
|
|
24790
25108
|
windowWidth,
|
|
24791
25109
|
premountDisplay: s.premountDisplay,
|
|
24792
25110
|
postmountDisplay: s.postmountDisplay
|
|
24793
25111
|
});
|
|
24794
|
-
}, [
|
|
25112
|
+
}, [
|
|
25113
|
+
displayDurationInFrames,
|
|
25114
|
+
effectiveMaxMediaDuration,
|
|
25115
|
+
s,
|
|
25116
|
+
video,
|
|
25117
|
+
windowWidth
|
|
25118
|
+
]);
|
|
24795
25119
|
const style11 = useMemo121(() => {
|
|
24796
25120
|
return {
|
|
24797
25121
|
background: s.type === "audio" ? AUDIO_GRADIENT : s.type === "video" ? VIDEO_GRADIENT : s.type === "image" ? IMAGE_GRADIENT : BLUE,
|
|
@@ -24806,7 +25130,7 @@ var Inner4 = ({ s, windowWidth }) => {
|
|
|
24806
25130
|
opacity: isInRange ? 1 : 0.5
|
|
24807
25131
|
};
|
|
24808
25132
|
}, [isInRange, marginLeft, s.type, width2]);
|
|
24809
|
-
if (maxMediaDuration === null) {
|
|
25133
|
+
if (maxMediaDuration === null && !s.loopDisplay) {
|
|
24810
25134
|
return null;
|
|
24811
25135
|
}
|
|
24812
25136
|
return /* @__PURE__ */ jsxs106("div", {
|
|
@@ -24849,7 +25173,8 @@ var Inner4 = ({ s, windowWidth }) => {
|
|
|
24849
25173
|
startFrom: s.startMediaFrom,
|
|
24850
25174
|
durationInFrames: s.duration,
|
|
24851
25175
|
volume: s.volume,
|
|
24852
|
-
playbackRate: s.playbackRate
|
|
25176
|
+
playbackRate: s.playbackRate,
|
|
25177
|
+
loopDisplay: s.loopDisplay
|
|
24853
25178
|
}) : null,
|
|
24854
25179
|
s.type === "video" ? /* @__PURE__ */ jsx218(TimelineVideoInfo, {
|
|
24855
25180
|
src: s.src,
|
|
@@ -24861,7 +25186,8 @@ var Inner4 = ({ s, windowWidth }) => {
|
|
|
24861
25186
|
volume: s.volume,
|
|
24862
25187
|
doesVolumeChange: s.doesVolumeChange,
|
|
24863
25188
|
premountWidth: premountWidth ?? 0,
|
|
24864
|
-
postmountWidth: postmountWidth ?? 0
|
|
25189
|
+
postmountWidth: postmountWidth ?? 0,
|
|
25190
|
+
loopDisplay: s.loopDisplay
|
|
24865
25191
|
}) : null,
|
|
24866
25192
|
s.type === "image" ? /* @__PURE__ */ jsx218(TimelineImageInfo, {
|
|
24867
25193
|
src: s.src,
|