@shopify/react-native-skia 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/external/reanimated/useVideo.d.ts +2 -0
- package/lib/commonjs/external/reanimated/useVideo.js +16 -4
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.d.ts +2 -0
- package/lib/module/external/reanimated/useVideo.js +16 -4
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/typescript/src/external/reanimated/useVideo.d.ts +2 -0
- package/package.json +1 -1
- package/src/external/reanimated/useVideo.ts +20 -5
@@ -5,6 +5,8 @@ export interface PlaybackOptions {
|
|
5
5
|
playbackSpeed: Animated<number>;
|
6
6
|
looping: Animated<boolean>;
|
7
7
|
paused: Animated<boolean>;
|
8
|
+
seek: Animated<number | null>;
|
9
|
+
currentTime: Animated<number>;
|
8
10
|
}
|
9
11
|
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => SharedValue<SkImage | null>;
|
10
12
|
export {};
|
@@ -13,7 +13,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
13
13
|
const defaultOptions = {
|
14
14
|
playbackSpeed: 1,
|
15
15
|
looping: true,
|
16
|
-
paused: false
|
16
|
+
paused: false,
|
17
|
+
seek: null,
|
18
|
+
currentTime: 0
|
17
19
|
};
|
18
20
|
const useOption = value => {
|
19
21
|
"worklet";
|
@@ -23,10 +25,12 @@ const useOption = value => {
|
|
23
25
|
return _ReanimatedProxy.default.isSharedValue(value) ? value : defaultValue;
|
24
26
|
};
|
25
27
|
const useVideo = (source, userOptions) => {
|
26
|
-
var _userOptions$paused, _userOptions$looping, _userOptions$playback;
|
28
|
+
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$currentT, _userOptions$playback;
|
27
29
|
const video = (0, _react.useMemo)(() => source ? _Skia.Skia.Video(source) : null, [source]);
|
28
30
|
const isPaused = useOption((_userOptions$paused = userOptions === null || userOptions === void 0 ? void 0 : userOptions.paused) !== null && _userOptions$paused !== void 0 ? _userOptions$paused : defaultOptions.paused);
|
29
31
|
const looping = useOption((_userOptions$looping = userOptions === null || userOptions === void 0 ? void 0 : userOptions.looping) !== null && _userOptions$looping !== void 0 ? _userOptions$looping : defaultOptions.looping);
|
32
|
+
const seek = useOption((_userOptions$seek = userOptions === null || userOptions === void 0 ? void 0 : userOptions.seek) !== null && _userOptions$seek !== void 0 ? _userOptions$seek : defaultOptions.seek);
|
33
|
+
const currentTime = useOption((_userOptions$currentT = userOptions === null || userOptions === void 0 ? void 0 : userOptions.currentTime) !== null && _userOptions$currentT !== void 0 ? _userOptions$currentT : defaultOptions.currentTime);
|
30
34
|
const playbackSpeed = useOption((_userOptions$playback = userOptions === null || userOptions === void 0 ? void 0 : userOptions.playbackSpeed) !== null && _userOptions$playback !== void 0 ? _userOptions$playback : defaultOptions.playbackSpeed);
|
31
35
|
const currentFrame = _ReanimatedProxy.default.useSharedValue(null);
|
32
36
|
const lastTimestamp = _ReanimatedProxy.default.useSharedValue(-1);
|
@@ -43,6 +47,12 @@ const useVideo = (source, userOptions) => {
|
|
43
47
|
if (!video) {
|
44
48
|
return;
|
45
49
|
}
|
50
|
+
if (seek.value !== null) {
|
51
|
+
video.seek(seek.value);
|
52
|
+
seek.value = null;
|
53
|
+
lastTimestamp.value = -1;
|
54
|
+
startTimestamp.value = -1;
|
55
|
+
}
|
46
56
|
if (isPaused.value && lastTimestamp.value !== -1) {
|
47
57
|
return;
|
48
58
|
}
|
@@ -57,6 +67,7 @@ const useVideo = (source, userOptions) => {
|
|
57
67
|
|
58
68
|
// Calculate the current time in the video
|
59
69
|
const currentTimestamp = timestamp - startTimestamp.value;
|
70
|
+
currentTime.value = currentTimestamp;
|
60
71
|
|
61
72
|
// Handle looping
|
62
73
|
if (currentTimestamp > duration && looping.value) {
|
@@ -65,8 +76,9 @@ const useVideo = (source, userOptions) => {
|
|
65
76
|
}
|
66
77
|
|
67
78
|
// Update frame only if the elapsed time since last update is greater than the frame duration
|
68
|
-
const currentFrameDuration = frameDuration / playbackSpeed.value;
|
69
|
-
|
79
|
+
const currentFrameDuration = Math.floor(frameDuration / playbackSpeed.value);
|
80
|
+
const delta = Math.floor(timestamp - lastTimestamp.value);
|
81
|
+
if (lastTimestamp.value === -1 || delta >= currentFrameDuration) {
|
70
82
|
const img = video.nextImage();
|
71
83
|
if (img) {
|
72
84
|
if (currentFrame.value) {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["_reactNativeReanimated","require","_react","_Skia","_Platform","_ReanimatedProxy","_interopRequireDefault","obj","__esModule","default","defaultOptions","playbackSpeed","looping","paused","useOption","value","defaultValue","useSharedValue","Rea","isSharedValue","useVideo","source","userOptions","_userOptions$paused","_userOptions$looping","_userOptions$playback","video","useMemo","Skia","Video","isPaused","currentFrame","lastTimestamp","startTimestamp","framerate","duration","frameDuration","disposeVideo","useCallback","dispose","useFrameCallback","frameInfo","timestamp","currentTimestamp","
|
1
|
+
{"version":3,"names":["_reactNativeReanimated","require","_react","_Skia","_Platform","_ReanimatedProxy","_interopRequireDefault","obj","__esModule","default","defaultOptions","playbackSpeed","looping","paused","seek","currentTime","useOption","value","defaultValue","useSharedValue","Rea","isSharedValue","useVideo","source","userOptions","_userOptions$paused","_userOptions$looping","_userOptions$seek","_userOptions$currentT","_userOptions$playback","video","useMemo","Skia","Video","isPaused","currentFrame","lastTimestamp","startTimestamp","framerate","duration","frameDuration","disposeVideo","useCallback","dispose","useFrameCallback","frameInfo","timestamp","currentTimestamp","currentFrameDuration","Math","floor","delta","img","nextImage","Platform","OS","makeNonTextureImage","useEffect","runOnUI","exports"],"sources":["useVideo.ts"],"sourcesContent":["import {\n runOnUI,\n useSharedValue,\n type FrameInfo,\n type SharedValue,\n} from \"react-native-reanimated\";\nimport { useCallback, useEffect, useMemo } from \"react\";\n\nimport { Skia } from \"../../skia/Skia\";\nimport type { SkImage } from \"../../skia/types\";\nimport { Platform } from \"../../Platform\";\n\nimport Rea from \"./ReanimatedProxy\";\n\ntype Animated<T> = SharedValue<T> | T;\n\nexport interface PlaybackOptions {\n playbackSpeed: Animated<number>;\n looping: Animated<boolean>;\n paused: Animated<boolean>;\n seek: Animated<number | null>;\n currentTime: Animated<number>;\n}\n\nconst defaultOptions = {\n playbackSpeed: 1,\n looping: true,\n paused: false,\n seek: null,\n currentTime: 0,\n};\n\nconst useOption = <T>(value: Animated<T>) => {\n \"worklet\";\n // TODO: only create defaultValue is needed (via makeMutable)\n const defaultValue = useSharedValue(\n Rea.isSharedValue(value) ? value.value : value\n );\n return Rea.isSharedValue(value) ? value : defaultValue;\n};\n\nexport const useVideo = (\n source: string | null,\n userOptions?: Partial<PlaybackOptions>\n) => {\n const video = useMemo(() => (source ? Skia.Video(source) : null), [source]);\n const isPaused = useOption(userOptions?.paused ?? defaultOptions.paused);\n const looping = useOption(userOptions?.looping ?? defaultOptions.looping);\n const seek = useOption(userOptions?.seek ?? defaultOptions.seek);\n const currentTime = useOption(\n userOptions?.currentTime ?? defaultOptions.currentTime\n );\n const playbackSpeed = useOption(\n userOptions?.playbackSpeed ?? defaultOptions.playbackSpeed\n );\n const currentFrame = Rea.useSharedValue<null | SkImage>(null);\n const lastTimestamp = Rea.useSharedValue(-1);\n const startTimestamp = Rea.useSharedValue(-1);\n\n const framerate = useMemo(() => (video ? video.framerate() : -1), [video]);\n const duration = useMemo(() => (video ? video.duration() : -1), [video]);\n const frameDuration = useMemo(\n () => (framerate > 0 ? 1000 / framerate : -1),\n [framerate]\n );\n const disposeVideo = useCallback(() => {\n \"worklet\";\n video?.dispose();\n }, [video]);\n\n Rea.useFrameCallback((frameInfo: FrameInfo) => {\n if (!video) {\n return;\n }\n if (seek.value !== null) {\n video.seek(seek.value);\n seek.value = null;\n lastTimestamp.value = -1;\n startTimestamp.value = -1;\n }\n if (isPaused.value && lastTimestamp.value !== -1) {\n return;\n }\n const { timestamp } = frameInfo;\n\n // Initialize start timestamp\n if (startTimestamp.value === -1) {\n startTimestamp.value = timestamp;\n }\n\n // Calculate the current time in the video\n const currentTimestamp = timestamp - startTimestamp.value;\n currentTime.value = currentTimestamp;\n\n // Handle looping\n if (currentTimestamp > duration && looping.value) {\n video.seek(0);\n startTimestamp.value = timestamp;\n }\n\n // Update frame only if the elapsed time since last update is greater than the frame duration\n const currentFrameDuration = Math.floor(\n frameDuration / playbackSpeed.value\n );\n const delta = Math.floor(timestamp - lastTimestamp.value);\n if (lastTimestamp.value === -1 || delta >= currentFrameDuration) {\n const img = video.nextImage();\n if (img) {\n if (currentFrame.value) {\n currentFrame.value.dispose();\n }\n if (Platform.OS === \"android\") {\n currentFrame.value = img.makeNonTextureImage();\n } else {\n currentFrame.value = img;\n }\n }\n lastTimestamp.value = timestamp;\n }\n });\n\n useEffect(() => {\n return () => {\n // TODO: should video simply be a shared value instead?\n runOnUI(disposeVideo)();\n };\n }, [disposeVideo, video]);\n\n return currentFrame;\n};\n"],"mappings":"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"}
|
@@ -5,6 +5,8 @@ export interface PlaybackOptions {
|
|
5
5
|
playbackSpeed: Animated<number>;
|
6
6
|
looping: Animated<boolean>;
|
7
7
|
paused: Animated<boolean>;
|
8
|
+
seek: Animated<number | null>;
|
9
|
+
currentTime: Animated<number>;
|
8
10
|
}
|
9
11
|
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => SharedValue<SkImage | null>;
|
10
12
|
export {};
|
@@ -6,7 +6,9 @@ import Rea from "./ReanimatedProxy";
|
|
6
6
|
const defaultOptions = {
|
7
7
|
playbackSpeed: 1,
|
8
8
|
looping: true,
|
9
|
-
paused: false
|
9
|
+
paused: false,
|
10
|
+
seek: null,
|
11
|
+
currentTime: 0
|
10
12
|
};
|
11
13
|
const useOption = value => {
|
12
14
|
"worklet";
|
@@ -16,10 +18,12 @@ const useOption = value => {
|
|
16
18
|
return Rea.isSharedValue(value) ? value : defaultValue;
|
17
19
|
};
|
18
20
|
export const useVideo = (source, userOptions) => {
|
19
|
-
var _userOptions$paused, _userOptions$looping, _userOptions$playback;
|
21
|
+
var _userOptions$paused, _userOptions$looping, _userOptions$seek, _userOptions$currentT, _userOptions$playback;
|
20
22
|
const video = useMemo(() => source ? Skia.Video(source) : null, [source]);
|
21
23
|
const isPaused = useOption((_userOptions$paused = userOptions === null || userOptions === void 0 ? void 0 : userOptions.paused) !== null && _userOptions$paused !== void 0 ? _userOptions$paused : defaultOptions.paused);
|
22
24
|
const looping = useOption((_userOptions$looping = userOptions === null || userOptions === void 0 ? void 0 : userOptions.looping) !== null && _userOptions$looping !== void 0 ? _userOptions$looping : defaultOptions.looping);
|
25
|
+
const seek = useOption((_userOptions$seek = userOptions === null || userOptions === void 0 ? void 0 : userOptions.seek) !== null && _userOptions$seek !== void 0 ? _userOptions$seek : defaultOptions.seek);
|
26
|
+
const currentTime = useOption((_userOptions$currentT = userOptions === null || userOptions === void 0 ? void 0 : userOptions.currentTime) !== null && _userOptions$currentT !== void 0 ? _userOptions$currentT : defaultOptions.currentTime);
|
23
27
|
const playbackSpeed = useOption((_userOptions$playback = userOptions === null || userOptions === void 0 ? void 0 : userOptions.playbackSpeed) !== null && _userOptions$playback !== void 0 ? _userOptions$playback : defaultOptions.playbackSpeed);
|
24
28
|
const currentFrame = Rea.useSharedValue(null);
|
25
29
|
const lastTimestamp = Rea.useSharedValue(-1);
|
@@ -36,6 +40,12 @@ export const useVideo = (source, userOptions) => {
|
|
36
40
|
if (!video) {
|
37
41
|
return;
|
38
42
|
}
|
43
|
+
if (seek.value !== null) {
|
44
|
+
video.seek(seek.value);
|
45
|
+
seek.value = null;
|
46
|
+
lastTimestamp.value = -1;
|
47
|
+
startTimestamp.value = -1;
|
48
|
+
}
|
39
49
|
if (isPaused.value && lastTimestamp.value !== -1) {
|
40
50
|
return;
|
41
51
|
}
|
@@ -50,6 +60,7 @@ export const useVideo = (source, userOptions) => {
|
|
50
60
|
|
51
61
|
// Calculate the current time in the video
|
52
62
|
const currentTimestamp = timestamp - startTimestamp.value;
|
63
|
+
currentTime.value = currentTimestamp;
|
53
64
|
|
54
65
|
// Handle looping
|
55
66
|
if (currentTimestamp > duration && looping.value) {
|
@@ -58,8 +69,9 @@ export const useVideo = (source, userOptions) => {
|
|
58
69
|
}
|
59
70
|
|
60
71
|
// Update frame only if the elapsed time since last update is greater than the frame duration
|
61
|
-
const currentFrameDuration = frameDuration / playbackSpeed.value;
|
62
|
-
|
72
|
+
const currentFrameDuration = Math.floor(frameDuration / playbackSpeed.value);
|
73
|
+
const delta = Math.floor(timestamp - lastTimestamp.value);
|
74
|
+
if (lastTimestamp.value === -1 || delta >= currentFrameDuration) {
|
63
75
|
const img = video.nextImage();
|
64
76
|
if (img) {
|
65
77
|
if (currentFrame.value) {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["runOnUI","useSharedValue","useCallback","useEffect","useMemo","Skia","Platform","Rea","defaultOptions","playbackSpeed","looping","paused","useOption","value","defaultValue","isSharedValue","useVideo","source","userOptions","_userOptions$paused","_userOptions$looping","_userOptions$playback","video","Video","isPaused","currentFrame","lastTimestamp","startTimestamp","framerate","duration","frameDuration","disposeVideo","dispose","useFrameCallback","frameInfo","timestamp","currentTimestamp","
|
1
|
+
{"version":3,"names":["runOnUI","useSharedValue","useCallback","useEffect","useMemo","Skia","Platform","Rea","defaultOptions","playbackSpeed","looping","paused","seek","currentTime","useOption","value","defaultValue","isSharedValue","useVideo","source","userOptions","_userOptions$paused","_userOptions$looping","_userOptions$seek","_userOptions$currentT","_userOptions$playback","video","Video","isPaused","currentFrame","lastTimestamp","startTimestamp","framerate","duration","frameDuration","disposeVideo","dispose","useFrameCallback","frameInfo","timestamp","currentTimestamp","currentFrameDuration","Math","floor","delta","img","nextImage","OS","makeNonTextureImage"],"sources":["useVideo.ts"],"sourcesContent":["import {\n runOnUI,\n useSharedValue,\n type FrameInfo,\n type SharedValue,\n} from \"react-native-reanimated\";\nimport { useCallback, useEffect, useMemo } from \"react\";\n\nimport { Skia } from \"../../skia/Skia\";\nimport type { SkImage } from \"../../skia/types\";\nimport { Platform } from \"../../Platform\";\n\nimport Rea from \"./ReanimatedProxy\";\n\ntype Animated<T> = SharedValue<T> | T;\n\nexport interface PlaybackOptions {\n playbackSpeed: Animated<number>;\n looping: Animated<boolean>;\n paused: Animated<boolean>;\n seek: Animated<number | null>;\n currentTime: Animated<number>;\n}\n\nconst defaultOptions = {\n playbackSpeed: 1,\n looping: true,\n paused: false,\n seek: null,\n currentTime: 0,\n};\n\nconst useOption = <T>(value: Animated<T>) => {\n \"worklet\";\n // TODO: only create defaultValue is needed (via makeMutable)\n const defaultValue = useSharedValue(\n Rea.isSharedValue(value) ? value.value : value\n );\n return Rea.isSharedValue(value) ? value : defaultValue;\n};\n\nexport const useVideo = (\n source: string | null,\n userOptions?: Partial<PlaybackOptions>\n) => {\n const video = useMemo(() => (source ? Skia.Video(source) : null), [source]);\n const isPaused = useOption(userOptions?.paused ?? defaultOptions.paused);\n const looping = useOption(userOptions?.looping ?? defaultOptions.looping);\n const seek = useOption(userOptions?.seek ?? defaultOptions.seek);\n const currentTime = useOption(\n userOptions?.currentTime ?? defaultOptions.currentTime\n );\n const playbackSpeed = useOption(\n userOptions?.playbackSpeed ?? defaultOptions.playbackSpeed\n );\n const currentFrame = Rea.useSharedValue<null | SkImage>(null);\n const lastTimestamp = Rea.useSharedValue(-1);\n const startTimestamp = Rea.useSharedValue(-1);\n\n const framerate = useMemo(() => (video ? video.framerate() : -1), [video]);\n const duration = useMemo(() => (video ? video.duration() : -1), [video]);\n const frameDuration = useMemo(\n () => (framerate > 0 ? 1000 / framerate : -1),\n [framerate]\n );\n const disposeVideo = useCallback(() => {\n \"worklet\";\n video?.dispose();\n }, [video]);\n\n Rea.useFrameCallback((frameInfo: FrameInfo) => {\n if (!video) {\n return;\n }\n if (seek.value !== null) {\n video.seek(seek.value);\n seek.value = null;\n lastTimestamp.value = -1;\n startTimestamp.value = -1;\n }\n if (isPaused.value && lastTimestamp.value !== -1) {\n return;\n }\n const { timestamp } = frameInfo;\n\n // Initialize start timestamp\n if (startTimestamp.value === -1) {\n startTimestamp.value = timestamp;\n }\n\n // Calculate the current time in the video\n const currentTimestamp = timestamp - startTimestamp.value;\n currentTime.value = currentTimestamp;\n\n // Handle looping\n if (currentTimestamp > duration && looping.value) {\n video.seek(0);\n startTimestamp.value = timestamp;\n }\n\n // Update frame only if the elapsed time since last update is greater than the frame duration\n const currentFrameDuration = Math.floor(\n frameDuration / playbackSpeed.value\n );\n const delta = Math.floor(timestamp - lastTimestamp.value);\n if (lastTimestamp.value === -1 || delta >= currentFrameDuration) {\n const img = video.nextImage();\n if (img) {\n if (currentFrame.value) {\n currentFrame.value.dispose();\n }\n if (Platform.OS === \"android\") {\n currentFrame.value = img.makeNonTextureImage();\n } else {\n currentFrame.value = img;\n }\n }\n lastTimestamp.value = timestamp;\n }\n });\n\n useEffect(() => {\n return () => {\n // TODO: should video simply be a shared value instead?\n runOnUI(disposeVideo)();\n };\n }, [disposeVideo, video]);\n\n return currentFrame;\n};\n"],"mappings":"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"}
|
@@ -5,6 +5,8 @@ export interface PlaybackOptions {
|
|
5
5
|
playbackSpeed: Animated<number>;
|
6
6
|
looping: Animated<boolean>;
|
7
7
|
paused: Animated<boolean>;
|
8
|
+
seek: Animated<number | null>;
|
9
|
+
currentTime: Animated<number>;
|
8
10
|
}
|
9
11
|
export declare const useVideo: (source: string | null, userOptions?: Partial<PlaybackOptions>) => SharedValue<SkImage | null>;
|
10
12
|
export {};
|
package/package.json
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
"setup-skia-web": "./scripts/setup-canvaskit.js"
|
8
8
|
},
|
9
9
|
"title": "React Native Skia",
|
10
|
-
"version": "1.3.
|
10
|
+
"version": "1.3.1",
|
11
11
|
"description": "High-performance React Native Graphics using Skia",
|
12
12
|
"main": "lib/module/index.js",
|
13
13
|
"react-native": "src/index.ts",
|
@@ -18,12 +18,16 @@ export interface PlaybackOptions {
|
|
18
18
|
playbackSpeed: Animated<number>;
|
19
19
|
looping: Animated<boolean>;
|
20
20
|
paused: Animated<boolean>;
|
21
|
+
seek: Animated<number | null>;
|
22
|
+
currentTime: Animated<number>;
|
21
23
|
}
|
22
24
|
|
23
25
|
const defaultOptions = {
|
24
26
|
playbackSpeed: 1,
|
25
27
|
looping: true,
|
26
28
|
paused: false,
|
29
|
+
seek: null,
|
30
|
+
currentTime: 0,
|
27
31
|
};
|
28
32
|
|
29
33
|
const useOption = <T>(value: Animated<T>) => {
|
@@ -42,6 +46,10 @@ export const useVideo = (
|
|
42
46
|
const video = useMemo(() => (source ? Skia.Video(source) : null), [source]);
|
43
47
|
const isPaused = useOption(userOptions?.paused ?? defaultOptions.paused);
|
44
48
|
const looping = useOption(userOptions?.looping ?? defaultOptions.looping);
|
49
|
+
const seek = useOption(userOptions?.seek ?? defaultOptions.seek);
|
50
|
+
const currentTime = useOption(
|
51
|
+
userOptions?.currentTime ?? defaultOptions.currentTime
|
52
|
+
);
|
45
53
|
const playbackSpeed = useOption(
|
46
54
|
userOptions?.playbackSpeed ?? defaultOptions.playbackSpeed
|
47
55
|
);
|
@@ -64,6 +72,12 @@ export const useVideo = (
|
|
64
72
|
if (!video) {
|
65
73
|
return;
|
66
74
|
}
|
75
|
+
if (seek.value !== null) {
|
76
|
+
video.seek(seek.value);
|
77
|
+
seek.value = null;
|
78
|
+
lastTimestamp.value = -1;
|
79
|
+
startTimestamp.value = -1;
|
80
|
+
}
|
67
81
|
if (isPaused.value && lastTimestamp.value !== -1) {
|
68
82
|
return;
|
69
83
|
}
|
@@ -76,6 +90,7 @@ export const useVideo = (
|
|
76
90
|
|
77
91
|
// Calculate the current time in the video
|
78
92
|
const currentTimestamp = timestamp - startTimestamp.value;
|
93
|
+
currentTime.value = currentTimestamp;
|
79
94
|
|
80
95
|
// Handle looping
|
81
96
|
if (currentTimestamp > duration && looping.value) {
|
@@ -84,11 +99,11 @@ export const useVideo = (
|
|
84
99
|
}
|
85
100
|
|
86
101
|
// Update frame only if the elapsed time since last update is greater than the frame duration
|
87
|
-
const currentFrameDuration =
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
) {
|
102
|
+
const currentFrameDuration = Math.floor(
|
103
|
+
frameDuration / playbackSpeed.value
|
104
|
+
);
|
105
|
+
const delta = Math.floor(timestamp - lastTimestamp.value);
|
106
|
+
if (lastTimestamp.value === -1 || delta >= currentFrameDuration) {
|
92
107
|
const img = video.nextImage();
|
93
108
|
if (img) {
|
94
109
|
if (currentFrame.value) {
|