@waveform-playlist/browser 11.2.0 → 11.3.0
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/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +70 -86
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +71 -87
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.d.mts
CHANGED
|
@@ -41,6 +41,15 @@ interface TrackState$1 {
|
|
|
41
41
|
volume: number;
|
|
42
42
|
pan: number;
|
|
43
43
|
}
|
|
44
|
+
/** Per-frame data passed to registered animation callbacks. */
|
|
45
|
+
interface FrameData {
|
|
46
|
+
/** Raw engine time (for state/logic — NOT for visual positioning). */
|
|
47
|
+
readonly time: number;
|
|
48
|
+
/** time - outputLatency (for DOM positioning — matches speaker output). */
|
|
49
|
+
readonly visualTime: number;
|
|
50
|
+
readonly sampleRate: number;
|
|
51
|
+
readonly samplesPerPixel: number;
|
|
52
|
+
}
|
|
44
53
|
interface PlaybackAnimationContextValue {
|
|
45
54
|
isPlaying: boolean;
|
|
46
55
|
currentTime: number;
|
|
@@ -49,6 +58,10 @@ interface PlaybackAnimationContextValue {
|
|
|
49
58
|
audioStartPositionRef: React__default.RefObject<number>;
|
|
50
59
|
/** Returns current playback time from engine (auto-wraps at loop boundaries). */
|
|
51
60
|
getPlaybackTime: () => number;
|
|
61
|
+
/** Register a per-frame callback driven by the single animation loop. */
|
|
62
|
+
registerFrameCallback: (id: string, cb: (data: FrameData) => void) => void;
|
|
63
|
+
/** Unregister a per-frame callback. */
|
|
64
|
+
unregisterFrameCallback: (id: string) => void;
|
|
52
65
|
}
|
|
53
66
|
interface PlaylistStateContextValue {
|
|
54
67
|
continuousPlay: boolean;
|
|
@@ -1174,7 +1187,7 @@ declare const TimeFormatSelect: React__default.FC<{
|
|
|
1174
1187
|
}>;
|
|
1175
1188
|
/**
|
|
1176
1189
|
* Audio position display that uses the playlist context.
|
|
1177
|
-
*
|
|
1190
|
+
* Updates via the shared animation frame registry — no own rAF loop.
|
|
1178
1191
|
* Direct DOM manipulation avoids React re-renders.
|
|
1179
1192
|
*/
|
|
1180
1193
|
declare const AudioPosition: React__default.FC<{
|
|
@@ -1811,4 +1824,4 @@ declare function getWaveformDataMetadata(src: string): Promise<{
|
|
|
1811
1824
|
bits: 8 | 16;
|
|
1812
1825
|
}>;
|
|
1813
1826
|
|
|
1814
|
-
export { type ActiveEffect, type AnnotationIntegration, AnnotationIntegrationProvider, AudioPosition, type AudioTrackConfig, AutomaticScrollCheckbox, ClearAllButton, type ClearAllButtonProps, ClipCollisionModifier, ClipInteractionProvider, type ClipInteractionProviderProps, ContinuousPlayCheckbox, DownloadAnnotationsButton, EditableCheckbox, type EffectDefinition, type EffectInstance, type EffectParameter, type ExportOptions, type ExportResult, ExportWavButton, type ExportWavButtonProps, FastForwardButton, type GetAnnotationBoxLabelFn, KeyboardShortcuts, type KeyboardShortcutsProps, LinkEndpointsCheckbox, LoopButton, MasterVolumeControl, type MasterVolumeControls, type MediaElementAnimationContextValue, MediaElementAnnotationList, type MediaElementAnnotationListProps, type MediaElementControlsContextValue, type MediaElementDataContextValue, MediaElementPlaylist, type MediaElementPlaylistProps, MediaElementPlaylistProvider, type MediaElementStateContextValue, type MediaElementTrackConfig, MediaElementWaveform, type MediaElementWaveformProps, type OnAnnotationUpdateFn, type ParameterType, PauseButton, PlayButton, PlaylistAnnotationList, type PlaylistAnnotationListProps, PlaylistVisualization, type PlaylistVisualizationProps, RewindButton, SelectionTimeInputs, SetLoopRegionButton, SkipBackwardButton, SkipForwardButton, SnapToGridModifier, type SpectrogramIntegration, SpectrogramIntegrationProvider, StopButton, type TimeFormatControls, TimeFormatSelect, type TrackActiveEffect, type TrackEffectsState, type TrackLoadError, type TrackSource, type TrackState$1 as TrackState, type UseDynamicEffectsReturn, type UseDynamicTracksReturn, type UseExportWavReturn, type UseOutputMeterOptions, type UseOutputMeterReturn, type UsePlaybackShortcutsOptions, type UsePlaybackShortcutsReturn, type UseTrackDynamicEffectsReturn, Waveform, WaveformPlaylistProvider, type WaveformProps, type WaveformTrack, type ZoomControls, ZoomInButton, ZoomOutButton, createEffectChain, createEffectInstance, effectCategories, effectDefinitions, getEffectDefinition, getEffectsByCategory, getWaveformDataMetadata, loadPeaksFromWaveformData, loadWaveformData, noDropAnimationPlugins, useAnnotationDragHandlers, useAnnotationIntegration, useAnnotationKeyboardControls, useAudioTracks, useClipDragHandlers, useClipInteractionEnabled, useClipSplitting, useDragSensors, useDynamicEffects, useDynamicTracks, useExportWav, useKeyboardShortcuts, useMasterAnalyser, useMasterVolume, useMediaElementAnimation, useMediaElementControls, useMediaElementData, useMediaElementState, useOutputMeter, usePlaybackAnimation, usePlaybackShortcuts, usePlaylistControls, usePlaylistData, usePlaylistState, useSpectrogramIntegration, useTimeFormat, useTrackDynamicEffects, useZoomControls, waveformDataToPeaks };
|
|
1827
|
+
export { type ActiveEffect, type AnnotationIntegration, AnnotationIntegrationProvider, AudioPosition, type AudioTrackConfig, AutomaticScrollCheckbox, ClearAllButton, type ClearAllButtonProps, ClipCollisionModifier, ClipInteractionProvider, type ClipInteractionProviderProps, ContinuousPlayCheckbox, DownloadAnnotationsButton, EditableCheckbox, type EffectDefinition, type EffectInstance, type EffectParameter, type ExportOptions, type ExportResult, ExportWavButton, type ExportWavButtonProps, FastForwardButton, type FrameData, type GetAnnotationBoxLabelFn, KeyboardShortcuts, type KeyboardShortcutsProps, LinkEndpointsCheckbox, LoopButton, MasterVolumeControl, type MasterVolumeControls, type MediaElementAnimationContextValue, MediaElementAnnotationList, type MediaElementAnnotationListProps, type MediaElementControlsContextValue, type MediaElementDataContextValue, MediaElementPlaylist, type MediaElementPlaylistProps, MediaElementPlaylistProvider, type MediaElementStateContextValue, type MediaElementTrackConfig, MediaElementWaveform, type MediaElementWaveformProps, type OnAnnotationUpdateFn, type ParameterType, PauseButton, PlayButton, PlaylistAnnotationList, type PlaylistAnnotationListProps, PlaylistVisualization, type PlaylistVisualizationProps, RewindButton, SelectionTimeInputs, SetLoopRegionButton, SkipBackwardButton, SkipForwardButton, SnapToGridModifier, type SpectrogramIntegration, SpectrogramIntegrationProvider, StopButton, type TimeFormatControls, TimeFormatSelect, type TrackActiveEffect, type TrackEffectsState, type TrackLoadError, type TrackSource, type TrackState$1 as TrackState, type UseDynamicEffectsReturn, type UseDynamicTracksReturn, type UseExportWavReturn, type UseOutputMeterOptions, type UseOutputMeterReturn, type UsePlaybackShortcutsOptions, type UsePlaybackShortcutsReturn, type UseTrackDynamicEffectsReturn, Waveform, WaveformPlaylistProvider, type WaveformProps, type WaveformTrack, type ZoomControls, ZoomInButton, ZoomOutButton, createEffectChain, createEffectInstance, effectCategories, effectDefinitions, getEffectDefinition, getEffectsByCategory, getWaveformDataMetadata, loadPeaksFromWaveformData, loadWaveformData, noDropAnimationPlugins, useAnnotationDragHandlers, useAnnotationIntegration, useAnnotationKeyboardControls, useAudioTracks, useClipDragHandlers, useClipInteractionEnabled, useClipSplitting, useDragSensors, useDynamicEffects, useDynamicTracks, useExportWav, useKeyboardShortcuts, useMasterAnalyser, useMasterVolume, useMediaElementAnimation, useMediaElementControls, useMediaElementData, useMediaElementState, useOutputMeter, usePlaybackAnimation, usePlaybackShortcuts, usePlaylistControls, usePlaylistData, usePlaylistState, useSpectrogramIntegration, useTimeFormat, useTrackDynamicEffects, useZoomControls, waveformDataToPeaks };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,15 @@ interface TrackState$1 {
|
|
|
41
41
|
volume: number;
|
|
42
42
|
pan: number;
|
|
43
43
|
}
|
|
44
|
+
/** Per-frame data passed to registered animation callbacks. */
|
|
45
|
+
interface FrameData {
|
|
46
|
+
/** Raw engine time (for state/logic — NOT for visual positioning). */
|
|
47
|
+
readonly time: number;
|
|
48
|
+
/** time - outputLatency (for DOM positioning — matches speaker output). */
|
|
49
|
+
readonly visualTime: number;
|
|
50
|
+
readonly sampleRate: number;
|
|
51
|
+
readonly samplesPerPixel: number;
|
|
52
|
+
}
|
|
44
53
|
interface PlaybackAnimationContextValue {
|
|
45
54
|
isPlaying: boolean;
|
|
46
55
|
currentTime: number;
|
|
@@ -49,6 +58,10 @@ interface PlaybackAnimationContextValue {
|
|
|
49
58
|
audioStartPositionRef: React__default.RefObject<number>;
|
|
50
59
|
/** Returns current playback time from engine (auto-wraps at loop boundaries). */
|
|
51
60
|
getPlaybackTime: () => number;
|
|
61
|
+
/** Register a per-frame callback driven by the single animation loop. */
|
|
62
|
+
registerFrameCallback: (id: string, cb: (data: FrameData) => void) => void;
|
|
63
|
+
/** Unregister a per-frame callback. */
|
|
64
|
+
unregisterFrameCallback: (id: string) => void;
|
|
52
65
|
}
|
|
53
66
|
interface PlaylistStateContextValue {
|
|
54
67
|
continuousPlay: boolean;
|
|
@@ -1174,7 +1187,7 @@ declare const TimeFormatSelect: React__default.FC<{
|
|
|
1174
1187
|
}>;
|
|
1175
1188
|
/**
|
|
1176
1189
|
* Audio position display that uses the playlist context.
|
|
1177
|
-
*
|
|
1190
|
+
* Updates via the shared animation frame registry — no own rAF loop.
|
|
1178
1191
|
* Direct DOM manipulation avoids React re-renders.
|
|
1179
1192
|
*/
|
|
1180
1193
|
declare const AudioPosition: React__default.FC<{
|
|
@@ -1811,4 +1824,4 @@ declare function getWaveformDataMetadata(src: string): Promise<{
|
|
|
1811
1824
|
bits: 8 | 16;
|
|
1812
1825
|
}>;
|
|
1813
1826
|
|
|
1814
|
-
export { type ActiveEffect, type AnnotationIntegration, AnnotationIntegrationProvider, AudioPosition, type AudioTrackConfig, AutomaticScrollCheckbox, ClearAllButton, type ClearAllButtonProps, ClipCollisionModifier, ClipInteractionProvider, type ClipInteractionProviderProps, ContinuousPlayCheckbox, DownloadAnnotationsButton, EditableCheckbox, type EffectDefinition, type EffectInstance, type EffectParameter, type ExportOptions, type ExportResult, ExportWavButton, type ExportWavButtonProps, FastForwardButton, type GetAnnotationBoxLabelFn, KeyboardShortcuts, type KeyboardShortcutsProps, LinkEndpointsCheckbox, LoopButton, MasterVolumeControl, type MasterVolumeControls, type MediaElementAnimationContextValue, MediaElementAnnotationList, type MediaElementAnnotationListProps, type MediaElementControlsContextValue, type MediaElementDataContextValue, MediaElementPlaylist, type MediaElementPlaylistProps, MediaElementPlaylistProvider, type MediaElementStateContextValue, type MediaElementTrackConfig, MediaElementWaveform, type MediaElementWaveformProps, type OnAnnotationUpdateFn, type ParameterType, PauseButton, PlayButton, PlaylistAnnotationList, type PlaylistAnnotationListProps, PlaylistVisualization, type PlaylistVisualizationProps, RewindButton, SelectionTimeInputs, SetLoopRegionButton, SkipBackwardButton, SkipForwardButton, SnapToGridModifier, type SpectrogramIntegration, SpectrogramIntegrationProvider, StopButton, type TimeFormatControls, TimeFormatSelect, type TrackActiveEffect, type TrackEffectsState, type TrackLoadError, type TrackSource, type TrackState$1 as TrackState, type UseDynamicEffectsReturn, type UseDynamicTracksReturn, type UseExportWavReturn, type UseOutputMeterOptions, type UseOutputMeterReturn, type UsePlaybackShortcutsOptions, type UsePlaybackShortcutsReturn, type UseTrackDynamicEffectsReturn, Waveform, WaveformPlaylistProvider, type WaveformProps, type WaveformTrack, type ZoomControls, ZoomInButton, ZoomOutButton, createEffectChain, createEffectInstance, effectCategories, effectDefinitions, getEffectDefinition, getEffectsByCategory, getWaveformDataMetadata, loadPeaksFromWaveformData, loadWaveformData, noDropAnimationPlugins, useAnnotationDragHandlers, useAnnotationIntegration, useAnnotationKeyboardControls, useAudioTracks, useClipDragHandlers, useClipInteractionEnabled, useClipSplitting, useDragSensors, useDynamicEffects, useDynamicTracks, useExportWav, useKeyboardShortcuts, useMasterAnalyser, useMasterVolume, useMediaElementAnimation, useMediaElementControls, useMediaElementData, useMediaElementState, useOutputMeter, usePlaybackAnimation, usePlaybackShortcuts, usePlaylistControls, usePlaylistData, usePlaylistState, useSpectrogramIntegration, useTimeFormat, useTrackDynamicEffects, useZoomControls, waveformDataToPeaks };
|
|
1827
|
+
export { type ActiveEffect, type AnnotationIntegration, AnnotationIntegrationProvider, AudioPosition, type AudioTrackConfig, AutomaticScrollCheckbox, ClearAllButton, type ClearAllButtonProps, ClipCollisionModifier, ClipInteractionProvider, type ClipInteractionProviderProps, ContinuousPlayCheckbox, DownloadAnnotationsButton, EditableCheckbox, type EffectDefinition, type EffectInstance, type EffectParameter, type ExportOptions, type ExportResult, ExportWavButton, type ExportWavButtonProps, FastForwardButton, type FrameData, type GetAnnotationBoxLabelFn, KeyboardShortcuts, type KeyboardShortcutsProps, LinkEndpointsCheckbox, LoopButton, MasterVolumeControl, type MasterVolumeControls, type MediaElementAnimationContextValue, MediaElementAnnotationList, type MediaElementAnnotationListProps, type MediaElementControlsContextValue, type MediaElementDataContextValue, MediaElementPlaylist, type MediaElementPlaylistProps, MediaElementPlaylistProvider, type MediaElementStateContextValue, type MediaElementTrackConfig, MediaElementWaveform, type MediaElementWaveformProps, type OnAnnotationUpdateFn, type ParameterType, PauseButton, PlayButton, PlaylistAnnotationList, type PlaylistAnnotationListProps, PlaylistVisualization, type PlaylistVisualizationProps, RewindButton, SelectionTimeInputs, SetLoopRegionButton, SkipBackwardButton, SkipForwardButton, SnapToGridModifier, type SpectrogramIntegration, SpectrogramIntegrationProvider, StopButton, type TimeFormatControls, TimeFormatSelect, type TrackActiveEffect, type TrackEffectsState, type TrackLoadError, type TrackSource, type TrackState$1 as TrackState, type UseDynamicEffectsReturn, type UseDynamicTracksReturn, type UseExportWavReturn, type UseOutputMeterOptions, type UseOutputMeterReturn, type UsePlaybackShortcutsOptions, type UsePlaybackShortcutsReturn, type UseTrackDynamicEffectsReturn, Waveform, WaveformPlaylistProvider, type WaveformProps, type WaveformTrack, type ZoomControls, ZoomInButton, ZoomOutButton, createEffectChain, createEffectInstance, effectCategories, effectDefinitions, getEffectDefinition, getEffectsByCategory, getWaveformDataMetadata, loadPeaksFromWaveformData, loadWaveformData, noDropAnimationPlugins, useAnnotationDragHandlers, useAnnotationIntegration, useAnnotationKeyboardControls, useAudioTracks, useClipDragHandlers, useClipInteractionEnabled, useClipSplitting, useDragSensors, useDynamicEffects, useDynamicTracks, useExportWav, useKeyboardShortcuts, useMasterAnalyser, useMasterVolume, useMediaElementAnimation, useMediaElementControls, useMediaElementData, useMediaElementState, useOutputMeter, usePlaybackAnimation, usePlaybackShortcuts, usePlaylistControls, usePlaylistData, usePlaylistState, useSpectrogramIntegration, useTimeFormat, useTrackDynamicEffects, useZoomControls, waveformDataToPeaks };
|
package/dist/index.js
CHANGED
|
@@ -3822,6 +3822,7 @@ var WaveformPlaylistProvider = ({
|
|
|
3822
3822
|
const playbackEndTimeRef = (0, import_react24.useRef)(null);
|
|
3823
3823
|
const scrollContainerRef = (0, import_react24.useRef)(null);
|
|
3824
3824
|
const isAutomaticScrollRef = (0, import_react24.useRef)(false);
|
|
3825
|
+
const frameCallbacksRef = (0, import_react24.useRef)(/* @__PURE__ */ new Map());
|
|
3825
3826
|
const continuousPlayRef = (0, import_react24.useRef)((_d = annotationList == null ? void 0 : annotationList.isContinuousPlay) != null ? _d : false);
|
|
3826
3827
|
const activeAnnotationIdRef = (0, import_react24.useRef)(null);
|
|
3827
3828
|
const engineTracksRef = (0, import_react24.useRef)(null);
|
|
@@ -4282,10 +4283,30 @@ var WaveformPlaylistProvider = ({
|
|
|
4282
4283
|
const elapsed = (0, import_tone4.getContext)().currentTime - ((_a2 = playbackStartTimeRef.current) != null ? _a2 : 0);
|
|
4283
4284
|
return ((_b2 = audioStartPositionRef.current) != null ? _b2 : 0) + elapsed;
|
|
4284
4285
|
}, []);
|
|
4286
|
+
const registerFrameCallback = (0, import_react24.useCallback)((id, cb) => {
|
|
4287
|
+
frameCallbacksRef.current.set(id, cb);
|
|
4288
|
+
}, []);
|
|
4289
|
+
const unregisterFrameCallback = (0, import_react24.useCallback)((id) => {
|
|
4290
|
+
frameCallbacksRef.current.delete(id);
|
|
4291
|
+
}, []);
|
|
4285
4292
|
const startAnimationLoop = (0, import_react24.useCallback)(() => {
|
|
4293
|
+
const audioCtx = (0, import_playout5.getGlobalAudioContext)();
|
|
4286
4294
|
const updateTime = () => {
|
|
4287
4295
|
const time = getPlaybackTime();
|
|
4288
4296
|
currentTimeRef.current = time;
|
|
4297
|
+
const latency = "outputLatency" in audioCtx ? audioCtx.outputLatency : 0;
|
|
4298
|
+
const visualTime = Math.max(0, time - latency);
|
|
4299
|
+
const sr = sampleRateRef.current;
|
|
4300
|
+
const spp = samplesPerPixelRef.current;
|
|
4301
|
+
const frameData = {
|
|
4302
|
+
time,
|
|
4303
|
+
visualTime,
|
|
4304
|
+
sampleRate: sr,
|
|
4305
|
+
samplesPerPixel: spp
|
|
4306
|
+
};
|
|
4307
|
+
for (const cb of frameCallbacksRef.current.values()) {
|
|
4308
|
+
cb(frameData);
|
|
4309
|
+
}
|
|
4289
4310
|
const currentAnnotations = annotationsRef.current;
|
|
4290
4311
|
if (currentAnnotations.length > 0) {
|
|
4291
4312
|
const currentAnnotation = currentAnnotations.find(
|
|
@@ -4320,10 +4341,9 @@ var WaveformPlaylistProvider = ({
|
|
|
4320
4341
|
}
|
|
4321
4342
|
if (isAutomaticScrollRef.current && scrollContainerRef.current && duration > 0) {
|
|
4322
4343
|
const container = scrollContainerRef.current;
|
|
4323
|
-
const
|
|
4324
|
-
const pixelPosition = time * sr / samplesPerPixelRef.current;
|
|
4344
|
+
const pixelPosition = visualTime * sr / spp;
|
|
4325
4345
|
const containerWidth = container.clientWidth;
|
|
4326
|
-
const targetScrollLeft = Math.max(0, pixelPosition - containerWidth / 2);
|
|
4346
|
+
const targetScrollLeft = Math.round(Math.max(0, pixelPosition - containerWidth / 2));
|
|
4327
4347
|
container.scrollLeft = targetScrollLeft;
|
|
4328
4348
|
}
|
|
4329
4349
|
if (playbackEndTimeRef.current !== null && time >= playbackEndTimeRef.current) {
|
|
@@ -4559,7 +4579,9 @@ var WaveformPlaylistProvider = ({
|
|
|
4559
4579
|
currentTimeRef,
|
|
4560
4580
|
playbackStartTimeRef,
|
|
4561
4581
|
audioStartPositionRef,
|
|
4562
|
-
getPlaybackTime
|
|
4582
|
+
getPlaybackTime,
|
|
4583
|
+
registerFrameCallback,
|
|
4584
|
+
unregisterFrameCallback
|
|
4563
4585
|
}),
|
|
4564
4586
|
[
|
|
4565
4587
|
isPlaying,
|
|
@@ -4567,7 +4589,9 @@ var WaveformPlaylistProvider = ({
|
|
|
4567
4589
|
currentTimeRef,
|
|
4568
4590
|
playbackStartTimeRef,
|
|
4569
4591
|
audioStartPositionRef,
|
|
4570
|
-
getPlaybackTime
|
|
4592
|
+
getPlaybackTime,
|
|
4593
|
+
registerFrameCallback,
|
|
4594
|
+
unregisterFrameCallback
|
|
4571
4595
|
]
|
|
4572
4596
|
);
|
|
4573
4597
|
const stateValue = (0, import_react24.useMemo)(
|
|
@@ -5348,32 +5372,19 @@ var PositionDisplay = import_styled_components3.default.span`
|
|
|
5348
5372
|
var AudioPosition = ({ className }) => {
|
|
5349
5373
|
var _a;
|
|
5350
5374
|
const timeRef = (0, import_react27.useRef)(null);
|
|
5351
|
-
const
|
|
5352
|
-
const { isPlaying, currentTimeRef, getPlaybackTime } = usePlaybackAnimation();
|
|
5375
|
+
const { isPlaying, currentTimeRef, registerFrameCallback, unregisterFrameCallback } = usePlaybackAnimation();
|
|
5353
5376
|
const { timeFormat: format } = usePlaylistData();
|
|
5354
5377
|
(0, import_react27.useEffect)(() => {
|
|
5355
|
-
const
|
|
5356
|
-
var _a2;
|
|
5357
|
-
if (timeRef.current) {
|
|
5358
|
-
const time = isPlaying ? getPlaybackTime() : (_a2 = currentTimeRef.current) != null ? _a2 : 0;
|
|
5359
|
-
timeRef.current.textContent = (0, import_ui_components6.formatTime)(time, format);
|
|
5360
|
-
}
|
|
5361
|
-
if (isPlaying) {
|
|
5362
|
-
animationFrameRef.current = requestAnimationFrame(updateTime);
|
|
5363
|
-
}
|
|
5364
|
-
};
|
|
5378
|
+
const id = "audio-position";
|
|
5365
5379
|
if (isPlaying) {
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5380
|
+
registerFrameCallback(id, ({ time }) => {
|
|
5381
|
+
if (timeRef.current) {
|
|
5382
|
+
timeRef.current.textContent = (0, import_ui_components6.formatTime)(time, format);
|
|
5383
|
+
}
|
|
5384
|
+
});
|
|
5369
5385
|
}
|
|
5370
|
-
return () =>
|
|
5371
|
-
|
|
5372
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5373
|
-
animationFrameRef.current = null;
|
|
5374
|
-
}
|
|
5375
|
-
};
|
|
5376
|
-
}, [isPlaying, format, currentTimeRef, getPlaybackTime]);
|
|
5386
|
+
return () => unregisterFrameCallback(id);
|
|
5387
|
+
}, [isPlaying, format, registerFrameCallback, unregisterFrameCallback]);
|
|
5377
5388
|
(0, import_react27.useEffect)(() => {
|
|
5378
5389
|
var _a2;
|
|
5379
5390
|
if (!isPlaying && timeRef.current) {
|
|
@@ -5533,33 +5544,20 @@ var PlayheadLine = import_styled_components4.default.div.attrs((props) => ({
|
|
|
5533
5544
|
`;
|
|
5534
5545
|
var AnimatedPlayhead = ({ color = "#ff0000" }) => {
|
|
5535
5546
|
const playheadRef = (0, import_react30.useRef)(null);
|
|
5536
|
-
const
|
|
5537
|
-
const { isPlaying, currentTimeRef, getPlaybackTime } = usePlaybackAnimation();
|
|
5547
|
+
const { isPlaying, currentTimeRef, registerFrameCallback, unregisterFrameCallback } = usePlaybackAnimation();
|
|
5538
5548
|
const { samplesPerPixel, sampleRate, progressBarWidth } = usePlaylistData();
|
|
5539
5549
|
(0, import_react30.useEffect)(() => {
|
|
5540
|
-
const
|
|
5541
|
-
var _a;
|
|
5542
|
-
if (playheadRef.current) {
|
|
5543
|
-
const time = isPlaying ? getPlaybackTime() : (_a = currentTimeRef.current) != null ? _a : 0;
|
|
5544
|
-
const position = time * sampleRate / samplesPerPixel;
|
|
5545
|
-
playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;
|
|
5546
|
-
}
|
|
5547
|
-
if (isPlaying) {
|
|
5548
|
-
animationFrameRef.current = requestAnimationFrame(updatePosition);
|
|
5549
|
-
}
|
|
5550
|
-
};
|
|
5550
|
+
const id = "playhead";
|
|
5551
5551
|
if (isPlaying) {
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5552
|
+
registerFrameCallback(id, ({ visualTime, sampleRate: sr, samplesPerPixel: spp }) => {
|
|
5553
|
+
if (playheadRef.current) {
|
|
5554
|
+
const px = visualTime * sr / spp;
|
|
5555
|
+
playheadRef.current.style.transform = `translate3d(${px}px, 0, 0)`;
|
|
5556
|
+
}
|
|
5557
|
+
});
|
|
5555
5558
|
}
|
|
5556
|
-
return () =>
|
|
5557
|
-
|
|
5558
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5559
|
-
animationFrameRef.current = null;
|
|
5560
|
-
}
|
|
5561
|
-
};
|
|
5562
|
-
}, [isPlaying, sampleRate, samplesPerPixel, currentTimeRef, getPlaybackTime]);
|
|
5559
|
+
return () => unregisterFrameCallback(id);
|
|
5560
|
+
}, [isPlaying, registerFrameCallback, unregisterFrameCallback]);
|
|
5563
5561
|
(0, import_react30.useEffect)(() => {
|
|
5564
5562
|
var _a;
|
|
5565
5563
|
if (!isPlaying && playheadRef.current) {
|
|
@@ -5631,10 +5629,10 @@ var ChannelWithProgress = (_a) => {
|
|
|
5631
5629
|
"clipOffsetSeconds"
|
|
5632
5630
|
]);
|
|
5633
5631
|
const progressRef = (0, import_react31.useRef)(null);
|
|
5634
|
-
const
|
|
5632
|
+
const callbackId = (0, import_react31.useId)();
|
|
5635
5633
|
const theme = (0, import_ui_components8.useTheme)();
|
|
5636
5634
|
const { waveHeight } = (0, import_ui_components8.usePlaylistInfo)();
|
|
5637
|
-
const { isPlaying, currentTimeRef,
|
|
5635
|
+
const { isPlaying, currentTimeRef, registerFrameCallback, unregisterFrameCallback } = usePlaybackAnimation();
|
|
5638
5636
|
const { samplesPerPixel, sampleRate } = usePlaylistData();
|
|
5639
5637
|
const progressColor = (theme == null ? void 0 : theme.waveProgressColor) || "rgba(0, 0, 0, 0.1)";
|
|
5640
5638
|
const clipPixelWidth = (0, import_core6.clipPixelWidth)(
|
|
@@ -5643,46 +5641,32 @@ var ChannelWithProgress = (_a) => {
|
|
|
5643
5641
|
samplesPerPixel
|
|
5644
5642
|
);
|
|
5645
5643
|
(0, import_react31.useEffect)(() => {
|
|
5646
|
-
const updateProgress = () => {
|
|
5647
|
-
var _a2;
|
|
5648
|
-
if (progressRef.current) {
|
|
5649
|
-
const currentTime = isPlaying ? getPlaybackTime() : (_a2 = currentTimeRef.current) != null ? _a2 : 0;
|
|
5650
|
-
const currentSample = currentTime * sampleRate;
|
|
5651
|
-
const clipEndSample = clipStartSample + clipDurationSamples;
|
|
5652
|
-
let ratio = 0;
|
|
5653
|
-
if (currentSample <= clipStartSample) {
|
|
5654
|
-
ratio = 0;
|
|
5655
|
-
} else if (currentSample >= clipEndSample) {
|
|
5656
|
-
ratio = 1;
|
|
5657
|
-
} else {
|
|
5658
|
-
const playedSamples = currentSample - clipStartSample;
|
|
5659
|
-
ratio = playedSamples / clipDurationSamples;
|
|
5660
|
-
}
|
|
5661
|
-
progressRef.current.style.transform = `scaleX(${ratio})`;
|
|
5662
|
-
}
|
|
5663
|
-
if (isPlaying) {
|
|
5664
|
-
animationFrameRef.current = requestAnimationFrame(updateProgress);
|
|
5665
|
-
}
|
|
5666
|
-
};
|
|
5667
5644
|
if (isPlaying) {
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5645
|
+
registerFrameCallback(callbackId, ({ visualTime, sampleRate: sr }) => {
|
|
5646
|
+
if (progressRef.current) {
|
|
5647
|
+
const currentSample = visualTime * sr;
|
|
5648
|
+
const clipEndSample = clipStartSample + clipDurationSamples;
|
|
5649
|
+
let ratio = 0;
|
|
5650
|
+
if (currentSample <= clipStartSample) {
|
|
5651
|
+
ratio = 0;
|
|
5652
|
+
} else if (currentSample >= clipEndSample) {
|
|
5653
|
+
ratio = 1;
|
|
5654
|
+
} else {
|
|
5655
|
+
const playedSamples = currentSample - clipStartSample;
|
|
5656
|
+
ratio = playedSamples / clipDurationSamples;
|
|
5657
|
+
}
|
|
5658
|
+
progressRef.current.style.transform = `scaleX(${ratio})`;
|
|
5659
|
+
}
|
|
5660
|
+
});
|
|
5671
5661
|
}
|
|
5672
|
-
return () =>
|
|
5673
|
-
if (animationFrameRef.current) {
|
|
5674
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5675
|
-
animationFrameRef.current = null;
|
|
5676
|
-
}
|
|
5677
|
-
};
|
|
5662
|
+
return () => unregisterFrameCallback(callbackId);
|
|
5678
5663
|
}, [
|
|
5679
5664
|
isPlaying,
|
|
5680
|
-
sampleRate,
|
|
5681
5665
|
clipStartSample,
|
|
5682
5666
|
clipDurationSamples,
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5667
|
+
callbackId,
|
|
5668
|
+
registerFrameCallback,
|
|
5669
|
+
unregisterFrameCallback
|
|
5686
5670
|
]);
|
|
5687
5671
|
(0, import_react31.useEffect)(() => {
|
|
5688
5672
|
var _a2;
|